Skip to main content

Appendix A. ISO 8601 Collected ABNF

本信息基于1988年版本的ISO 8601。2000年修订版可能有一些变化。

说明

ISO 8601没有为其定义的日期和时间格式指定正式的语法。以下是从ISO 8601创建正式语法的尝试。这仅供参考,可能包含错误。ISO 8601仍然是权威参考。

歧义和解释

请注意,由于ISO 8601中的歧义,必须进行一些解释:

  1. 基本和扩展格式混合: ISO 8601不清楚是否允许混合基本格式和扩展格式。本语法允许混合。

  2. 24小时: ISO 8601不清楚是否仅在分钟和秒为0时才允许小时为24。本语法假设在任何上下文中都允许小时为24。

  3. 日期限制: 第5.7节中关于date-mday的限制适用。

  4. "T"分隔符: ISO 8601规定在某些情况下可以省略"T"。本语法要求使用"T"以避免歧义。

  5. 小数点: 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 8601RFC 3339
基本格式 (20020715)✅ 支持❌ 不支持
扩展格式 (2002-07-15)✅ 支持✅ 支持
周日期 (2002-W29-1)✅ 支持❌ 不支持
序数日期 (2002-196)✅ 支持❌ 不支持
部分日期 (2002-07)✅ 支持❌ 不支持
24小时 (2002-07-16T24:00:00)✅ 支持❌ 不支持
时区"Z"✅ 支持✅ 支持
数字时区偏移✅ 支持✅ 支持(强制)
小数秒✅ 支持✅ 支持

RFC 3339简化的原因

RFC 3339选择简化的子集是为了:

  1. 互操作性: 减少实现差异
  2. 明确性: 避免歧义
  3. 完整性: 要求完整的日期时间信息
  4. 简洁性: 更容易实现和测试

注意: 如果需要完整的ISO 8601功能(如周日期),应直接参考ISO 8601标准。RFC 3339专注于互联网协议中最常见的时间戳用例。