新聞中心
標(biāo)準(zhǔn)化時(shí)間
標(biāo)準(zhǔn)化時(shí)間是指使用一套公認(rèn)的標(biāo)準(zhǔn)來(lái)表示和衡量時(shí)間的方法。這種標(biāo)準(zhǔn)化使得不同地區(qū)和系統(tǒng)之間能夠統(tǒng)一地解讀和比較時(shí)間。目前最常用的標(biāo)準(zhǔn)化時(shí)間系統(tǒng)是協(xié)調(diào)世界時(shí)(Coordinated Universal Time,簡(jiǎn)稱UTC)。UTC 是基于原子鐘的國(guó)際標(biāo)準(zhǔn)時(shí)間,被廣泛應(yīng)用于全球各個(gè)領(lǐng)域,包括科學(xué)、航空、計(jì)算機(jī)網(wǎng)絡(luò)等。

成都創(chuàng)新互聯(lián)公司業(yè)務(wù)包括:成品網(wǎng)站、企業(yè)產(chǎn)品展示型網(wǎng)站建設(shè)、高端網(wǎng)站設(shè)計(jì)、電子商務(wù)型網(wǎng)站建設(shè)、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)(多語(yǔ)言)、商城網(wǎng)站定制開(kāi)發(fā)、定制網(wǎng)站設(shè)計(jì)、網(wǎng)絡(luò)營(yíng)銷推廣等。效率優(yōu)先,品質(zhì)保證,用心服務(wù)是我們的核心價(jià)值觀,我們將繼續(xù)以良好的信譽(yù)為基礎(chǔ),秉承穩(wěn)固與發(fā)展、求實(shí)與創(chuàng)新的精神,為客戶提供更全面、更優(yōu)質(zhì)的互聯(lián)網(wǎng)服務(wù)!
在 Web 應(yīng)用中,只要知道用戶所在的時(shí)區(qū),就可以隨時(shí)轉(zhuǎn)換、展示時(shí)間。如果知道用戶當(dāng)?shù)氐臅r(shí)間和時(shí)區(qū),就可以將其轉(zhuǎn)換為 UTC。計(jì)算機(jī)中的時(shí)間采用 ISO 日期格式,它是 ISO-8601 擴(kuò)展格式的簡(jiǎn)化版本,如下所示:
日期/時(shí)間操作
下面先來(lái)看看如何使用 JavaScript 進(jìn)行日期/時(shí)間操作。
Date對(duì)象
Date 對(duì)象基于 Unix Time Stamp,即自 1970 年 1 月 1 日(UTC)起經(jīng)過(guò)的毫秒數(shù)。其語(yǔ)法如下:
new Date();
new Date(value);
new Date(dateString);
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);注意, 創(chuàng)建一個(gè)新Date對(duì)象的唯一方法是通過(guò) new 操作符,例如:let now = new Date(); 若將它作為常規(guī)函數(shù)調(diào)用(即不加 new 操作符),將返回一個(gè)字符串,而非 Date 對(duì)象。
獲取當(dāng)前時(shí)間
const currentDate = new Date();如果不向 Date 構(gòu)造函數(shù)傳遞任何內(nèi)容,則返回的日期對(duì)象就是當(dāng)前的日期和時(shí)間。然后,就可以將其格式化為僅提取日期部分,如下所示:
const currentDate = new Date();
const currentDayOfMonth = currentDate.getDate();
const currentMonth = currentDate.getMonth();
const currentYear = currentDate.getFullYear();
const dateString = currentDayOfMonth + "-" + (currentMonth + 1) + "-" + currentYear;
// '4-7-2023'需要注意,月份是從 0 開(kāi)始的,一月就是 0,依此類推。
獲取當(dāng)前時(shí)間戳
可以創(chuàng)建一個(gè)新的 Date 對(duì)象并使用 getTime() 方法來(lái)獲取當(dāng)前時(shí)間戳:
const currentDate = new Date();
const timestamp = currentDate.getTime();在 JavaScript 中,時(shí)間戳是自 1970 年 1 月 1 日以來(lái)經(jīng)過(guò)的毫秒數(shù)。如果不需要支持
解析日期
可以通過(guò)不同的方式將字符串轉(zhuǎn)換為 JavaScript 日期對(duì)象。Date 對(duì)象的構(gòu)造函數(shù)接受多種日期格式:
const date1 = new Date("Wed, 27 July 2016 13:30:00");
const date2 = new Date("Wed, 27 July 2016 07:45:00 UTC");
const date3 = new Date("27 July 2016 13:30:00 UTC+05:45");需要注意,這里字符串不需要包含星期幾,因?yàn)?JS 可以確定任何日期是星期幾。
我們還可以傳入年、月、日、小時(shí)、分鐘和秒作為單獨(dú)的參數(shù):
const date = new Date(2016, 6, 27, 13, 30, 0);當(dāng)然,也可以使用 ISO 日期格式:
const date = new Date("2016-07-27T07:45:00Z");但是,如果不明確提供時(shí)區(qū),就會(huì)有問(wèn)題:
const date1 = new Date("25 July 2016");
const date2 = new Date("July 25, 2016");
date1 === date2; // false這兩個(gè)都會(huì)展示當(dāng)?shù)貢r(shí)間 2016 年 7 月 25 日 00:00:00,但是兩者是不相等的。
如果使用 ISO 格式,即使只提供日期而不提供時(shí)間和時(shí)區(qū),它也會(huì)自動(dòng)接受時(shí)區(qū)為 UTC。
new Date("25 July 2016").getTime() !== new Date("2016-07-25").getTime()
new Date("2016-07-25").getTime() === new Date("2016-07-25T00:00:00Z").getTime()
設(shè)置日期格式
現(xiàn)代 JavaScript 在標(biāo)準(zhǔn)命名空間中內(nèi)置了一些方便的國(guó)際化函數(shù)Intl,使日期格式化變得簡(jiǎn)單。
為此,我們需要兩個(gè)對(duì)象:Date 和 Intl.DateTimeFormat,并使用輸出首選項(xiàng)進(jìn)行初始化。假設(shè)想使用美國(guó) (M/D/YYYY) 格式,則如下所示:
const firstValentineOfTheDecade = new Date(2020, 1, 14);
const enUSFormatter = new Intl.DateTimeFormat('en-US');
console.log(enUSFormatter.format(firstValentineOfTheDecade));
// 2/14/2020如果想要荷蘭 (D/M/YYYY) 格式,只需將不同的區(qū)域性代碼傳遞給 DateTimeFormat 構(gòu)造函數(shù)即可:
const nlBEFormatter = new Intl.DateTimeFormat('nl-BE');
console.log(nlBEFormatter.format(firstValentineOfTheDecade));
// 14/2/2020或者美國(guó)格式的較長(zhǎng)形式,并拼寫出月份名稱:
const longEnUSFormatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
console.log(longEnUSFormatter.format(firstValentineOfTheDecade));
// February 14, 2020
更改日期格式
我們知道了如何解析日期并對(duì)其進(jìn)行格式化,將日期從一種格式更改為另一種格式只需將兩者結(jié)合起來(lái)即可。
例如,如果日期格式為 Jul 21, 2013,并且想要將格式更改為 21-07-2013,可以這樣實(shí)現(xiàn):
const myDate = new Date("Jul 21, 2013");
const dayOfMonth = myDate.getDate();
const month = myDate.getMonth();
const year = myDate.getFullYear();
function pad(n) {
return n<10 ? '0'+n : n
}
const ddmmyyyy = pad(dayOfMonth) + "-" + pad(month + 1) + "-" + year;
// "21-07-2013"
本地化日期
上面討論的日期格式化方法應(yīng)該適用于大多數(shù)應(yīng)用,但如果想本地化日期的格式,建議使用 Date 對(duì)象的toLocaleDateString()方法:
const today = new Date().toLocaleDateString('en-GB', {
day: 'numeric',
month: 'short',
year: 'numeric',
});
console.log(today); // '4 Jul 2023'如果想顯示日期的數(shù)字版本,建議使用以下解決方案:
const today = new Date().toLocaleDateString(undefined, {
day: 'numeric',
month: 'numeric',
year: 'numeric',
});這里輸出了 7/26/2016. 如果想確保月份和日期是兩位數(shù),只需更改選項(xiàng):
const today = new Date().toLocaleDateString(undefined, {
day: '2-digit',
month: '2-digit',
year: 'numeric',
});這樣就會(huì)輸出 07/26/2016。
還可以使用其他一些相關(guān)函數(shù)來(lái)本地化時(shí)間和日期的顯示方式:
計(jì)算相對(duì)日期和時(shí)間
下面是在 JavaScript 日期中添加 20 天的示例(即計(jì)算出已知日期后 20 天的日期):
const myDate = new Date("July 20, 2016 15:00:00");
const nextDayOfMonth = myDate.getDate() + 20;
myDate.setDate(nextDayOfMonth);
const newDate = myDate.toLocaleString();原始的日期對(duì)象現(xiàn)在表示7月20日之后20天的日期,newDate包含的是表示該日期的本地化字符串。newDate的值是2016/8/9 15:00:00。
要計(jì)算相對(duì)時(shí)間戳,并得到更精確的差異,可以使用Date.getTime()和Date.setTime()來(lái)處理表示自某個(gè)特定時(shí)刻(即1970年1月1日)以來(lái)的毫秒數(shù)的整數(shù)。例如,如果想知道距離現(xiàn)在17小時(shí)后的時(shí)間:
const msSinceEpoch = (new Date()).getTime();
const seventeenHoursLater = new Date(msSinceEpoch + 17 * 60 * 60 * 1000);
比較時(shí)間
在比較時(shí)間時(shí),首先需要?jiǎng)?chuàng)建日期對(duì)象,<、>、<= 和 >= 都可以工作。 因此,比較 2014 年 7 月 19 日和 2014 年 7 月 18 日就很簡(jiǎn)單:
const date1 = new Date("July 19, 2014");
const date2 = new Date("July 28, 2014");
if(date1 > date2) {
console.log(date1);
} else {
console.log(date2);
}檢查相等性比較棘手,因?yàn)楸硎就蝗掌诘膬蓚€(gè)日期對(duì)象仍然是兩個(gè)不同的日期對(duì)象并且不相等。 比較日期字符串不是一個(gè)好主意,因?yàn)槔纭癑uly 20, 2014”和“20 July 2014”表示相同的日期,但具有不同的字符串表示形式。 下面的代碼片段說(shuō)明了第一點(diǎn):
const date1 = new Date("June 10, 2003");
const date2 = new Date(date1);
const equalOrNot = date1 == date2 ? "相等" : "不等";
console.log(equalOrNot);這里將輸出“不等”,這種特殊情況可以通過(guò)比較日期的時(shí)間戳來(lái)解決,如下所示:
date1.getTime() == date2.getTime()這個(gè)例子不太符合實(shí)際的應(yīng)用,因?yàn)橥ǔ2粫?huì)從另一個(gè)日期對(duì)象創(chuàng)建日期對(duì)象。下面來(lái)看一個(gè)更實(shí)際的例子。比較用戶輸入的生日是否與從后端獲得的幸運(yùn)日期相同。
const userEnteredString = "12/20/1989"; // MM/DD/YYYY format
const dateStringFromAPI = "1989-12-20T00:00:00Z";
const dateFromUserEnteredString = new Date(userEnteredString)
const dateFromAPIString = new Date(dateStringFromAPI);
if (dateFromUserEnteredString.getTime() == dateFromAPIString.getTime()) {
transferOneMillionDollarsToUserAccount();
} else {
doNothing();
}兩者都代表相同的日期,但不幸的是用戶將無(wú)法獲得這百萬(wàn)美元。問(wèn)題在于:JavaScript 會(huì)假定時(shí)區(qū)是瀏覽器提供的時(shí)區(qū),除非另有明確指定。
這意味著,new Date ("12/20/1989") 將創(chuàng)建一個(gè)日期 1989-12-20T00:00:00+5:45 或 1989-12-19T18:15:00Z ,而這與時(shí)間戳為 1989-12-20T00:00:00Z 是不同的。
不能只更改現(xiàn)有日期對(duì)象的時(shí)區(qū),因此現(xiàn)在的目標(biāo)是創(chuàng)建一個(gè)新的日期對(duì)象,但使用 UTC 而不是本地時(shí)區(qū)。
在創(chuàng)建日期對(duì)象時(shí)將忽略用戶的時(shí)區(qū)并使用 UTC。有兩種方法可以做到這一點(diǎn):
根據(jù)用戶輸入日期創(chuàng)建 ISO 格式的日期字符串,并使用它創(chuàng)建 Date 對(duì)象。 使用有效的 ISO 日期格式創(chuàng)建 Date 對(duì)象,同時(shí)明確指定使用的是 UTC 而不是本地時(shí)區(qū)。
const userEnteredDate = "12/20/1989";
const parts = userEnteredDate.split("/");
const userEnteredDateISO = parts[2] + "-" + parts[0] + "-" + parts[1];
const userEnteredDateObj = new Date(userEnteredDateISO + "T00:00:00Z");
const dateFromAPI = new Date("1989-12-20T00:00:00Z");
const result = userEnteredDateObj.getTime() == dateFromAPI.getTime(); // true如果不指定時(shí)間,這也適用,因?yàn)槟J(rèn)為午夜(即 00:00:00Z):
const userEnteredDate = new Date("1989-12-20");
const dateFromAPI = new Date("1989-12-20T00:00:00Z");
const result = userEnteredDate.getTime() == dateFromAPI.getTime(); // true注意,如果向日期構(gòu)造函數(shù)傳遞了正確的 ISO 日期格式 YYYY-MM-DD 的字符串,則它會(huì)自動(dòng)采用 UTC。
JavaScript 提供了一個(gè)簡(jiǎn)潔的 Date.UTC() 函數(shù),可以使用它來(lái)獲取日期的 UTC 時(shí)間戳。從日期中提取組件并將它們傳遞給函數(shù)。
const userEnteredDate = new Date("12/20/1989");
const userEnteredDateTimeStamp = Date.UTC(userEnteredDate.getFullYear(), userEnteredDate.getMonth(), userEnteredDate.getDate(), 0, 0, 0);
const dateFromAPI = new Date("1989-12-20T00:00:00Z");
const result = userEnteredDateTimeStamp == dateFromAPI.getTime(); // true
日期差異
下面來(lái)討論兩個(gè)用例:
- 計(jì)算兩個(gè)日期之間的天數(shù)
將兩個(gè)日期轉(zhuǎn)換為 UTC 時(shí)間戳,找出以毫秒為單位的差異并找到等效的天數(shù)。
const dateFromAPI = "2016-02-10T00:00:00Z";
const now = new Date();
const datefromAPITimeStamp = (new Date(dateFromAPI)).getTime();
const nowTimeStamp = now.getTime();
const microSecondsDiff = Math.abs(datefromAPITimeStamp - nowTimeStamp);
// 使用 Math.round 代替 Math.floor 來(lái)考慮某些 DST 情況
// 每天的毫秒數(shù) = 24 小時(shí)/天 * 60 分鐘/小時(shí) * 60 秒/分鐘 * 1000 毫秒/秒
const daysDiff = Math.round(microSecondsDiff / (1000 * 60 * 60 * 24));
console.log(daysDiff);
- 根據(jù)出生日期計(jì)算用戶的年齡
const birthDateFromAPI = "12/10/1989";
日期/時(shí)間操作最佳實(shí)踐
從用戶獲取日期和時(shí)間
如果需要從用戶那里獲取日期和時(shí)間,那么很可能需要的是他們的本地日期時(shí)間。我們?cè)谌掌谟?jì)算部分看到Date構(gòu)造函數(shù)可以接受多種不同的日期格式。
為了消除任何混淆,建議使用new Date(year, month, day, hours, minutes, seconds, milliseconds)格式來(lái)創(chuàng)建日期,這是使用Date構(gòu)造函數(shù)時(shí)能夠做到的最明確的方式。
可以使用允許省略最后四個(gè)參數(shù)的變體,如果它們?yōu)榱?;例如,new Date(2012, 10, 12)與new Date(2012, 10, 12, 0, 0, 0, 0)是相同的,因?yàn)槲粗付ǖ膮?shù)默認(rèn)為零。
例如,如果正在使用一個(gè)日期和時(shí)間選擇器,它給出了日期2012-10-12和時(shí)間12:30,可以提取這些部分并創(chuàng)建一個(gè)新的Date對(duì)象,如下所示:
const datePickerDate = '2012-10-12';
const timePickerTime = '12:30';
const [year, month, day] = datePickerDate.split('-').map(Number);
const [hours, minutes] = timePickerTime.split(':').map(Number);
const dateTime = new Date(year, month - 1, day, hours, minutes);
console.log(dateTime); // Fri Oct 12 2012 12:30:00 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)在上述示例中,首先將日期和時(shí)間分別存儲(chǔ)在datePickerDate和timePickerTime變量中。然后,使用split()方法將日期字符串和時(shí)間字符串拆分為數(shù)值數(shù)組,并將其存儲(chǔ)在[year, month, day]和[hours, minutes]變量中。最后,使用這些值創(chuàng)建一個(gè)新的Date對(duì)象,注意按照 JavaScript 的月份規(guī)則,需要將月份減去1。這樣就得到了一個(gè)包含用戶所選日期和時(shí)間的Date對(duì)象。
通過(guò)遵循這種方法,可以明確地指定日期和時(shí)間,以便消除不同日期解析格式可能帶來(lái)的混亂。
const dateFromPicker = "2012-10-12";
const timeFromPicker = "12:30";
const dateParts = dateFromPicker.split("-");
const timeParts = timeFromPicker.split(":");
const localDate = new Date(dateParts[0], dateParts[1]-1, dateParts[2], timeParts[0], timeParts[1]);注意,盡量避免從字符串創(chuàng)建日期,除非它是 ISO 日期格式。 請(qǐng)改用 Date(year, month, date, hours, minutes, seconds, microseconds) 方法。
僅獲取日期
如果只獲取日期(例如用戶的生日),最好將格式轉(zhuǎn)換為有效的 ISO 日期格式,以消除任何可能導(dǎo)致日期在轉(zhuǎn)換為 UTC 時(shí)向前或向后移動(dòng)的時(shí)區(qū)信息。 例如:
const dateFromPicker = "12/20/2012";
const dateParts = dateFromPicker.split("/");
const ISODate = dateParts[2] + "-" + dateParts[0] + "-" + dateParts[1];
const birthDate = new Date(ISODate).toISOString();如果使用有效的 ISO 日期格式 (YYYY-MM-DD) 輸入創(chuàng)建一個(gè) Date 對(duì)象,它將默認(rèn)為 UTC,而不是默認(rèn)為瀏覽器的時(shí)區(qū)。
存儲(chǔ)日期
始終以 UTC 格式存儲(chǔ)日期時(shí)間,始終將 ISO 日期字符串或時(shí)間戳保存到數(shù)據(jù)庫(kù)。實(shí)踐證明,在后端存儲(chǔ)本地時(shí)間是一個(gè)壞主意,最好讓瀏覽器在前端處理到本地時(shí)間的轉(zhuǎn)換。不應(yīng)該將“July 20, 1989 12:10 PM”之類的日期時(shí)間字符串發(fā)送到后端。
可以使用 Date 對(duì)象的 toISOString() 或 toJSON() 方法將本地時(shí)間轉(zhuǎn)換為 UTC。
const dateFromUI = "12-13-2012";
const timeFromUI = "10:20";
const dateParts = dateFromUI.split("-");
const timeParts = timeFromUI.split(":");
const date = new Date(dateParts[2], dateParts[0]-1, dateParts[1], timeParts[0], timeParts[1]);
const dateISO = date.toISOString();
$.post("http://example.com/", {date: dateISO}, ...)
顯示日期和時(shí)間
- 從 API 獲取時(shí)間戳或 ISO 格式的日期。
- 創(chuàng)建一個(gè)日期對(duì)象。
- 使用 toLocaleString() 或 toLocaleDateString() 和 toLocaleTimeString() 方法或日期庫(kù)來(lái)顯示本地時(shí)間。
const dateFromAPI = "2016-01-02T12:30:00Z";
const localDate = new Date(dateFromAPI);
const localDateString = localDate.toLocaleDateString(undefined, {
day: 'numeric',
month: 'short',
year: 'numeric',
});
const localTimeString = localDate.toLocaleTimeString(undefined, {
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
});
現(xiàn)代日期/時(shí)間處理 API:Temporal
JavaScript 中的日期處理 Date() 對(duì)象一直是飽受詬病,該對(duì)象是1995 年受到 Java 的啟發(fā)而實(shí)現(xiàn)的,自此就一直沒(méi)有改變過(guò)。雖然Java已經(jīng)放棄了這個(gè)對(duì)象,但是 Date() 仍保留在 JavaScript 中來(lái)實(shí)現(xiàn)瀏覽器的兼容。
Date() API 存在的問(wèn)題:
- 只支持UTC和用戶的PC時(shí)間;
- 不支持公歷以外的日歷;
- 字符串到日期解析容易出錯(cuò);
- Date 對(duì)象是可變的,比如:
const today = new Date();
const tomorrow = new Date(today.setDate(today.getDate() + 1));
console.log(tomorrow);
console.log(today);此時(shí),兩個(gè)時(shí)間輸出是一樣的,不符合我們的預(yù)期。正因?yàn)?Date() 對(duì)象存在的種種問(wèn)題。平時(shí)我們經(jīng)常需要借助 moment.js、Day.js等日期庫(kù),但是它們的體積較大,有時(shí)一個(gè)簡(jiǎn)單的日期處理就需要引入一個(gè)庫(kù),得不償失。
目前,由于Date API 在很多庫(kù)和瀏覽器引擎中的廣泛使用,沒(méi)有辦法修復(fù)API的不好的部分。而改變Date API 的工作方式也很可能會(huì)破壞許多網(wǎng)站和庫(kù)。
正因如此,TC39提出了一個(gè)全新的用于處理日期和時(shí)間的標(biāo)準(zhǔn)對(duì)象和函數(shù)——Temporal。新的Temporal API 提案旨在解決Date API的問(wèn)題。它為 JavaScript 日期/時(shí)間操作帶來(lái)了以下修復(fù):
- 僅可以創(chuàng)建和處理不可變Temporal對(duì)象;
- 提供用于日期和時(shí)間計(jì)算的簡(jiǎn)單 API;
- 支持所有時(shí)區(qū);
- 從 ISO-8601 格式進(jìn)行嚴(yán)格的日期解析;
- 支持非公歷。
Temporal 將取代 Moment.js 之類的庫(kù),這些庫(kù)很好地填補(bǔ)了 JavaScript 中的空白,這種空白非常普遍,因此將功能作為語(yǔ)言的一部分更有意義。
由于該提案還未正式發(fā)布,所以,可以借助官方提供的prlyfill來(lái)測(cè)試。首選進(jìn)行安裝:
npm install @js-temporal/polyfill導(dǎo)入并使用:
import { Temporal } from '@js-temporal/polyfill';
console.log(Temporal);Temporal 對(duì)象如下:
下面就來(lái)看看 Temporal 對(duì)象有哪些實(shí)用的功能。
當(dāng)前時(shí)間和日期
Temporal.Now 會(huì)返回一個(gè)表示當(dāng)前日期和時(shí)間的對(duì)象:
// 自1970年1月1日以來(lái)的時(shí)間(秒和毫秒)
Temporal.Now.instant().epochSeconds;
Temporal.Now.instant().epochMilliseconds;
// 當(dāng)前位置的時(shí)間
Temporal.Now.zonedDateTimeISO();
// 當(dāng)前時(shí)區(qū)
Temporal.Now.timeZone();
// 指定時(shí)區(qū)的當(dāng)前時(shí)間
Temporal.Now.zonedDateTimeISO('Europe/London');
實(shí)例時(shí)間和日期
Temporal.Instant 根據(jù) ISO 8601 格式的字符串返回一個(gè)表示日期和時(shí)間的對(duì)象,結(jié)果會(huì)精確到納秒:
Temporal.Instant.from('2022-02-01T05:56:78.999999999+02:00[Europe/Berlin]');
// 輸出結(jié)果:2022-02-01T03:57:18.999999999Z
Temporal.Instant.from('2022-02-011T05:06+07:00');
// 輸出結(jié)果:2022-01-31T22:06:00Z除此之外,還可以獲取紀(jì)元時(shí)間的對(duì)應(yīng)的日期(UTC 1970年1月1日0點(diǎn)是紀(jì)元時(shí)間):
Temporal.Instant.fromEpochSeconds(1.0e8);
// 輸出結(jié)果:1973-03-03T09:46:40Z
時(shí)區(qū)日期和時(shí)間
Temporal.ZonedDateTime 返回一個(gè)對(duì)象,該對(duì)象表示在特定時(shí)區(qū)的日期/時(shí)間:
new Temporal.ZonedDateTime(
1234567890000, // 紀(jì)元時(shí)間
Temporal.TimeZone.from('Europe/London'), // 時(shí)區(qū)
Temporal.Calendar.from('iso8601') // 默認(rèn)日歷
);
Temporal.ZonedDateTime.from('2025-09-05T02:55:00+02:00[Africa/Cairo]');
Temporal.Instant('2022-08-05T20:06:13+05:45').toZonedDateTime('+05:45');
// 輸出結(jié)果:
Temporal.ZonedDateTime.from({
timeZone: 'America/New_York',
year: 2025,
month: 2,
day: 28,
hour: 10,
minute: 15,
second: 0,
millisecond: 0,
microsecond: 0,
nanosecond: 0
});
// 輸出結(jié)果:2025-02-28T10:15:00-05:00[America/New_York]
簡(jiǎn)單的日期和時(shí)間
我們并不會(huì)總是需要使用精確的時(shí)間,因此 Temporal API 提供了獨(dú)立于時(shí)區(qū)的對(duì)象。這些可以用于更簡(jiǎn)單的活動(dòng)。
- Temporal.PlainDateTime:指日歷日期和時(shí)間。
- Temporal.PlainDate:指特定的日歷日期。
- Temporal.PlainTime:指一天中的特定時(shí)間。
- Temporal.PlainYearMonth:指沒(méi)有日期成分的日期,例如“2022 年 2 月”。
- Temporal.PlainMonthDay:指沒(méi)有年份的日期,例如“10 月 1 日”。
它們都有類似的構(gòu)造函數(shù),以下有兩種形式來(lái)創(chuàng)建簡(jiǎn)單的時(shí)間和日期:
new Temporal.PlainDateTime(2021, 5, 4, 13, 14, 15);
Temporal.PlainDateTime.from('2021-05-04T13:14:15');
new Temporal.PlainDate(2021, 5, 4);
Temporal.PlainDate.from('2021-05-04');
new Temporal.PlainTime(13, 14, 15);
Temporal.PlainTime.from('13:14:15');
new Temporal.PlainYearMonth(2021, 4);
Temporal.PlainYearMonth.from('2019-04');
new Temporal.PlainMonthDay(3, 14);
Temporal.PlainMonthDay.from('03-14');
日期和時(shí)間值
所有 Temporal 對(duì)象都可以返回特定的日期/時(shí)間值。例如,使用ZonedDateTime:
const t1 = Temporal.ZonedDateTime.from('2025-12-07T03:24:30+02:00[Africa/Cairo]');
t1.year; // 2025
t1.month; // 12
t1.day; // 7
t1.hour; // 3
t1.minute; // 24
t1.second; // 30
t1.millisecond; // 0
t1.microsecond; // 0
t1.nanosecond; // 0其他有用的屬性包括:
- dayOfWeek(周一為 1 至周日為 7)
- dayOfYear(1 至 365 或 366)
- weekOfYear(1 到 52,有時(shí)是 53)
- daysInMonth(28、29、30、31)
- daysInYear(365 或 366)
- inLeapYear(true或false)
比較和排序日期
所有 Temporal 對(duì)象都可以使用 compare() 返回整數(shù)的函數(shù)進(jìn)行比較。例如,比較兩個(gè)ZonedDateTime對(duì)象:
Temporal.ZonedDateTime.compare(t1, t2);這個(gè)比較結(jié)果會(huì)有三種情況:
- 當(dāng)兩個(gè)時(shí)間值相等時(shí),返回 0;
- 當(dāng) t1 在 t2 之后時(shí),返回 1;
- 當(dāng) t1 在 t2 之前時(shí),但會(huì) -1;
const date1 = Temporal.Now,
const date2 = Temporal.PlainDateTime.from('2022-05-01');
Temporal.ZonedDateTime.compare(date1, date2); // -1compare() 的結(jié)果可以用于數(shù)組的 sort() 方法來(lái)對(duì)時(shí)間按照升序進(jìn)行排列(從早到晚):
const t = [
'2022-01-01T00:00:00+00:00[Europe/London]',
'2022-01-01T00:00:00+00:00[Africa/Cairo]',
'2022-01-01T00:00:00+00:00[America/New_York]'
].map(d => Temporal.ZonedDateTime.from(d))
.sort(Temporal.ZonedDateTime.compare);
日期計(jì)算
提案還提供了幾種方法來(lái)對(duì)任何 Temporal 對(duì)象執(zhí)行日期計(jì)算。當(dāng)傳遞一個(gè)Temporal.Duration對(duì)象時(shí),它們都會(huì)返回一個(gè)相同類型的新的 Temporal,該對(duì)象使用years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds 和 nanoseconds 字段來(lái)設(shè)置時(shí)間。
const t1 = Temporal.ZonedDateTime.from('2022-01-01T00:00:00+00:00[Europe/London]');
t1.add({ hours: 8, minutes: 30 }); // 往后8小時(shí)30分
t1.subtract({ days: 5 }); // 往前5天
t1.round({ smallestUnit: 'month' }); // 四舍五入到最近的月份until() 和 since() 方法會(huì)返回一個(gè)對(duì)象,該 Temporal.Duration 對(duì)象描述基于當(dāng)前日期/時(shí)間的特定日期和時(shí)間之前或之后的時(shí)間,例如:
t1.until().months; // 到t1還有幾個(gè)月
t2.until().days; // 到t2還有幾天
t3.since().weeks; // t3已經(jīng)過(guò)去了幾周equals() 方法用來(lái)確定兩個(gè)日期/時(shí)間值是否相同:
const d1 = Temporal.PlainDate.from('2022-01-31');
const d2 = Temporal.PlainDate.from('2023-01-31');
d1.equals(d2); // false
格式化日期
雖然這不是 Temporal API 的一部分,但 JavaScript Intl(國(guó)際化)API提供了一個(gè) DateTimeFormat() 構(gòu)造函數(shù),可以用于格式化 Temporal 或 Date 對(duì)象:
const d = new Temporal.PlainDate(2022, 3, 14);
// 美國(guó)日期格式:3/14/2022
new Intl.DateTimeFormat('en-US').format(d);
// 英國(guó)日期格式:14/3/2022
new Intl.DateTimeFormat('en-GB').format(d);
// 西班牙長(zhǎng)日期格式:miércoles, 14 de abril de 2022
new Intl.DateTimeFormat('es-ES', { dateStyle: 'full' }).format(d);
瀏覽器支持
目前還沒(méi)有瀏覽器支持 Temporal API:
Temporal 提案:https://tc39.es/proposal-temporal/。
日期/時(shí)間操作庫(kù)
在 JavaScript 中進(jìn)行日期/時(shí)間操作是一個(gè)很麻煩的事,JS的生態(tài)中有很多實(shí)用的日期操作庫(kù),最后就來(lái)分享幾個(gè)實(shí)用的日期庫(kù)。
Moment.js
Moment.js 是一個(gè)輕量級(jí) JavaScript 日期庫(kù),用于解析、驗(yàn)證、操作和格式化日期,是一個(gè)很受歡迎的日期操作庫(kù)。
不過(guò),Moment.js 是一個(gè)遺留項(xiàng)目,現(xiàn)在處于維護(hù)模式。維護(hù)者認(rèn)為,無(wú)法重構(gòu) Moment.js 來(lái)滿足現(xiàn)代 JavaScript 開(kāi)發(fā)的需求,例如不變性和 tree shaking。Lighthouse(Chrome 的內(nèi)置審核工具)警告不要使用 Moment,因?yàn)樗拇笮≥^大 (329 kb)。
安裝Moment.js
可以通過(guò)以下任一方式來(lái)安裝該庫(kù):
npm install moment --save # npm
yarn add moment # Yarn
Install-Package Moment.js # NuGet
spm install moment --save # spm
meteor add momentjs:moment # meteor
導(dǎo)入Moment.js
在 JavaScript 文件中,導(dǎo)入Moment.js庫(kù):
const moment = require('moment');
創(chuàng)建日期對(duì)象
可以傳遞一個(gè)日期字符串或日期對(duì)象給moment()函數(shù),然后返回一個(gè)Moment對(duì)象:
const date = moment('2023-07-04');
格式化日期顯示
Moment.js 提供了豐富的日期格式化選項(xiàng)??梢允褂胒ormat()方法將日期格式化為所需的字符串格式:
const formattedDate = date.format('YYYY-MM-DD');
console.log(formattedDate); // 輸出:2023-07-04
日期運(yùn)算
Moment.js提供了許多方便的方法來(lái)進(jìn)行日期和時(shí)間的運(yùn)算。下面是一些示例:
// 添加一天
const tomorrow = date.add(1, 'day');
console.log(tomorrow.format('YYYY-MM-DD')); // 輸出:2023-07-05
// 減去一個(gè)月
const lastMonth = date.subtract(1, 'month');
console.log(lastMonth.format('YYYY-MM-DD')); // 輸出:2023-06-04
// 比較日期
const otherDate = moment('2023-07-10');
console.log(date.isBefore(otherDate)); // 輸出:true
console.log(date.isAfter(otherDate)); // 輸出:falseMoment.js還提供了許多其他常用的功能,如獲取當(dāng)前日期、解析日期字符串、計(jì)算日期之間的差異等。
Date-fns
Date-fns 是一個(gè)現(xiàn)代、輕量級(jí)的JavaScript日期處理庫(kù),用于在瀏覽器和Node.js環(huán)境中處理日期和時(shí)間。它的設(shè)計(jì)目標(biāo)是提供一組簡(jiǎn)單、純函數(shù)式的API來(lái)執(zhí)行各種日期操作,而不依賴于全局對(duì)象。
以下是Date-fns 的特點(diǎn):
- 輕量級(jí):Date-fns非常小巧,只包含所需的功能,可以減少項(xiàng)目的文件大小。
- 純函數(shù):Date-fns的函數(shù)都是純函數(shù),即相同的輸入總是產(chǎn)生相同的輸出,不存在副作用。這使得代碼更可預(yù)測(cè)、易測(cè)試和可維護(hù)。
- 易于使用:Date-fns的API設(shè)計(jì)簡(jiǎn)單易懂,與現(xiàn)代JavaScript的語(yǔ)法和慣用法保持一致。它提供了大量的日期處理功能,如格式化、解析、比較、計(jì)算等。
- 兼容性:Date-fns支持所有現(xiàn)代的瀏覽器和Node.js版本。
安裝Date-fns
可以使用npm或yarn等包管理工具來(lái)安裝Date-fns。在項(xiàng)目目錄下運(yùn)行以下命令安裝Date-fns:
npm install date-fns
導(dǎo)入Date-fns
在JavaScript文件中導(dǎo)入所需的Date-fns函數(shù):
import { format, parseISO, differenceInDays } from 'date-fns';
使用Date-fns函數(shù)
使用導(dǎo)入的函數(shù)來(lái)執(zhí)行各種日期操作。以下是一些示例:
const date = new Date();
// 格式化日期
const formattedDate = format(date, 'yyyy-MM-dd');
console.log(formattedDate); // 輸出:2023-07-04
// 解析日期字符串
const parsedDate = parseISO('2023-07-04');
console.log(parsedDate); // 輸出:Tue Jul 04 2023 00:00:00 GMT+0530 (India Standard Time)
// 計(jì)算日期之間的差異
const startDate = new Date(2023, 6, 1);
const endDate = new Date(2023, 6, 10);
const diff = differenceInDays(endDate, startDate);
console.log(diff); // 輸出:9在上述示例中,使用了format()函數(shù)將日期格式化為指定的字符串格式,使用了parseISO()函數(shù)解析日期字符串為日期對(duì)象,以及使用了differenceInDays()函數(shù)計(jì)算兩個(gè)日期之間的天數(shù)差異。
Day.js
Day.js 是一個(gè)輕量級(jí)的JavaScript日期處理庫(kù),用于解析、操作和格式化日期對(duì)象。它的設(shè)計(jì)目標(biāo)是提供一個(gè)簡(jiǎn)單、靈活的API,使得處理日期和時(shí)間變得更加方便。
以下是 Day.js 的特點(diǎn):
- 輕量級(jí):Day.js非常小巧,壓縮后僅有2 KB左右的大小,可以減少項(xiàng)目的文件大小。
- 易用性:Day.js的API設(shè)計(jì)簡(jiǎn)潔明了,與現(xiàn)代JavaScript的語(yǔ)法和慣用法保持一致。你可以輕松地對(duì)日期進(jìn)行解析、格式化、計(jì)算、比較等操作。
- 不可變性:Day.js的日期對(duì)象是不可變的,即每次對(duì)日期進(jìn)行操作都會(huì)返回一個(gè)新的日期對(duì)象,而不會(huì)修改原始對(duì)象。這種設(shè)計(jì)模式有助于避免副作用,并提高代碼的可預(yù)測(cè)性。
- Moment.js兼容性:Day.js的API設(shè)計(jì)與Moment.js類似,因此可以很容易地從Moment.js遷移到Day.js,而無(wú)需更改太多代碼。
安裝Day.js
可以使用npm或yarn等包管理工具來(lái)安裝Day.js。在項(xiàng)目目錄下運(yùn)行以下命令安裝Day.js:
npm install dayjs
導(dǎo)入Day.js
在JavaScript文件中導(dǎo)入Day.js:
import dayjs from 'dayjs';
使用Day.js函數(shù)
使用Day.js的函數(shù)來(lái)進(jìn)行日期操作。以下是一些示例:
const date = dayjs();
// 格式化日期
const formattedDate = date.format('YYYY-MM-DD');
console.log(formattedDate); // 輸出:2023-07-04
// 解析日期字符串
const parsedDate = dayjs('2023-07-04');
console.log(parsedDate); // 輸出:Tue Jul 04 2023 00:00:00 GMT+0530 (India Standard Time)
// 計(jì)算日期之間的差異
const startDate = dayjs('2023-07-01');
const endDate = dayjs('2023-07-10');
const diff = endDate.diff(startDate, 'day');
console.log(diff); // 輸出:9在上述示例中,使用了format()函數(shù)將日期格式化為指定的字符串格式,使用了dayjs()函數(shù)解析日期字符串為日期對(duì)象,以及使用了diff()函數(shù)計(jì)算兩個(gè)日期之間的天數(shù)差異。
Luxon
Luxon 是一個(gè)用于處理日期、時(shí)間和時(shí)區(qū)的先進(jìn) JavaScript 庫(kù)。它提供了一組強(qiáng)大的功能,可以幫助你在瀏覽器和 Node.js 環(huán)境中輕松處理日期和時(shí)間。
以下是 Luxon 的特點(diǎn):
- 強(qiáng)大的日期和時(shí)間處理:Luxon 提供了豐富的 API,用于解析、格式化、操作和比較日期和時(shí)間。它支持多種標(biāo)準(zhǔn)和自定義的日期和時(shí)間格式,包括 ISO 8601、RFC 2822 等。
- 支持時(shí)區(qū)處理:Luxon 支持全球各地的時(shí)區(qū),并提供了靈活的時(shí)區(qū)轉(zhuǎn)換功能。它使用 IANA(Olson)時(shí)區(qū)數(shù)據(jù)庫(kù),確保準(zhǔn)確的時(shí)區(qū)信息。
- 不可變性:Luxon 的日期對(duì)象是不可變的,每次對(duì)日期進(jìn)行操作都會(huì)返回一個(gè)新的日期對(duì)象,而不會(huì)修改原始對(duì)象。這種設(shè)計(jì)模式有助于避免副作用,并提高代碼的可預(yù)測(cè)性。
- 鏈?zhǔn)秸{(diào)用:Luxon 的 API 允許你使用鏈?zhǔn)秸{(diào)用,使得代碼更簡(jiǎn)潔、易讀。你可以按順序執(zhí)行多個(gè)操作,而無(wú)需多次引用日期對(duì)象。
安裝 Luxon
使用 npm 或 yarn 等包管理工具,在項(xiàng)目目錄下運(yùn)行以下命令安裝 Luxon:
npm install luxon
導(dǎo)入 Luxon
在 JavaScript 文件中導(dǎo)入 Luxon:
import { DateTime } from 'luxon';
使用 Luxon 函數(shù)
使用 Luxon 的函數(shù)來(lái)處理日期和時(shí)間。以下是一些示例:
const now = DateTime.now();
// 格式化日期
const formattedDate = now.toFormat('yyyy-MM-dd');
console.log(formattedDate); // 輸出:2023-07-04
// 解析日期字符串
const parsedDate = DateTime.fromISO('2023-07-04');
console.log(parsedDate); // 輸出:DateTime { ... }
// 計(jì)算日期之間的差異
const startDate = DateTime.fromISO('2023-07-01');
const endDate = DateTime.fromISO('2023-07-10');
const diff = endDate.diff(startDate, 'days').toObject().days;
console.log(diff); // 輸出:9在上述示例中,使用了 toFormat() 函數(shù)將日期格式化為指定的字符串格式,使用了 fromISO() 函數(shù)解析 ISO 8601 格式的日期字符串為日期對(duì)象,以及使用了 diff() 函數(shù)計(jì)算兩個(gè)日期之間的天數(shù)差異。
分享標(biāo)題:JavaScript日期時(shí)間操作完整指南!
本文路徑:http://fisionsoft.com.cn/article/dpphihc.html


咨詢
建站咨詢
