JavaScriptで時間を比較せずに日付部分のみを比較する


397

以下のコードの何が問題になっていますか?

たぶん、日付ではなく時間を比較する方が簡単でしょう。どうすればいいのかわからないので検索しましたが、正確な問題が見つかりませんでした。

ところで、2つの日付をアラートに表示すると、まったく同じように表示されます。

私のコード:

window.addEvent('domready', function() {
    var now = new Date();
    var input = $('datum').getValue();
    var dateArray = input.split('/');
    var userMonth = parseInt(dateArray[1])-1;
    var userDate = new Date();
    userDate.setFullYear(dateArray[2], userMonth, dateArray[0], now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds());

    if (userDate > now)
    {
        alert(now + '\n' + userDate);
    }
});

時間を含めずに日付を比較する簡単な方法はありますか?

回答:


781

私はまだJavaScriptを学習しています。時間なしで2つの日付を比較するために機能する唯一のsetHours方法は、Dateオブジェクトのメソッドを使用して、時間、分、秒、ミリ秒をゼロに設定することです。次に、2つの日付を比較します。

例えば、

date1 = new Date()
date2 = new Date(2011,8,20)

date2時、分、秒、ミリ秒をゼロに設定しますが、date1はそれらをdate1が作成された時刻に設定します。date1の時間、分、秒、ミリ秒を取り除くには、次のようにします。

date1.setHours(0,0,0,0)

これで、時間要素を気にすることなく、2つの日付をDATESとしてのみ比較できます。


63
によるテストdate1 === date2は一貫した動作を提供するようには見えないことに注意してください。それを行うdate1.valueOf() === b.valueOf()か、さらに良いdate1.getTime() === date2.getTime()です。奇妙さ。
アーウィンウェッセルズ2013年

4
注意:date1とdate2が冬と夏にあり、addDays(1)を使用して一方から他方に反復することを計画している場合、問題は夏時間のためにそれらが同じタイムゾーンを持たないことです。 2つの日付が実際には00:00:00:0ではないため、等しい日付を与えるはずの比較は機能しません。
オリバー

9
これは古い質問であることは知っていますが、Googleで検索すると最初に出てきます。この回答には注意してください。これは、ユーザーが日付オブジェクトの作成者と同じタイムゾーンにいない場合、誤った回答を返します。たとえば、コンピュータのOSのタイムゾーンを東海岸(米国)の時刻に変更します。ブラウザのコンソールを開き、と入力しvar date2 = new Date(2011,8,20)ます。次に、OSのタイムゾーンを太平洋標準時(米国)に変更します。同じブラウザコンソールタイプdate2.toDateString()Mon Sep 19 2011、20日の火曜日ではなく戻ってきます!
アダム

9
またsetHours()、ブラウザが自動的に検出した現在のタイムゾーンに基づいて時刻を設定することにも注意してください。試してみてください:28 t = new Date("2016-02-29T01:45:49.098Z"); t.setHours(0,0,0,0); console.log(t.toJSON());は印刷されますが"2016-02-28T15:00:00.000Z"、29 は印刷されません現在のタイムゾーンはAsia/Tokyo
2016

8
この回答setUTCxxxは、ローカル/タイムゾーン対応のバリアントの代わりにメソッドを使用するように更新する必要があります。
Stijn de Witt

136

タイムゾーンに注意

日付オブジェクトを使用して日付をすぐに表すと、非常に大きな精度の問題が発生します。あなたはそれらを締め出すために時間とタイムゾーンを管理する必要があり、彼らはどの段階でも忍び込むことができます。この質問への受け入れられた答えは罠に陥ります。

JavaScriptの日付にはタイムゾーンの概念はありません。これは、デフォルトでデバイスの「ローカル」タイムゾーン、または指定されている場合はUTCまたは別のタイムゾーンを使用して、文字列との間で変換するための便利な(静的)関数を備えた瞬間(エポック以降のティック)です。日付オブジェクトを使用してjust-a-date™ を表すには、問題の日付の開始日の真夜中のUTCを日付に表す必要があります。これは、作成の季節やタイムゾーンに関係なく日付を操作できるようにする一般的かつ必要な規則です。したがって、午前0時のUTC Dateオブジェクトを作成するときとシリアル化するときの両方で、タイムゾーンの概念を管理するために非常に警戒する必要があります。

