ISO 8601 日期时间应该使用 hypen-minus (U+002D) 还是 hypen (U+2010)?

Should hypen-minus (U+002D) or hypen (U+2010) be used for ISO 8601 datetimes?

提问人:deadlock 提问时间:10/13/2023 最后编辑:Remy Lebeaudeadlock 更新时间:10/19/2023 访问量:78

问:

Python 解释器在生成 ISO-8601 格式的日期/时间字符串时提供以下内容:

>>> import datetime
>>> datetime.datetime.now().isoformat(timespec='seconds')
'2023-10-12T22:35:02'

请注意,字符串中的“-”字符是 hypen-minus 字符。当向后生成 datetime 对象时,我们执行以下操作:

>>> datetime.datetime.strptime('2023-10-12T22:35:02', '%Y-%m-%dT%H:%M:%S')
datetime.datetime(2023, 10, 12, 22, 35, 2)

这一切都检查出来了。

但是,有时,当 ISO-8601 格式的日期/时间字符串从外部源提供时,例如在 GET/POST 请求或文件中发送的参数,连字符将作为 (U+2010) 字符发送,这会导致解析中断:.csv

>>> datetime.datetime.strptime('2023‐10‐12T22:35:02', '%Y-%m-%dT%H:%M:%S')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/_strptime.py", line 568, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/_strptime.py", line 349, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data '2023‐10‐12T22:35:02' does not match format '%Y-%m-%dT%H:%M:%S'

正确的标准是什么?是 Python 在通过 转换时给出的 hypen-minus U+002D 还是 hypen U+2010?-.isoformat()

最好同时接受两者吗?

python 日期时间 unicode ascii iso8601

评论

1赞 deceze 10/13/2023
简单的 ASCII 减号是意料之中的,因为任何非 ASCII 都会带来更复杂的编码注意事项。
0赞 Joran Beasley 10/13/2023
这不是您的 API 应该支持的东西......简单的 ASCII ...这是方法
0赞 Codist 10/13/2023
我的理解是,如果原点(互换)字符集不包括连字符减号 ('\u002d'),则应使用减号 ('\u2212')
0赞 FObersteiner 10/13/2023
根据维基百科上提供的信息,建议使用非 ASCII 字符来表示例如负 UTC 偏移量。因此,尽管这不适用于年、月和日之间的分隔符,但期望格式化的日期时间仅ISO8601 ASCII 是不安全的。

答:

-2赞 RandomCoder368 10/13/2023 #1

我建议使用 ASCII 0x2D,因为 ASCII 非常常用,并且会更少中断。出于您的目的,如果您关心兼容性,请将其替换为 ASCII,用于 ISO 8601。如果你不在乎,就让你的用户去做(我推荐ASCII).replace("\u2010", "-")replace("-", "\u2010")

评论

0赞 Remy Lebeau 10/19/2023
这并不能回答OP的问题。他们没有征求意见,而是征求官方标准。
4赞 Keith Thompson 10/13/2023 #2

ISO 8601 标准不是免费公开的。也许有副本的人可以发布更明确的答案。

ISO 发布了 ISO 8601 标准的简要摘要。摘要始终使用 HYPHEN-MINUS (0x2D)。(感谢 Giacomo Catenazzi 在评论中指出这一点。

RFC 3339 基于 ISO 8601,它始终使用 HYPHEN-MINUS 字符 (0x2D),而不是 Unicode HYPHEN 字符 (0x2010)。请注意,使用 HYPHEN-MINUS(ASCII 字符)可以避免出现不同字符集的问题。

参考资料: https://datatracker.ietf.org/doc/html/rfc3339

如果创建的时间戳旨在与 ISO 8601 保持一致,则绝对应使用 HYPHEN-MINUS。

如果您收到的时间戳本应是 ISO 8601,但它们包含连字符 (0x2010) 字符,则可以选择接受它们。是否应该接受它们取决于项目的要求。如果可能,请询问生成时间戳的人员使用正确的连字符-减号字符。一旦你开始接受非标准输入,你可能不得不做大量的工作。

评论

1赞 skomisa 10/13/2023
需要明确的是,ISO 8601 是公开的,但不是免费公开的。我不是律师,但我怀疑直接引用它可能会侵犯版权。(不过,我很高兴在这一点上得到纠正。
1赞 Giacomo Catenazzi 10/13/2023
ISO在以下方面发表了摘要:iso.org/iso-8601-date-and-time-format.html。不是真正的标准,但他们写了一个日期,他们正在使用0x2D。如果 ISO 8601 页面上的 ISO 使用了错误的字符,那将是令人尴尬的。
0赞 skomisa 10/15/2023
虽然与问题或您的答案没有直接关系,但元问题是否可以引用 ISO 标准? 可能仍然感兴趣。基于该元讨论,我的理解是,即使您购买了 ISO 8601 的副本,您仍然不能在 SO 上自由引用它。