タイムゾーンに注意
日付オブジェクトを使用して日付をすぐに表すと、非常に大きな精度の問題が発生します。あなたはそれらを締め出すために時間とタイムゾーンを管理する必要があり、彼らはどの段階でも忍び込むことができます。この質問への受け入れられた答えは罠に陥ります。
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())
date1 === date2
は一貫した動作を提供するようには見えないことに注意してください。それを行うdate1.valueOf() === b.valueOf()
か、さらに良いdate1.getTime() === date2.getTime()
です。奇妙さ。