多くの人々はコンソールのデフォルトの振る舞いに混乱しています。日付をコンソールにスプレーすると、表示される出力にはタイムゾーンが含まれます。これは、コンソールがtoString()あなたの日付を呼び出して、toString()あなたに地元の代表を与えるからです。基になる日付にはタイムゾーンがありません!(時間がタイムゾーンのオフセットと一致している限り、午前0時のUTC日付オブジェクトがまだあります)

逆シリアル化(または真夜中のUTC Dateオブジェクトの作成)

これは丸めのステップであり、2つの「正しい」答えがあるというトリックがあります。ほとんどの場合、日付にはユーザーのタイムゾーンを反映させる必要があります。今日がお誕生日の場合はクリックしてください。ニュージーランドと米国のユーザーが同時にクリックすると、日付が異なります。その場合、これを行います...

// create a date (utc midnight) reflecting the value of myDate and the environment's timezone offset.
new Date(Date.UTC(myDate.getFullYear(),myDate.getMonth(), myDate.getDate()));

時には、国際的な比較可能性が地域の正確さよりも優先されます。その場合、これを行います...

// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));

日付を逆シリアル化する

多くの場合、回線上の日付はYYYY-MM-DDの形式になります。それらをデシリアライズするには、次のようにします...

var midnightUTCDate = new Date( dateString + 'T00:00:00Z');

シリアライズ

作成時にタイムゾーンの管理に注意を払ったので、文字列表現に変換するときにタイムゾーンを確実に除外する必要があります。安全に使用できます...

  • toISOString()
  • getUTCxxx()
  • getTime() //returns a number with no time or timezone.
  • .toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.

そして、他のすべてを完全に避けてください、特に...

  • getYear()getMonth()getDate()

だからあなたの質問に答えるには、7年遅すぎる...

<input type="date" onchange="isInPast(event)">
<script>
var isInPast = function(event){
  var userEntered = new Date(event.target.valueAsNumber); // valueAsNumber has no time or timezone!
  var now = new Date();
  var today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() ));
  if(userEntered.getTime() < today.getTime())
    alert("date is past");
  else if(userEntered.getTime() == today.getTime())
    alert("date is today");
  else
    alert("date is future");

}
</script>

それが走っているのを見てください...

2019を更新...無料のもの...

この回答の人気を考慮して、私はそれをすべてコードに入れました。以下の関数はラップされた日付オブジェクトを返し、just-a-date™で安全に使用できる関数のみを公開します。

Dateオブジェクトを使用して呼び出し、ユーザーのタイムゾーンを反映するJustADateに解決します。文字列を指定して呼び出します。文字列がISO 8601でタイムゾーンが指定されている場合は、時間の部分を丸めます。タイムゾーンが指定されていない場合は、日付オブジェクトと同様に、ローカルタイムゾーンを反映する日付に変換します。

function JustADate(initDate){
  var utcMidnightDateObj = null
  // if no date supplied, use Now.
  if(!initDate)
    initDate = new Date();

  // if initDate specifies a timezone offset, or is already UTC, just keep the date part, reflecting the date _in that timezone_
  if(typeof initDate === "string" && initDate.match(/((\+|-)\d{2}:\d{2}|Z)$/gm)){  
     utcMidnightDateObj = new Date( initDate.substring(0,10) + 'T00:00:00Z');
  } else {
    // if init date is not already a date object, feed it to the date constructor.
    if(!(initDate instanceof Date))
      initDate = new Date(initDate);
      // Vital Step! Strip time part. Create UTC midnight dateObj according to local timezone.
      utcMidnightDateObj = new Date(Date.UTC(initDate.getFullYear(),initDate.getMonth(), initDate.getDate()));
  }

  return {
    toISOString:()=>utcMidnightDateObj.toISOString(),
    getUTCDate:()=>utcMidnightDateObj.getUTCDate(),
    getUTCDay:()=>utcMidnightDateObj.getUTCDay(),
    getUTCFullYear:()=>utcMidnightDateObj.getUTCFullYear(),
    getUTCMonth:()=>utcMidnightDateObj.getUTCMonth(),
    setUTCDate:(arg)=>utcMidnightDateObj.setUTCDate(arg),
    setUTCFullYear:(arg)=>utcMidnightDateObj.setUTCFullYear(arg),
    setUTCMonth:(arg)=>utcMidnightDateObj.setUTCMonth(arg),
    addDays:(days)=>{
      utcMidnightDateObj.setUTCDate(utcMidnightDateObj.getUTCDate + days)
    },
    toString:()=>utcMidnightDateObj.toString(),
    toLocaleDateString:(locale,options)=>{
      options = options || {};
      options.timezone = "UTC";
      locale = locale || "en-EN";
      return utcMidnightDateObj.toLocaleDateString(locale,options)
    }
  }
}


