給急躁的程式設計師的 JavaScript(ES2022 版)
請支持這本書:購買捐款
(廣告,請不要封鎖。)

44 日期 (Date)



本章說明 JavaScript 的 API 以處理日期,也就是 Date 類別。

44.1 最佳實務:避免使用內建的 Date

JavaScript Date API 使用起來很麻煩。因此,最好依賴函式庫來處理與日期相關的任何事情。熱門的函式庫包括

請參閱部落格文章 “為什麼你不應該使用 Moment.js…” 以了解這些函式庫的優缺點。

此外,TC39 正在為 JavaScript 開發新的日期 API:temporal

44.1.1 在日期函式庫中尋找的項目

有兩件事很重要,請記住

44.2 時間標準

44.2.1 背景:UTC 與 Z 與 GMT

UTC、Z 和 GMT 都是指定時間的方式,它們很相似,但有細微的差別

來源

44.2.2 日期不支援時區

日期支援下列時間標準

根據作業的不同,只有部分選項可用。例如,在將日期轉換為字串或擷取時間單位(例如月份中的天數)時,您只能在當地時區和 UTC 之間進行選擇。

在內部,日期會儲存為 UTC。在從當地時區轉換或轉換到當地時區時,必要的偏移會透過日期來決定。在以下範例中,當地時區為歐洲/巴黎

// CEST (Central European Summer Time)
assert.equal(
  new Date('2122-06-29').getTimezoneOffset(), -120);
  
// CET (Central European Time)
assert.equal(
  new Date('2122-12-29').getTimezoneOffset(), -60);

每當您建立或轉換日期時,您需要留意所使用的時間標準 - 例如:new Date() 使用當地時區,而 .toISOString() 使用 UTC。

> new Date(2077, 0, 27).toISOString()
'2077-01-26T23:00:00.000Z'

日期會將 0 解釋為 1 月。在當地時區中,月份中的天數為 27,但在 UTC 中為 26。

  記錄每個作業支援的時間標準

在本章節的其餘部分中,每個作業支援的時間標準都會註明。

44.2.2.1 無法指定時區的缺點

無法指定時區有兩個缺點

44.3 背景:日期時間格式(ISO)

日期時間格式描述

以下是 .toISOString() 回傳的日期時間字串範例

'2033-05-28T15:59:59.123Z'

日期時間格式具有下列結構

除了 Z(即 UTC+0)之外,我們也可以指定相對於 UTC 的時間偏移量

44.3.1 提示:附加 Z 以確定日期剖析

如果在字串尾端加上 Z,日期剖析不會在不同位置產生不同的結果

44.4 時間值

時間值透過自 1970 年 1 月 1 日 00:00:00 UTC 以來的毫秒數來表示日期。

時間值可用於建立日期

const timeValue = 0;
assert.equal(
  new Date(timeValue).toISOString(),
  '1970-01-01T00:00:00.000Z');

將日期轉換為數字會回傳其時間值

> Number(new Date(123))
123

排序運算子會將其運算元轉換為數字。因此,您可以使用這些運算子來比較日期

assert.equal(
  new Date('1972-05-03') < new Date('2001-12-23'), true);

// Internally:
assert.equal(73699200000 < 1009065600000, true);

44.4.1 建立時間值

下列方法會建立時間值

44.4.2 取得和設定時間值

44.5 建立日期

44.5.1 透過數字建立日期

new Date(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number)(當地時區)

兩個參數有陷阱

範例

> new Date(2077,0,27, 21,49).toISOString() // CET (UTC+1)
'2077-01-27T20:49:00.000Z'

請注意,輸入小時 (21) 與輸出小時 (20) 不同。前者是指當地時區,後者是指 UTC。

44.5.2 從字串剖析日期

new Date(dateTimeStr: string)(當地時區、UTC、時間偏移量)

如果結尾有 Z,則使用 UTC

> new Date('2077-01-27T00:00Z').toISOString()
'2077-01-27T00:00:00.000Z'

如果結尾沒有 Z 或時間偏移量,則使用當地時區

> new Date('2077-01-27T00:00').toISOString() // CET (UTC+1)
'2077-01-26T23:00:00.000Z'

如果字串只包含日期,則解釋為 UTC

> new Date('2077-01-27').toISOString()
'2077-01-27T00:00:00.000Z'

44.5.3 建立日期的其他方式

44.6 取得器和設定器

44.6.1 時間單位取得器和設定器

日期有時間單位的取得器和設定器,例如

這些取得器和設定器符合下列模式

以下是支援的時間單位

還有一個取得器不符合前面提到的模式

44.7 將日期轉換為字串

範例日期

const d = new Date(0);

44.7.1 帶有時間的字串

44.7.2 帶有日期的字串

44.7.3 帶有日期和時間的字串

44.7.4 其他方法

以下三個方法不屬於 ECMAScript,而是屬於 ECMAScript 國際化 API。該 API 有許多用於格式化日期(包括支援時區)的功能,但無法用於剖析日期。

  練習:建立日期字串

exercises/dates/create_date_string_test.mjs