HTML 中使用的日期和時間格式
某些 HTML 元素使用日期和/或時間值。本文介紹了指定這些值的字串的格式。
使用此類格式的元素包括 <input> 元素的某些形式,這些形式允許使用者選擇或指定日期、時間或兩者,以及 <ins> 和 <del> 元素,它們的 datetime 屬性指定插入或刪除內容發生的日期或日期和時間。
示例
在深入研究 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 字串表示,其值範圍從 01 到 12。請參閱每月天數部分中的表格,瞭解月份數字及其對應的名稱(以及天數)。
每月的天數
月份數字 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)以及兩位數的年份周值組成。
年份周是介於 01 和 53 之間的兩位數字符串。每個星期從星期一開始,到星期天結束。這意味著 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+003A)、然後是兩位數的分鐘組成。分鐘之後可以選擇新增另一個冒號和兩位數的秒數。毫秒可以選擇透過新增一個小數點字元(“.”、U+002E)後跟一位、兩位或三位數字來指定。
還有一些額外的基本規則
- 小時始終使用 24 小時制指定,其中
00為午夜,晚上 11 點為23。不允許00–23範圍之外的任何值。 - 分鐘必須是介於
00和59之間的兩位數。不允許該範圍之外的任何值。 - 如果省略秒數(僅指定精確到分鐘的時間),冒號不應該跟隨分鐘數。
- 如果指定了秒數並且是整數,則後面不應跟隨小數點。
- 如果指定了秒數並且是整數,則後面不應跟隨小數點。
- 如果包含了秒數的小數部分,它可以是一到三位數字長,表示毫秒數。它位於時間字串秒數部分之後的小數點之後。
| 時間字串 | 時間 |
|---|---|
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時省略它來實現的。
| 日期/時間字串 | 規範化的日期/時間字串 | 實際日期和時間 |
|---|---|---|
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 年 1 月 28 日上午 11:38:00.01 |
0170-07-31T22:00:00 |
請注意,此日期的規範化形式刪除了“ |
170 年 7 月 31 日晚上 10:00 |
全域性日期和時間字串
全球日期和時間字串指定日期和時間以及發生的時區。**有效的全球日期和時間字串**與本地日期和時間字串的格式相同,只是在時間之後附加了一個時區字串,位於時間之後。
時區偏移字串
時區偏移字串指定從標準時間基線正負小時和分鐘的偏移量。有兩個標準時間基線,它們非常接近,但並不完全相同
- 對於協調世界時(UTC)在 1960 年代初建立後的日期,時間基線為
Z,偏移量表示特定時區相對於 0º 經線(經過英國格林威治皇家天文臺)的子午線時間的偏移量。 - 對於 UTC 之前的日期,時間基線則用UT1表示,它是子午線上的當代地球太陽時間。
時區字串立即附加在日期和時間字串中的時間之後。您可以指定“Z”作為時區偏移字串,以指示時間以 UTC 指定。否則,時區字串將按如下方式構造
- 一個表示偏移量符號的字元:加號(“
+”或 U+002B)表示位於子午線以東的時區,減號(“-”或 U+002D)表示位於子午線以西的時區。 - 一個兩位數表示該時區相對於子午線的偏移小時數。此值必須介於
00和23之間。 - 可選的冒號("
:")字元。 - 兩位數的分鐘數,表示超過小時的分鐘數;該值必須介於
00和59之間。
雖然此格式允許時區在 -23:59 到 +23:59 之間,但當前時區偏移範圍為 -12:00 到 +14:00,並且當前沒有時區偏離小時數以外的任何其他值,例如 00、30 或 45 分鐘。這可能會隨時發生變化,因為國家/地區可以隨時以任何他們希望的方式更改其時區。
| 全域性日期和時間字串 | 實際全域性日期和時間 | 本初子午線上的日期和時間 |
|---|---|---|
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 位數字的日期。
<!--midnight of January 1st, 10000: the exact time of Y10K-->
<input type="datetime-local" value="+010000-01-01T05:00" />
就這麼簡單。只需為任意位數的數字做好準備。不要只為 5 位數字做好準備。以下是用程式設計方式設定值的 JavaScript 程式碼
function setValue(element, date) {
const isoString = date.toISOString();
element.value = isoString.substring(0, isoString.indexOf("T") + 6);
}
為什麼要擔心 Y10K 問題,因為它將在您去世後幾個世紀才發生?正是因為您已經去世了,因此使用您的軟體的公司將被迫繼續使用您的軟體,而沒有其他程式設計師能夠充分了解該系統來修復它。
另請參見
<input><ins>和<del>:請參閱datetime屬性,它指定內容插入或刪除的日期或本地日期和時間- ISO 8601 規範
- 數字和日期 在 JavaScript 指南 中
- JavaScript
Date物件 - 用於為給定區域設定格式化日期和時間的
Intl.DateTimeFormat物件