// if initDate already has a timezone, we'll just use the date part directly
console.log(JustADate('1963-11-22T12:30:00-06:00').toLocaleDateString())


3
あなたの答えには本当に貴重な情報が含まれています!残念ながら、OPの実際の質問に実際に回答を追加しなかったため、私はそれを支持できませんでした。OPの質問に答える小さなコードスニペットを追加してみてください。
Stijn de Witt

ハハハ@「7年は遅すぎる」!私はあなたのスタイルuser1585345が好きです!あなたは私の投票を獲得しました!
Stijn de Witt

これは役に立ちました。「国際比較可能性」スニペットにタイプミスがあることに注意してください。私はそれがあるべきだと思います:new Date(Date.UTC(myDate.getUTCFullYear()、myDate.getUTCMonth()、myDate.getUTCDate()));
RikRak 2018年

1
この回答に100回賛成できるといいのですが。
Sнаđошƒаӽ

77

これはどう?

Date.prototype.withoutTime = function () {
    var d = new Date(this);
    d.setHours(0, 0, 0, 0);
    return d;
}

これにより、変数の値に影響を与えることなく、次のように日付の日付部分を比較できます。

var date1 = new Date(2014,1,1);
new Date().withoutTime() > date1.withoutTime(); // true

これは、元の投稿に対する最も優雅な答えです。私は目的のために別個の関数を作成せず、2行のコードを含めただけです。
Danimal Reks

25

Moment.jsの使用

サードパーティのライブラリを含めるオプションがある場合は、Moment.jsを確認する価値があります。それはでの作業になりDateそしてDateTimeずっと、はるかに簡単。

たとえば、ある日付が別の日付の後に来るかどうかを確認しますが、それらの時間を除外するには、次のようにします。

var date1 = new Date(2016,9,20,12,0,0); // October 20, 2016 12:00:00
var date2 = new Date(2016,9,20,12,1,0); // October 20, 2016 12:01:00

// Comparison including time.
moment(date2).isAfter(date1); // => true

// Comparison excluding time.
moment(date2).isAfter(date1, 'day'); // => false

あなたに渡す2番目のパラメータは、isAfter比較を行うための精度であるとのいずれかとすることができるyearmonthweekdayhourminuteまたはsecond


4
momentjsソリューションからDate()+ sethoursソリューションに100倍高速化しました。注意深い友人:-)
2c2c 2017

@ 2c2c興味深い。パフォーマンスへの影響を知るのは間違いなく良いことです。ベンチマークに使用した操作はいくつですか。
Joshua Pinter 2017

1
私は約1milの比較でした。実際のベンチマークを設定し
なかった

17

以下のように.toDateStringを使用して比較するだけです:

new Date().toDateString();

次のように、これは日付部分のみを返し、時間やタイムゾーンは返しません。

「2017年2月3日金曜日」

したがって、両方の日付は、時間の部分なしで同様にこの形式で比較できます。


2
これは良いスタートですが、現在は文字列であるため、比較はできません。比較するには、次のようにしてDateオブジェクトに戻します new Date(new Date().toDateString());
Grid Trekkor

@GridTrekkor真ですが、簡単な等価テストが必要な場合は、これが最も簡単なソリューションです。
CM

8

