HTML 中使用的日期和時間格式

某些 HTML 元素使用日期和/或時間值。本文介紹了指定這些值的字串的格式。

使用此類格式的元素包括 <input> 元素的某些形式,這些形式允許使用者選擇或指定日期、時間或兩者,以及 <ins><del> 元素,它們的 datetime 屬性指定插入或刪除內容發生的日期或日期和時間。

對於 <input>type 輸入的值,其 value 包含表示日期和/或時間的字串是

示例

在深入研究 HTML 中日期和時間字串的編寫和解析方式之前,以下是一些示例,這些示例應該可以幫助您瞭解常用的日期和時間字串格式。

示例 HTML 日期和時間字串
字串 日期和/或時間
2005-06-07 2005 年 6 月 7 日 [詳細資訊]
08:45 上午 8:45 [詳細資訊]
08:45:25 上午 8:45 和 25 秒 [詳細資訊]
0033-08-04T03:40 公元 33 年 8 月 4 日上午 3:40 [詳細資訊]
1977-04-01T14:00:30 1977年4月1日下午2:00:30 [詳細資訊]
1901-01-01T00:00Z 1901年1月1日午夜協調世界時(UTC) [詳細資訊]
1901-01-01T00:00:01-04:00 1901年1月1日東部標準時間(EST)午夜過後1秒 [詳細資訊]

基礎

在檢視 HTML 元素使用的各種日期和時間相關字串格式之前,瞭解它們定義方式的一些基本事實會很有幫助。HTML 使用ISO 8601標準的變體來表示其日期和時間字串。值得檢視您使用的格式的描述,以確保您的字串確實與 HTML 相容,因為 HTML 規範包含用於解析這些字串的演算法,實際上比 ISO 8601 更精確,因此在日期和時間字串的預期外觀方面可能存在細微差異。

字元集

HTML 中的日期和時間始終是使用ASCII字元集的字串。

年份數字

為了簡化 HTML 中日期字串使用的基本格式,規範要求所有年份都使用現代(或**推算**)公曆。雖然使用者介面可能允許使用其他日曆輸入日期,但底層值始終使用公曆。

雖然公曆直到 1582 年才建立(取代了類似的儒略曆),但為了 HTML 的目的,公曆被擴充套件回公元 1 年。確保任何更早的日期都考慮了這一點。

為了 HTML 日期,年份始終至少為四位數長;公元 1000 年之前的年份用前導零(“0”)填充,因此公元 72 年寫為 0072。公元 1 年之前的年份不受支援,因此 HTML 不支援公元前 1 年(公元前 1 年)或更早的年份。

一年通常為 365 天,除了在**閏年**期間。

閏年

**閏年**是指任何能被 400 整除的年份,或者年份能被 4 整除但不能被 100 整除。儘管日曆年通常為 365 天,但地球實際上大約需要 365.2422 天才能繞太陽完成一次軌道。閏年有助於調整日曆,使其與地球在其軌道上的實際位置同步。每四年在一年中新增一天,實際上使平均年份為 365.25 天,這接近正確。

對演算法的調整(當年份可以被 400 整除時採用閏年,而當年份可以被 100 整除時跳過閏年)有助於使平均值更接近正確的日期數(365.2425 天)。科學家偶爾會在日曆中新增閏秒(認真地說),以處理剩下的千分之三天的誤差,並補償地球自轉逐漸自然發生的減速。

雖然月份 02,二月,通常有 28 天,但在閏年有 29 天。

一年中的月份

一年有 12 個月,從 1 到 12 編號。它們始終由兩位數的 ASCII 字串表示,其值範圍從 0112。請參閱每月天數部分中的表格,瞭解月份數字及其對應的名稱(以及天數)。

每月的天數

月份數字 1、3、5、7、8、10 和 12 為 31 天。月份 4、6、9 和 11 為 30 天。月份 2,二月,大多數年份為 28 天,但在閏年為 29 天。以下表格對此進行了詳細說明。

一年中的月份及其天數
月份數字 名稱(英文) 天數
01 一月 31
02 二月 28(閏年為 29 天)
03 三月 31
04 四月 30
05 五月 31
06 六月 30
07 七月 31
08 八月 31
09 九月 30
10 十月 31
11 十一月 30
12 十二月 31

星期字串

周字串指定特定年份內的某一週。**有效的周字串**由一個有效的年份數字、一個連字元(“-”或 U+002D)、大寫字母“W”(U+0057)以及兩位數的年份周值組成。

