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
对象