XEM THỜI GIAN
Sử dụng đối tượng ngày để thể hiện ngay một ngày ngay lập tức sẽ đưa bạn vào một vấn đề chính xác vượt quá lớn. Bạn cần quản lý thời gian và múi giờ để tránh xa họ và họ có thể quay lại bất cứ lúc nào. Câu trả lời được chấp nhận cho câu hỏi này rơi vào bẫy.
Một ngày javascript không có khái niệm về múi giờ . Đó là một khoảnh khắc thời gian (tích tắc kể từ thời đại) với các chức năng (tĩnh) tiện dụng để dịch sang và từ các chuỗi, theo mặc định sử dụng múi giờ "cục bộ" của thiết bị hoặc, nếu được chỉ định, UTC hoặc múi giờ khác. Để thể hiện chỉ một ngày ™ với một đối tượng ngày, bạn muốn ngày của bạn đại diện cho nửa đêm UTC vào đầu ngày được đề cập. Đây là một quy ước phổ biến và cần thiết cho phép bạn làm việc với các ngày bất kể mùa hoặc múi giờ sáng tạo của họ. Vì vậy, bạn cần hết sức cảnh giác để quản lý khái niệm múi giờ, cả khi bạn tạo đối tượng Ngày UTC nửa đêm và khi bạn tuần tự hóa nó.
Rất nhiều người bối rối bởi hành vi mặc định của giao diện điều khiển. Nếu bạn phun một ngày vào bảng điều khiển, đầu ra bạn nhìn thấy sẽ bao gồm múi giờ của bạn. Điều này chỉ là do bảng điều khiển gọi toString()
vào ngày của bạn và toString()
cung cấp cho bạn sự hồi phục cục bộ. Ngày cơ bản không có múi giờ ! (Miễn là thời gian khớp với thời gian bù, bạn vẫn có một đối tượng ngày UTC nửa đêm)
Giải trừ (hoặc tạo các đối tượng Ngày UTC nửa đêm)
Đây là bước làm tròn, với mẹo có hai câu trả lời "đúng". Hầu hết thời gian, bạn sẽ muốn ngày của bạn phản ánh múi giờ của người dùng. Nhấp vào nếu hôm nay là sinh nhật của bạn . Người dùng ở New Zealand và Mỹ nhấp vào cùng một lúc và nhận được các ngày khác nhau. Trong trường hợp đó, hãy làm điều này ...
// 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()));
Đôi khi, so sánh quốc tế hơn hẳn độ chính xác địa phương. Trong trường hợp đó, hãy làm điều này ...
// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));
Hủy bỏ một ngày
Thông thường ngày trên dây sẽ có định dạng YYYY-MM-DD. Để giải trừ chúng, hãy làm điều này ...
var midnightUTCDate = new Date( dateString + 'T00:00:00Z');
Nối tiếp
Đã cẩn thận để quản lý múi giờ khi bạn tạo, bây giờ bạn cần chắc chắn giữ hết múi giờ khi bạn chuyển đổi trở lại thành một chuỗi đại diện. Vì vậy, bạn có thể sử dụng một cách an toàn ...
toISOString()
getUTCxxx()
getTime() //returns a number with no time or timezone.
.toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.
Và hoàn toàn tránh mọi thứ khác, đặc biệt là ...
getYear()
, getMonth()
,getDate()
Vì vậy, để trả lời câu hỏi của bạn, 7 năm quá muộn ...
<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>
Thấy nó chạy ...
Cập nhật 2019 ... công cụ miễn phí ...
Với sự phổ biến của câu trả lời này, tôi đã đặt tất cả vào mã. Hàm sau trả về một đối tượng ngày được bao bọc và chỉ hiển thị các chức năng an toàn để sử dụng với chỉ một ngày ™.
Gọi nó với một đối tượng Date và nó sẽ phân giải thành JustADate phản ánh múi giờ của người dùng. Gọi nó bằng một chuỗi: nếu chuỗi là ISO 8601 với múi giờ được chỉ định, chúng ta sẽ làm tròn phần thời gian. Nếu múi giờ không được chỉ định, chúng tôi sẽ chuyển đổi nó thành ngày phản ánh múi giờ địa phương, giống như đối với các đối tượng ngày.
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
dường như không cung cấp hành vi nhất quán; tốt hơn là làmdate1.valueOf() === b.valueOf()
hoặc thậm chídate1.getTime() === date2.getTime()
. Lạ thay.