これは少しわかりやすいバージョンかもしれませんが、parseIntを使用するときは常に基数を使用する必要があることにも注意してください。

window.addEvent('domready', function() {
    // Create a Date object set to midnight on today's date
    var today = new Date((new Date()).setHours(0, 0, 0, 0)),
    input = $('datum').getValue(),
    dateArray = input.split('/'),
    // Always specify a radix with parseInt(), setting the radix to 10 ensures that
    // the number is interpreted as a decimal.  It is particularly important with
    // dates, if the user had entered '09' for the month and you don't use a
    // radix '09' is interpreted as an octal number and parseInt would return 0, not 9!
    userMonth = parseInt(dateArray[1], 10) - 1,
    // Create a Date object set to midnight on the day the user specified
    userDate = new Date(dateArray[2], userMonth, dateArray[0], 0, 0, 0, 0);

    // Convert date objects to milliseconds and compare
    if(userDate.getTime() > today.getTime())
    {
            alert(today+'\n'+userDate);
    }
});

基数の詳細については、MDC parseIntページを確認してください。

JSLintは、基数の欠落など、不明瞭でデバッグが困難なエラーの原因となる可能性のある多くのものをキャッチするための優れたツールです。それはあなたがより良いコーディング標準を使うことを強いるので将来の頭痛を避けることができます。私がコーディングするすべてのJavaScriptプロジェクトで使用します。


@EmKayこれは、ES5がほとんどのブラウザーでかなり標準であり、8進解釈を禁止しいるので、それほど大きな問題ではないはずです。近い将来のために。
役に立たないコード

厳密モードを使用する場合、8進解釈はエラーをスローします。これは、誤って解釈される可能性のあるエラーを見つけるのに役立つため、これは良いことです。
役に立たないコード


4

時間コンポーネントなしで日付のみを本当に比較している場合、間違っているように感じるかもしれないがすべてのDate()時間とタイムゾーンの問題を回避する別のソリューションは、文字列比較を使用してISO文字列の日付を直接比較することです。

> "2019-04-22" <= "2019-04-23"
true
> "2019-04-22" <= "2019-04-22"
true
> "2019-04-22" <= "2019-04-21"
false
> "2019-04-22" === "2019-04-22"
true

次を使用して、現在の日付(UTC日付、必ずしもユーザーのローカル日付ではない)を取得できます。

> new Date().toISOString().split("T")[0]
"2019-04-22"

それを支持する私の議論は、プログラマーの単純さです-おそらく、速度を犠牲にして、日時とオフセットを正しく処理しようとするよりも、これを失敗する可能性ははるかに低くなります(パフォーマンスを比較していません)。


あなたも行うことができますnew Date().toISOString().substr(0, 10) // "2019-04-22"
ストーマ

ローカル日付(UTC以外の日付)にはを使用できますnew Date().toLocaleDateString() // "8/26/2019"。ただし、テキストの比較は正確ではありません("8/26/2019" >= "9/29/2001"falseなど)。したがってnew Date(new Date().toLocaleDateString())、別の日付と正確に比較するには、それを変換する必要があります。
ストーマ

4

両方の日付でtoDateString()を使用するだけです。toDateStringには時刻が含まれていないため、以下に示すように、同じ日付の2回の場合、値は等しくなります。

var d1 = new Date(2019,01,01,1,20)
var d2 = new Date(2019,01,01,2,20)
console.log(d1==d2) // false
console.log(d1.toDateString() == d2.toDateString()) // true

明らかに、この質問の他の箇所で述べられているタイムゾーンの懸念のいくつかは有効ですが、多くのシナリオでは、それらは関係ありません。


1
私の場合、この解決策は選択した回答や投票数の多い回答よりもはるかに優れています。タイトルでは「時間を比較せずに」と明示されていますが、このソリューションは正確にそうするため、比較を操作する時間を設定する必要がありません。「イベントXとイベントYは同じ日に発生しました」と答えるには、「イベントXの日付の00:00:00.00 AMが00:00とまったく同じである:」と答えるよりも、日付のみを比較する方が理にかなっています。イベントYの00.00?」これは他の多くの回答者が行っていることです
Mr.K