年份周是介於 0153 之間的兩位數字符串。每個星期從星期一開始,到星期天結束。這意味著 1 月份的前幾天可能被認為是上一個週年的部分,而 12 月份的最後幾天可能被認為是下一個週年的部分。一年的第一週是包含該年第一個星期四的星期。例如,1953 年的第一個星期四是 1 月 1 日,因此該星期(從 12 月 29 日星期一開始)被認為是一年的第一週。因此,1952 年 12 月 30 日出現在 1953-W01 周內。

一年有 53 周,如果

  • 日曆年的第一天(1 月 1 日)是星期四**或**
  • 一年中的第一天(1 月 1 日)是星期三,並且年份是閏年

所有其他年份有 52 周。

周字串 周和年(日期範圍)
2001-W37 2001 年第 37 周(2001 年 9 月 10 日至 16 日)
1953-W01 1953 年第 1 周(1952 年 12 月 29 日至 1953 年 1 月 4 日)
1948-W53 1948 年第 53 周(1948 年 12 月 27 日至 1949 年 1 月 2 日)
1949-W01 1949 年第 1 周(1949 年 1 月 3 日至 9 日)
0531-W16 531 年第 16 周(531 年 4 月 13 日至 19 日)
0042-W04 42 年第 4 周(42 年 1 月 21 日至 27 日)

請注意,年份和週數都用前導零填充,年份填充到四位數,週數填充到兩位數。

月份字串

月份字串表示時間中的特定月份,而不是一年的通用月份。也就是說,HTML 月份字串不是表示“一月”,而是表示月份和年份配對,如“1972 年一月”。

**有效的月份字串**由一個有效的年份數字(至少四位數的字串)、一個連字元(“-”或 U+002D)、一個兩位數的數字月份數字組成,其中 01 表示一月,12 表示十二月。

月份字串 月份和年份
17310-09 17310 年 9 月
2019-01 2019 年 1 月
1993-11 1993 年 11 月
0571-04 571 年 4 月
0001-07 公元 1 年 7 月

請注意,所有年份至少為四個字元長;少於四位數的年份用前導零填充。

日期字串

有效的日期字串由一個月份字串、一個連字元(“-”或 U+002D)、一個兩位數的每月日期組成。

日期字串 完整日期
1993-11-01 1993 年 11 月 1 日
1066-10-14 1066 年 10 月 14 日
0571-04-22 571 年 4 月 22 日
0062-02-05 62 年 2 月 5 日

時間字串

時間字串可以指定精確到分鐘、秒或毫秒的時間。僅指定小時或分鐘是不允許的。**有效的時間字串**至少由兩位數的小時、一個冒號(“:”、U+003A)、然後是兩位數的分鐘組成。分鐘之後可以選擇新增另一個冒號和兩位數的秒數。毫秒可以選擇透過新增一個小數點字元(“.”、U+002E)後跟一位、兩位或三位數字來指定。

還有一些額外的基本規則

  • 小時始終使用 24 小時制指定,其中 00 為午夜,晚上 11 點為 23。不允許 0023 範圍之外的任何值。
  • 分鐘必須是介於 0059 之間的兩位數。不允許該範圍之外的任何值。
  • 如果省略秒數(僅指定精確到分鐘的時間),冒號不應該跟隨分鐘數。
  • 如果指定了秒數並且是整數,則後面不應跟隨小數點。
  • 如果指定了秒數並且是整數,則後面不應跟隨小數點。
  • 如果包含了秒數的小數部分,它可以是一到三位數字長,表示毫秒數。它位於時間字串秒數部分之後的小數點之後。
時間字串 時間
00:00:30.75 上午 12:00:30.75(午夜過後 30.75 秒)
12:15 下午 12:15
13:44:25 下午 1:44:25(下午 1:44 過後 25 秒)

本地日期和時間字串

有效的datetime-local字串由一個date字串和一個time字串組成,它們之間用字母“T”或空格字元連線。字串中不包含任何關於時區的資訊;日期和時間被認為是在使用者的本地時區。

當您設定datetime-local輸入的value時,字串將被**規範化**為標準形式。規範化的datetime字串始終使用字母“T”來分隔日期和時間,並且字串的時間部分儘可能短。這是透過在秒陣列件的值為:00時省略它來實現的。

有效的datetime-local字串示例
日期/時間字串 規範化的日期/時間字串 實際日期和時間
1986-01-28T11:38:00.01 1986-01-28T11:38:00.01 1986 年 1 月 28 日上午 11:38:00.01
1986-01-28 11:38:00.010

1986-01-28T11:38:00.01

請注意,規範化後,這與前面的datetime-local字串相同。空格已被替換為“T”字元,並且秒數小數部分中的尾隨零已被刪除,以使字串儘可能短。

1986 年 1 月 28 日上午 11:38:00.01
0170-07-31T22:00:00

0170-07-31T22:00

