为什么ISO-8601规范在小数点时似乎被普遍忽略?

时间:2013-12-20 08:56:10

标签: c# javascript php datetime iso8601

来自ISO-8601:2004(E)规范:

  

4.2.2.4带小数的表示

     

如果特定应用需要小时,分钟或秒的小数部分   可能包括在内。如果包含小数部分,则为低阶时间   元素(如果有的话)应省略,小数部分应为   从整数部分除以ISO中指定的小数符号   31-0,即逗号[,]或句号[。]。其中,逗号是   首选标志。

足够简单。因此,根据此规范,优选使用逗号分隔整数和小数部分(例如2014-01-01T00:00:00,123)来写入小数秒。然而,似乎在任何地方,只接受小数点(又名“完全停止”)!

现在我确定有一些语言或库将这一点考虑在内,我知道在很多情况下你可以自己提供格式的完整细节。但这似乎是对规范的明显监督,似乎各种程序员都犯了同样的错误。 除了纯粹的人为错误之外,还有其他原因吗?

以下是我测试的地方列表。如果您找到其他人,请随意编辑问题以扩充我的列表。感谢。

.NET / C#

DateTime dt = DateTime.Parse("2014-01-01T00:00:00,123");

抛出FormatException,并显示消息“字符串未被识别为有效的DateTime”。使用句点而不是逗号的相同内容会成功解析。

JavaScript日期对象

最新测试(截至撰写本文时)Chrome,Internet Explorer,Firefox和Node.js:

var dt = new Date('2014-01-01T00:00:00,123');

返回"Invalid Date"。使用句号可以正常工作。

带有moment.js

的JavaScript
var valid = moment("2014-01-01T00:00:00,123").isValid();

返回false。使用句点代替返回true

PHP

echo strtotime('2014-01-01T00:00:00,123');

返回一个空字符串。使用句号可以正常工作。

红宝石

require 'time'
puts Time.iso8601("2014-01-01T00:00:00,123")

发出运行时错误。虽然Time不会保留小数秒,但它不应该出错 - 而且如果使用句号代替它,它就会起作用。

2 个答案:

答案 0 :(得分:7)

RFC3339定义的

IETF仅指定.作为分隔符。

这是第5.6节:

5.6. Internet Date/Time Format

   The following profile of ISO 8601 [ISO8601] dates SHOULD be used in
   new protocols on the Internet.  This is specified using the syntax
   description notation defined in [ABNF].

   date-fullyear   = 4DIGIT
   date-month      = 2DIGIT  ; 01-12
   date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on
                             ; month/year
   time-hour       = 2DIGIT  ; 00-23
   time-minute     = 2DIGIT  ; 00-59
   time-second     = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second
                             ; rules
   time-secfrac    = "." 1*DIGIT
   time-numoffset  = ("+" / "-") time-hour ":" time-minute
   time-offset     = "Z" / time-numoffset

   partial-time    = time-hour ":" time-minute ":" time-second
                     [time-secfrac]
   full-date       = date-fullyear "-" date-month "-" date-mday
   full-time       = partial-time time-offset

   date-time       = full-date "T" full-time

答案 1 :(得分:4)

纯ISO-8601兼容解析器必须支持逗号和点。逗号并非严格要求,仅建议使用。因此,关于此标准,JavaScript,PHP,Ruby等的给定示例清楚地表明了这些解析器实现的错误。

RFC3339确实只支持一个子集(不包括逗号,也不包括小数小时或小数分钟!) - 所以不完全符合ISO标准。

XML-schema类似。不幸的是,它排除了逗号(参见W3C文档)。

所以你问为什么?这是我的怀疑:编程世界受到美国的强烈支配。在美国文化中,点用作数字中的小数分隔符。因此,大多数开发此类框架,标准和库的人都坐在美国,错误地认为点是准国际标准。

所以问题仍然存在,为什么ISO使用/推荐使用逗号?我完全不知道,但我们都知道ISO集团的办公室位于巴黎,而不是美国。在欧洲(英国除外),逗号通常作为小数分隔符,也是文化方面的首选。

最后,并非所有解析器都是错误的。至少Joda-Time也支持逗号,但在打印时更喜欢使用点。 NodaTime的情况如何?我希望至少与Joda-Time相似。请继续支持解析逗号。从欧洲的角度来看,很高兴看到并非所有的东西都像美国人一样; - )。