HATI-HATI WAKTU
Menggunakan objek tanggal untuk mewakili hanya-kencan langsung membuat Anda menjadi masalah presisi berlebih besar. Anda perlu mengatur waktu dan zona waktu untuk mencegahnya, dan mereka dapat menyelinap masuk kembali pada langkah apa pun. Jawaban yang diterima untuk pertanyaan ini jatuh ke dalam jebakan.
Tanggal javascript tidak memiliki gagasan tentang zona waktu . Ini adalah momen waktu (kutu sejak zamannya) dengan fungsi praktis (statis) untuk menerjemahkan ke dan dari string, menggunakan secara default zona waktu "lokal" pada perangkat, atau, jika ditentukan, UTC atau zona waktu lainnya. Untuk mewakili just-a-date ™ dengan objek tanggal, Anda ingin tanggal Anda mewakili UTC tengah malam pada awal tanggal tersebut. Ini adalah konvensi umum dan perlu yang memungkinkan Anda bekerja dengan tanggal terlepas dari musim atau zona waktu pembuatannya. Jadi, Anda harus sangat waspada untuk mengelola gagasan tentang zona waktu, baik saat Anda membuat objek Date UTC tengah malam Anda, dan ketika Anda membuat cerita bersambung.
Banyak orang bingung dengan perilaku default konsol. Jika Anda menyemprotkan tanggal ke konsol, output yang Anda lihat akan mencakup zona waktu Anda. Ini hanya karena konsol memanggil toString()
tanggal Anda, dan toString()
memberi Anda representasi lokal. Tanggal yang mendasarinya tidak memiliki zona waktu ! (Selama waktu cocok dengan offset zona waktu, Anda masih memiliki objek tanggal UTC tengah malam)
Deserializing (atau membuat objek Date UTC tengah malam)
Ini adalah langkah pembulatan, dengan trik bahwa ada dua jawaban "benar". Sebagian besar waktu, Anda ingin agar tanggal mencerminkan zona waktu pengguna. Klik jika hari ini adalah hari ulang tahun Anda . Pengguna di NZ dan AS mengklik pada waktu yang sama dan mendapatkan tanggal yang berbeda. Dalam hal ini, lakukan ini ...
// 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()));
Terkadang, perbandingan internasional mengalahkan akurasi lokal. Dalam hal ini, lakukan ini ...
// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));
Deserialize tanggal
Seringkali tanggal pada kawat akan berada dalam format YYYY-MM-DD. Untuk menghilangkan bakteri mereka, lakukan ini ...
var midnightUTCDate = new Date( dateString + 'T00:00:00Z');
Serialisasi
Setelah berhati-hati mengelola zona waktu saat Anda membuat, Anda sekarang harus memastikan untuk tidak menggunakan zona waktu saat Anda mengonversi kembali ke representasi string. Jadi Anda bisa menggunakan ...
toISOString()
getUTCxxx()
getTime() //returns a number with no time or timezone.
.toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.
Dan benar-benar menghindari yang lainnya, terutama ...
getYear()
, getMonth()
,getDate()
Jadi untuk menjawab pertanyaan Anda, 7 tahun terlambat ...
<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>
Lihat sedang berjalan ...
Perbarui 2019 ... barang gratis ...
Mengingat popularitas jawaban ini, saya telah memasukkan semuanya ke dalam kode. Fungsi berikut mengembalikan objek tanggal yang dibungkus, dan hanya memaparkan fungsi-fungsi yang aman digunakan dengan just-a-date ™.
Sebut dengan objek Tanggal dan itu akan memutuskan untuk JustADate yang mencerminkan zona waktu pengguna. Sebut dengan string: jika string adalah ISO 8601 dengan zona waktu yang ditentukan, kami hanya akan mengakhiri bagian waktu. Jika zona waktu tidak ditentukan, kami akan mengonversinya menjadi tanggal yang mencerminkan zona waktu lokal, seperti halnya untuk objek tanggal.
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
tampaknya tidak memberikan perilaku yang konsisten; lebih baik dilakukandate1.valueOf() === b.valueOf()
atau bahkandate1.getTime() === date2.getTime()
. Keanehan.