为什么 Python 的日期时间 ISO 函数在逻辑上不正确且存在错误?

发布于 2024-11-03 12:47:05 字数 1270 浏览 5 评论 0原文

我有点惊讶 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怪我入戏太深 2024-11-10 12:47:05

确保您使用的是“时区感知”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 了解更多详细信息。

编辑,以解决您的更新:

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

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

来自文档:

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

以下是 fromtimestamp 方法的文档(添加粗体):

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

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

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:

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

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:

Whether a naive datetime object
represents Coordinated Universal Time
(UTC), local time, or time in some
other timezone is purely up to the
program, just like it’s up to the
program whether a particular number
represents metres, miles, or mass.
Naive datetime objects are easy to
understand and to work with, at the
cost of ignoring some aspects of
reality.

Here is the documentation for the fromtimestamp method (bolding added):

Return the local date and time
corresponding to the POSIX timestamp,
such as is returned by time.time(). If
optional argument tz is None or not
specified, the timestamp is converted
to the platform’s local date and time,
and the returned datetime object is
naive.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文