ระวังไทม์โซน
การใช้ออบเจ็กต์วันที่เพื่อแสดงถึงวันที่จะทำให้คุณกลายเป็นปัญหาความแม่นยำที่มากเกินไป คุณต้องจัดการเวลาและเขตเวลาเพื่อให้พวกเขาออกไปและพวกเขาสามารถแอบเข้าไปในขั้นตอนใด ๆ คำตอบที่ยอมรับสำหรับคำถามนี้ตกหลุมพราง
วันที่จาวาสคริปต์มี ความคิดของการไม่มีการเขต มันเป็นช่วงเวลาในเวลา (เห็บตั้งแต่ยุค) ที่มีฟังก์ชั่นที่มีประโยชน์ (คงที่) สำหรับการแปลไปยังและจากสตริงการใช้ตามค่าเริ่มต้นเขตเวลา "ท้องถิ่น" ของอุปกรณ์หรือถ้าระบุ UTC หรือเขตเวลาอื่น ในการแสดง just-a-date ™พร้อมวัตถุวันที่คุณต้องการให้วันที่ของคุณเป็นตัวแทน UTC เที่ยงคืนที่จุดเริ่มต้นของวันที่เป็นปัญหา นี่เป็นแบบแผนทั่วไปและจำเป็นที่ช่วยให้คุณทำงานกับวันที่โดยไม่คำนึงถึงฤดูกาลหรือเขตเวลาของการสร้าง ดังนั้นคุณต้องมีความระมัดระวังในการจัดการความคิดของเขตเวลาทั้งเมื่อคุณสร้างวัตถุ UTC Date เที่ยงคืนและเมื่อคุณทำให้เป็นอนุกรม
ผู้คนจำนวนมากสับสนโดยพฤติกรรมเริ่มต้นของคอนโซล หากคุณสเปรย์วันที่ไปยังคอนโซลเอาต์พุตที่คุณเห็นจะรวมเขตเวลาของคุณ นี่เป็นเพียงเพราะคอนโซลโทรถึงtoString()
วันที่ของคุณและtoString()
ให้การตอบโต้ในพื้นที่ของคุณ วันที่พื้นฐานไม่มีเขตเวลา ! (ตราบใดที่เวลาตรงกับเขตเวลาชดเชยคุณยังคงมีวัตถุวันที่เที่ยงคืน UTC)
Deserializing (หรือสร้างวัตถุ UTC Date เที่ยงคืน)
นี่คือขั้นตอนการปัดเศษด้วยเคล็ดลับที่มีสองคำตอบ "ถูกต้อง" ส่วนใหญ่คุณจะต้องการวันที่ของคุณเพื่อสะท้อนเขตเวลาของผู้ใช้ คลิกถ้าวันนี้เป็นวันเกิดของคุณคลิกที่ถ้าวันนี้เป็นวันเกิดของคุณผู้ใช้ในนิวซีแลนด์และสหรัฐอเมริกาคลิกในเวลาเดียวกันและรับวันที่แตกต่างกัน ในกรณีนี้ให้ทำ ...
// 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');
serializing
ตอนนี้คุณต้องแน่ใจว่าได้จัดการเขตเวลาเมื่อคุณแปลงกลับไปเป็นตัวแทนสตริง ดังนั้นคุณสามารถใช้ ...
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 ™
เรียกว่ามีวัตถุวันที่และจะแก้ไขให้ 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()
ความไม่ชอบมาพากล