Appendix A. ISO 8601 Collected ABNF
本信息基于1988年版本的ISO 8601。2000年修订版可能有一些变化。
说明
ISO 8601没有为其定义的日期和时间格式指定正式的语法。以下是从ISO 8601创建正式语法的尝试。这仅供参考,可能包含错误。ISO 8601仍然是权威参考。
歧义和解释
请注意,由于ISO 8601中的歧义,必须进行一些解释:
-
基本和扩展格式混合: ISO 8601不清楚是否允许混合基本格式和扩展格式。本语法允许混合。
-
24小时: ISO 8601不清楚是否仅在分钟和秒为0时才允许小时为24。本语法假设在任何上下文中都允许小时为24。
-
日期限制: 第5.7节中关于date-mday的限制适用。
-
"T"分隔符: ISO 8601规定在某些情况下可以省略"T"。本语法要求使用"T"以避免歧义。
-
小数点: ISO 8601要求(在5.3.1.3节中)如果小于1,小数部分前必须有"0"。ISO 8601的附录B.2给出了小数部分前没有"0"的示例。本语法假设5.3.1.3节是正确的,附录B.2有误。
完整的ISO 8601 ABNF语法
date-century = 2DIGIT ; 00-99
date-decade = DIGIT ; 0-9
date-subdecade = DIGIT ; 0-9
date-year = date-decade date-subdecade
date-fullyear = date-century date-year
date-month = 2DIGIT ; 01-12
date-wday = DIGIT ; 1-7 ; 1 is Monday, 7 is Sunday
date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31
date-yday = 3DIGIT ; 001-365, 001-366
date-week = 2DIGIT ; 01-52, 01-53
datepart-fullyear = [date-century] date-year ["-"]
datepart-ptyear = "-" [date-subdecade ["-"]]
datepart-wkyear = datepart-fullyear / datepart-ptyear
dateopt-century = "-" / date-century
dateopt-fullyear = "-" / datepart-fullyear
dateopt-year = "-" / (date-year ["-"])
dateopt-month = "-" / (date-month ["-"])
dateopt-week = "-" / (date-week ["-"])
datespec-full = datepart-fullyear date-month ["-"] date-mday
datespec-year = date-century / dateopt-century date-year
datespec-month = "-" dateopt-year date-month [["-"] date-mday]
datespec-mday = "--" dateopt-month date-mday
datespec-week = datepart-wkyear "W"
(date-week / dateopt-week date-wday)
datespec-wday = "---" date-wday
datespec-yday = dateopt-fullyear date-yday
date = datespec-full
/ datespec-year
/ datespec-month
/ datespec-mday
/ datespec-week
/ datespec-wday
/ datespec-yday
time-hour = 2DIGIT ; 00-24
time-minute = 2DIGIT ; 00-59
time-second = 2DIGIT ; 00-58, 00-59, 00-60
time-fraction = ("," / ".") 1*DIGIT
time-numoffset = ("+" / "-") time-hour [[":"] time-minute]
time-zone = "Z" / time-numoffset
timeopt-hour = "-" / (time-hour [":"])
timeopt-minute = "-" / (time-minute [":"])
timespec-hour = time-hour [[":"] time-minute [[":"] time-second]]
timespec-minute = timeopt-hour time-minute [[":"] time-second]
timespec-second = "-" timeopt-minute time-second
timespec-base = timespec-hour / timespec-minute / timespec-second
time = timespec-base [time-fraction] [time-zone]
iso-date-time = date "T" time
RFC 3339 vs 完整ISO 8601
RFC 3339是ISO 8601的一个受限子集,而不是完整实现:
| 特性 | ISO 8601 | RFC 3339 |
|---|---|---|
| 基本格式 (20020715) | ✅ 支持 | ❌ 不支持 |
| 扩展格式 (2002-07-15) | ✅ 支持 | ✅ 支持 |
| 周日期 (2002-W29-1) | ✅ 支持 | ❌ 不支持 |
| 序数日期 (2002-196) | ✅ 支持 | ❌ 不支持 |
| 部分日期 (2002-07) | ✅ 支持 | ❌ 不支持 |
| 24小时 (2002-07-16T24:00:00) | ✅ 支持 | ❌ 不支持 |
| 时区"Z" | ✅ 支持 | ✅ 支持 |
| 数字时区偏移 | ✅ 支持 | ✅ 支持(强制) |
| 小数秒 | ✅ 支持 | ✅ 支持 |
RFC 3339简化的原因
RFC 3339选择简化的子集是为了:
- 互操作性: 减少实现差异
- 明确性: 避免歧义
- 完整性: 要求完整的日期时间信息
- 简洁性: 更容易实现和测试
注意: 如果需要完整的ISO 8601功能(如周日期),应直接参考ISO 8601标准。RFC 3339专注于互联网协议中最常见的时间戳用例。