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
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.
精彩评论