3

これは私がそれをする方法です:

var myDate  = new Date($('input[name=frequency_start]').val()).setHours(0,0,0,0);
var today   = new Date().setHours(0,0,0,0);
if(today>myDate){
    jAlert('Please Enter a date in the future','Date Start Error', function(){
        $('input[name=frequency_start]').focus().select();
    });
}

私は現在これを本番環境で使用しており、問題やブラウザの非互換性などはありません...なぜそれgetTime()が必要と言われているのですか?
Fabrizio 2013年

5
setHours()が呼び出されたオブジェクトを変更し、ミリ秒数として日付を返すことに注意してください(を呼び出すのと同じgetTime()です)。したがって、today変数はDate一部の人が予想するようなオブジェクトではありませんが、実際にはミリ秒の整数です。副作用として、これはgetTime()比較する前に呼び出す必要がなかった理由です。
ティモシーウォルターズ

3

ここでは同様のアプローチは見られず、h / m / s / msを0に設定することを楽しんでいないdateので、オブジェクトが変更されたローカルタイムゾーンへの正確な移行で問題が発生する可能性があります(そうだと思います)。少し前に書いた、lil関数をここに紹介します。

+:使いやすく、基本的な比較操作を実行します(日、月、年を時間なしで比較します)。
-これは、「すぐに使える」考え方とは正反対のようです。

function datecompare(date1, sign, date2) {
    var day1 = date1.getDate();
    var mon1 = date1.getMonth();
    var year1 = date1.getFullYear();
    var day2 = date2.getDate();
    var mon2 = date2.getMonth();
    var year2 = date2.getFullYear();
    if (sign === '===') {
        if (day1 === day2 && mon1 === mon2 && year1 === year2) return true;
        else return false;
    }
    else if (sign === '>') {
        if (year1 > year2) return true;
        else if (year1 === year2 && mon1 > mon2) return true;
        else if (year1 === year2 && mon1 === mon2 && day1 > day2) return true;
        else return false;
    }    
}

使用法:

datecompare(date1, '===', date2)等価性チェック、
datecompare(date1, '>', date2)より大きいチェック、
!datecompare(date1, '>', date2)より小さいか等しいチェック

また、明らかに、あなたは切り替えることができますdate1し、date2場所で、他の単純な比較を達成するために。


素敵な1つに加えて、プラスが私を助けてくれました。
エデンコルビン

3

日付を比較する効率的で正しい方法は次のとおりです。

Math.floor(date1.getTime() / 86400000) > Math.floor(date2.getTime() / 86400000);

時間の部分は無視され、さまざまなタイムゾーンで機能し、同等かどうかを比較すること==もできます。86400000は、1日のミリ秒数(= 24*60*60*1000)です。

等価演算子==は2つのDateオブジェクトを比較している(そして2つの日付を比較していない)ため、等価テストが機能すると予想される場合は失敗するため、Dateオブジェクトの比較には決して使用しないでください。

> date1;
outputs: Thu Mar 08 2018 00:00:00 GMT+1300

> date2;
outputs: Thu Mar 08 2018 00:00:00 GMT+1300

> date1 == date2;
outputs: false

> Math.floor(date1.getTime() / 86400000) == Math.floor(date2.getTime() / 86400000);
outputs: true

注:時間部分がゼロに設定されているDateオブジェクトを比較する場合は、使用できますdate1.getTime() == date2.getTime()が、最適化する価値はほとんどありません。あなたは使用することができ<><=、または>=これらの演算子が最初に呼び出すことで、Dateオブジェクトを変換するため、日付を比較すると、オブジェクトを直接とき.valueOf()、オペレータは、比較を行う前に。


2

この質問が投稿されてからまったく同じ時期に読んだ後、少なくとも私のニーズには十分満足できるものではなかったため、別の解決策を投稿することにしました。

私はこのようなものを使用しました:

var currentDate= new Date().setHours(0,0,0,0);

var startDay = new Date(currentDate - 86400000 * 2);
var finalDay = new Date(currentDate + 86400000 * 2);