請注意,此日期的規範化形式刪除了“:00”,它表示秒數為零,因為當秒數為零時,秒數是可選的,並且規範化字串將字串的長度最小化。

170 年 7 月 31 日晚上 10:00

全域性日期和時間字串

全球日期和時間字串指定日期和時間以及發生的時區。**有效的全球日期和時間字串**與本地日期和時間字串的格式相同,只是在時間之後附加了一個時區字串,位於時間之後。

時區偏移字串

時區偏移字串指定從標準時間基線正負小時和分鐘的偏移量。有兩個標準時間基線,它們非常接近,但並不完全相同

  • 對於協調世界時(UTC)在 1960 年代初建立後的日期,時間基線為 Z,偏移量表示特定時區相對於 0º 經線(經過英國格林威治皇家天文臺)的子午線時間的偏移量。
  • 對於 UTC 之前的日期,時間基線則用UT1表示,它是子午線上的當代地球太陽時間。

時區字串立即附加在日期和時間字串中的時間之後。您可以指定“Z”作為時區偏移字串,以指示時間以 UTC 指定。否則,時區字串將按如下方式構造

  1. 一個表示偏移量符號的字元:加號(“+”或 U+002B)表示位於子午線以東的時區,減號(“-”或 U+002D)表示位於子午線以西的時區。
  2. 一個兩位數表示該時區相對於子午線的偏移小時數。此值必須介於 0023 之間。
  3. 可選的冒號(":")字元。
  4. 兩位數的分鐘數,表示超過小時的分鐘數;該值必須介於 0059 之間。

雖然此格式允許時區在 -23:59 到 +23:59 之間,但當前時區偏移範圍為 -12:00 到 +14:00,並且當前沒有時區偏離小時數以外的任何其他值,例如 003045 分鐘。這可能會隨時發生變化,因為國家/地區可以隨時以任何他們希望的方式更改其時區。

有效全域性日期和時間字串的示例
全域性日期和時間字串 實際全域性日期和時間 本初子午線上的日期和時間
2005-06-07T00:00Z 2005 年 6 月 7 日,協調世界時(UTC)午夜 2005 年 6 月 7 日,午夜
1789-08-22T12:30:00.1-04:00 1789 年 8 月 22 日,東部夏令時(EDT)下午 12:30 十分之一秒 1789 年 8 月 22 日,下午 4:30 十分之一秒
3755-01-01 00:00+10:00 3755 年 1 月 1 日,澳大利亞東部標準時間(AEST)午夜 3754 年 12 月 31 日,下午 2:00

日期問題

由於資料儲存和精度問題,您可能需要了解一些客戶端和伺服器端問題。

Y2K38 問題(通常是伺服器端)

JavaScript 使用雙精度浮點數儲存日期,與所有數字一樣,這意味著 JavaScript 程式碼不會遇到 Y2K38 問題,除非使用整數強制轉換/位駭客,因為所有 JavaScript 位運算子都使用 32 位帶符號的 2 的補碼整數。

問題在於伺服器端:儲存大於 2^31 - 1 的日期。要解決此問題,您必須使用無符號 32 位整數、帶符號 64 位整數或雙精度浮點數在伺服器上儲存所有日期。如果您的伺服器是用 PHP 編寫的,解決方法可能很簡單,只需升級到 PHP 8 或 7,並將硬體升級到 x86_64 或 IA64。如果您仍然使用其他硬體,可以嘗試在 32 位虛擬機器中模擬 64 位硬體,但大多數虛擬機器不支援這種虛擬化,因為穩定性可能會受到影響,效能肯定會大幅下降。

Y10K 問題(通常是客戶端)

在許多伺服器中,日期儲存為數字而不是字串——固定大小的數字,與格式無關(除了位元組序)。在公元 10000 年之後,這些數字將比以前略大一些,因此許多伺服器不會看到在公元 10000 年之後提交的表單的問題。

問題在於客戶端:解析年份中包含超過 4 位數字的日期。

html
<!--midnight of January 1st, 10000: the exact time of Y10K-->
<input type="datetime-local" value="+010000-01-01T05:00" />

就這麼簡單。只需為任意位數的數字做好準備。不要只為 5 位數字做好準備。以下是用程式設計方式設定值的 JavaScript 程式碼

js
function setValue(element, date) {
  const isoString = date.toISOString();
  element.value = isoString.substring(0, isoString.indexOf("T") + 6);
}

為什麼要擔心 Y10K 問題,因為它將在您去世後幾個世紀才發生?正是因為您已經去世了,因此使用您的軟體的公司將被迫繼續使用您的軟體,而沒有其他程式設計師能夠充分了解該系統來修復它。

另請參見