【问题标题】:Why are Python's datetime ISO-functions logically incorrect and buggy?为什么 Python 的日期时间 ISO 函数在逻辑上不正确且有问题?
【发布时间】:2011-04-27 03:55:31
【问题描述】:

python datetime .isoformat() 函数没有返回正确的信息,这让我有点吃惊。当向 fromtimestamp() 方法提供时区时,该函数正确返回 ISO 8601 格式的字符串。但是,在计算结果时会忽略时区。观察:

13:29 msimsonnet:~$ python
Python 2.7.1 (r271:86832, Jan 26 2011, 13:56:46) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
Running with pythonstartup.py
>>> import pytz,datetime
>>> datetime.datetime.fromtimestamp(1303876413).isoformat()
'2011-04-26T23:53:33'
>>> ny = pytz.timezone('America/New_York')
>>> sf = pytz.timezone('America/Los_Angeles')
>>> datetime.datetime.fromtimestamp(1303876413,ny).isoformat()
'2011-04-26T23:53:33-04:00'
>>> datetime.datetime.fromtimestamp(1303876413,sf).isoformat()
'2011-04-26T20:53:33-07:00'
>>> 

我在 EDT 中的计算机上运行此程序(格林威治标准时间为 -400)。时间 1303876413 实际上是 2011 年 4 月 26 日晚上 11:53:33,当时我第一次写这个问题。请注意,在第一个示例中,简单地请求 .isoformat() 返回 '2011-04-26T23:53:33',这是错误的 --- 它应该返回 '2011-04-26T23:53:33-04:00',因为它返回本地时间并且 Python 知道时区。第二个例子是正确的,但我在 NY 时区对象中干扰。第三个例子是错误的 --- Python 保留了时区,但没有相应地调整时间。

附录:

如果您阅读所有 cmets,您会发现我正在寻找的行为可以使用 utcfromtimestamp 而不是 fromtimestamp 找到

【问题讨论】:

  • 这里没有理由反对,这是一个很好的问题(如果有点情绪化......)

标签: python iso8601


【解决方案1】:

确保您使用的是“时区感知”datetime 对象,而不是“幼稚”对象。

为了使时区“感知”datetime 对象,您需要确保在创建时提供时区。

更多细节在这里: http://docs.python.org/library/datetime.html

此外,ISO 8601 需要时区,并且符合isoformat 。事实上,它根本不支持时区,只支持与 UTC 的时间偏移

ISO 8601 允许许多不同的格式,例如,这些都是有效的:

2011-04-27
2011-04-27 02:48Z
2011-04-27T02:48Z
2011-W17-3
2011-117

更多详情请见http://en.wikipedia.org/wiki/ISO_8601

编辑,以解决您的更新:

它没有错误,它可以正常工作,并且根据文档。天真的 datetime 对象只是没有任何时区信息,句号。因此,当您致电 isoformat() 时,没有理由期望他们能够为您提供时区信息。

当您使用时间戳创建对象时,它会根据 python 认为您的系统时区是什么来创建本地时间 datetime 对象。这就是为什么当您给它一个 posix 时间戳时,它会为您将其转换为您的本地时间。请注意,虽然 datetime 模块知道时间戳是 UTC,并且它知道您的本地时区,并且 fromtimestamp 使用该信息来创建 datetime 对象,但生成的对象仍然是幼稚的,并且与时区无关。如果你想使用时间戳,你不应该使用简单的 datetime 对象。

来自文档:

是否是一个朴素的日期时间对象 表示协调世界时 (UTC)、当地时间或某些地区的时间 其他时区完全取决于 程序,就像它取决于 程序是否特定编号 代表米、英里或质量。 天真的日期时间对象很容易 了解并与之合作,在 忽略某些方面的代价 现实。

这里是fromtimestamp 方法的文档(加粗):

返回本地日期和时间 对应于 POSIX 时间戳, 例如由 time.time() 返回。 如果 可选参数 tz 是否为 None 指定,时间戳被转换 到平台的本地日期和时间, 并且返回的日期时间对象是 天真。

如果你想让它考虑时区,你需要传递一个时区,它不会为你推断它。只是因为它没有做你认为它应该做的事情不要让它不合规或有问题。它按预期工作,并记录在案。这几乎与越野车相反。

【讨论】:

  • 维基百科页面显示“ISO 8601 中没有时区指示符。时间仅表示为当地时间或与 UTC 相关。”
  • 我以为这就是我所说的……“……与 UTC 相关”
  • 不应该 fromtimestamp() 方法自动将数据时间放入 GMT (Z),因为所有 Unix 时间戳都是相对于 GMT 的?
  • 我对示例进行了大幅修改,以便您现在可以看到 Python 有多么错误。
  • "生成的日期时间对象应该在那个时区" 它不在任何时区,这就是你所缺少的点。这是时区不知道。这只是一天中的日期和时间,仅此而已。 fromtimestamp 假设您希望在本地系统时间进行操作(大多数应用程序都希望这样做,因为通常您希望在本地时间查看内容)。如果您希望它们位于不同的时区,则可以传递 tz arg。
猜你喜欢
  • 2017-03-06
  • 1970-01-01
  • 1970-01-01
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 2017-04-12
  • 2020-07-08
  • 2012-08-20
相关资源
最近更新 更多