为什么 Python 的日期时间 ISO 函数在逻辑上不正确且存在错误?
我有点惊讶 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 知道时区。第二个例子是正确的,但我堵塞了纽约时区对象。第三个例子是错误的——Python 保留了时区,但没有相应地调整时间。
附录:
如果您阅读了所有评论,您会发现我正在寻找的行为可以使用 utcfromtimestamp
而不是 fromtimestamp
找到
I'm kind of stunned that the python datetime
.isoformat()
function doesn't return correct information. The function correctly returns an ISO 8601-formatted string when a timezone is provided to the fromtimestamp() method. However, the timezone is ignored in the calculation of the resultant. Observe:
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'
>>>
I'm running this on a computer that's in EDT (-400 from GMT). The time 1303876413 is actually 11:53:33pm on April 26, 2011, when I first wrote the question. Notice that in the first example simply requesting .isoformat()
returns '2011-04-26T23:53:33'
, which is wrong --- it should return '2011-04-26T23:53:33-04:00'
, since it's returning local time and Python knows the timezone. The second example is correct, but I am jamming in the NY timezone object. The third example is just wrong --- Python is preserving the timezone, but it's not adjusting the time accordingly.
ADDENDUM:
If you read all of the comments, you'll see that the behavior I was looking for can be found using utcfromtimestamp
rather than fromtimestamp
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
确保您使用的是“时区感知”
datetime
对象,而不是“天真的”对象。为了使时区“感知”
datetime
对象,您需要确保在创建它时提供时区。更多详细信息请参见:
http://docs.python.org/library/datetime.html
另外,ISO 8601 不需要时区,并且
isoformat
兼容。事实上,它根本不支持时区,只支持 UTC 的时间偏移。ISO 8601 允许许多不同的格式,例如,这些都是有效的:
请参阅 http://en.wikipedia.org /wiki/ISO_8601 了解更多详细信息。
编辑,以解决您的更新:
它没有错误,它可以正常工作,并且根据文档。天真的日期时间对象只是没有任何时区信息,句点。因此,没有理由期望当您调用
isoformat()
时他们能够为您提供时区信息。当您使用时间戳创建对象时,它会根据 python 认为您的系统时区的值创建本地时间日期时间对象。这就是为什么当您给它一个 posix 时间戳时,它会将其转换为您的本地时间。请注意,虽然 datetime 模块知道时间戳是 UTC,并且它知道您的本地时区,并且
fromtimestamp
使用该信息创建 datetime 对象,但生成的对象仍然是幼稚的并且不执行任何操作关于时区。如果您想使用时间戳,则不应使用简单的日期时间对象。来自文档:
以下是
fromtimestamp
方法的文档(添加粗体):如果你想让它考虑时区,你需要传递一个时区,它不会为你推断它。只是因为它没有按照你的想法去做应该做的事情不会使其不合规或有问题。它按预期工作,并且如记录的那样。这与越野车几乎相反。
Make sure you are using "timezone aware"
datetime
objects, not "naive" objects.In order to make a timezone "aware"
datetime
object you need to be sure to provide the timezone when you create it.More details are here:
http://docs.python.org/library/datetime.html
Also, ISO 8601 does not require timezone, and
isoformat
is compliant. In fact, it doesn't support timezone at all, only time offsets from UTC.ISO 8601 allows many different formats, for example, these are all valid:
See http://en.wikipedia.org/wiki/ISO_8601 for more details.
Edit, to address your updates:
It's not buggy, it works properly, and according to the docs. Naive datetime objects just don't have any time zone information, period. So there's no reason to expect that they'd be able to give you timezone information when you call
isoformat()
.When you create an object using the timestamp, it makes a local time datetime object based on whatever python thinks your system time zone is. That's why when you give it a posix timestamp, it converts it to your local time for you. Note that while the datetime module knows that a timestamp is UTC, and it knows your local time zone, and
fromtimestamp
uses that information to create a datetime object, the resulting object is still naive and doesn't anything about time zones. If you want to use timestamps, you shouldn't use naive datetime objects.From the docs:
Here is the documentation for the
fromtimestamp
method (bolding added):If you want it to consider time zone, you need to pass a time zone, it won't infer it for you. Just because it doesn't do what you think it should do does not make it non-compliant or buggy. It works as intended, and as is documented. That's pretty much the opposite of buggy.