このようにして、後で処理したい形式で日付を使用することができます。しかし、これは私の必要性のためだけでした、しかし私はとにかくそれを投稿することに決めました、多分それは誰かを助けるでしょう


1
currentDate変数は日付ではなく、1970-01-01からのミリ秒数であることに注意してください。このsetHours()メソッドは、呼び出された日付オブジェクトを変更し、getTime()(1970-01-01以降のミリ秒単位の日付の値)に相当するものを返します。
ティモシーウォルターズ


1

合計msの演算を使用できます。

var date = new Date(date1);
date.setHours(0, 0, 0, 0);

var diff = date2.getTime() - date.getTime();
return diff >= 0 && diff < 86400000;

元の日付への更新は行われず、文字列の分割と比較よりも高速であるため、これが好きです。

この助けを願っています!


1

このJSは設定された日付の後でコンテンツを変更します。これ は同じことですが、w3schoolsで行われます

date1 = new Date()
date2 = new Date(2019,5,2) //the date you are comparing

date1.setHours(0,0,0,0)

var stockcnt = document.getElementById('demo').innerHTML;
if (date1 > date2){
document.getElementById('demo').innerHTML="yes"; //change if date is > set date (date2)
}else{
document.getElementById('demo').innerHTML="hello"; //change if date is < set date (date2)
}
<p id="demo">hello</p> <!--What will be changed-->
<!--if you check back in tomorrow, it will say yes instead of hello... or you could change the date... or change > to <-->


1

これは私にとってはうまくいきます:

 export default (chosenDate) => {
  const now = new Date();
  const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
  const splitChosenDate = chosenDate.split('/');

  today.setHours(0, 0, 0, 0);
  const fromDate = today.getTime();
  const toDate = new Date(splitChosenDate[2], splitChosenDate[1] - 1, splitChosenDate[0]).getTime();

  return toDate < fromDate;
};

受け入れられた回答では、タイムゾーンの問題があり、他の時間では00:00:00ではありません


0

私はこの質問にすでに回答しており、これが最善の方法ではないかもしれないことを知っていますが、私のシナリオでは完全に機能するため、私のような人を助けることができると思いました。

あなたが持っているdate stringなら

String dateString="2018-01-01T18:19:12.543";

そして、日付部分をJSの別のDateオブジェクトと比較したいだけです

var anotherDate=new Date(); //some date

あなたがする必要がありますに使用して、オブジェクトconvertstringDatenew Date("2018-01-01T18:19:12.543");

そしてここにトリックがあります:-

var valueDate =new Date(new Date(dateString).toDateString());

            return valueDate.valueOf() == anotherDate.valueOf(); //here is the final result

私が使用しているtoDateString()Date object唯一の日付文字列を返しますJSの。

注:.valueOf()日付を比較しながら関数を使用することを忘れないでください。

詳細.valeOf()はこちら参照

ハッピーコード。


0

これは役立ちます。私はなんとかこのようにそれを得ました。

var currentDate = new Date(new Date().getFullYear(), new Date().getMonth() , new Date().getDate())

0

と比較するsetHours()ことがソリューションになります。サンプル:

var d1 = new Date();
var d2 = new Date("2019-2-23");
if(d1.setHours(0,0,0,0) == d2.setHours(0,0,0,0)){
    console.log(true)
}else{
    console.log(false)
}

0
var fromdate = new Date(MM/DD/YYYY);
var todate = new Date(MM/DD/YYYY);
if (fromdate > todate){
    console.log('False');
}else{
    console.log('True');
}

日付形式が異なる場合は、moment.jsライブラリを使用して日付の形式を変換し、上記のコードを使用して2つの日付を比較します

例:

あなたの日付が「DD / MM / YYYY」にあり、それを「MM / DD / YYYY」に変換したい場合は、以下のコード例を参照してください

var newfromdate = new Date(moment(fromdate, "DD/MM/YYYY").format("MM/DD/YYYY"));
console.log(newfromdate);
var newtodate = new Date(moment(todate, "DD/MM/YYYY").format("MM/DD/YYYY"));
console.log(newtodate);

0

fp_incr(0)を使用できます。タイムゾーンの部分を真夜中に設定し、日付オブジェクトを返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.