Почему функции даты и времени Python логически некорректны и содержат ошибки? - PullRequest
3 голосов
/ 27 апреля 2011

Я немного ошеломлен тем, что функция python datetime .isoformat() не возвращает правильную информацию. Функция корректно возвращает строку в формате ISO 8601, когда часовой пояс предоставлен методу fromtimestamp (). Тем не менее, часовой пояс игнорируется при расчете результирующего. Обратите внимание:

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 от GMT). Время 1303876413 - фактически 23:53:33 26 апреля 2011 года, когда я впервые написал вопрос. Обратите внимание, что в первом примере простой запрос .isoformat() возвращает '2011-04-26T23:53:33', что неверно - он должен возвращать '2011-04-26T23:53:33-04:00', так как он возвращает местное время, а Python знает часовой пояс. Второй пример верен, но я застрял в объекте часового пояса Нью-Йорка. Третий пример просто неверен - Python сохраняет часовой пояс, но не корректирует время соответствующим образом.

ДОПОЛНЕНИЕ:

Если вы прочитаете все комментарии, вы увидите, что искомое поведение можно найти с помощью utcfromtimestamp вместо fromtimestamp

1 Ответ

17 голосов
/ 27 апреля 2011

Убедитесь, что вы используете datetime объекты, «осведомленные о часовом поясе», а не «наивные» объекты.

Чтобы сделать объект «1004 *» осведомленным о часовом поясе, вы должны обязательно предоставитьчасовой пояс при его создании.

Более подробная информация здесь: 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().

Когда вы создаете объект, используя метку времени, он создает объект даты и времени локального времени на основе любого питона.думает, что ваш системный часовой пояс.Вот почему, когда вы даете ему метку времени posix, она конвертирует ее в ваше местное время.Обратите внимание, что хотя модуль datetime знает, что временная метка является UTC, и знает ваш местный часовой пояс, и fromtimestamp использует эту информацию для создания объекта datetime, результирующий объект по-прежнему наивен и ничего не делает с часовыми поясами.Если вы хотите использовать временные метки, вы не должны использовать наивные объекты даты и времени.

Из документов:

Представляет ли наивный объект даты / времени координированное универсальное время (UTC), местное времяили время в каком-то другом часовом поясе зависит только от программы, точно так же, как от программы зависит, представляет ли конкретное число метры, мили или массу.Наивные объекты даты и времени легко понять и работать с ними, за счет игнорирования некоторых аспектов реальности.

Вот документация для метода fromtimestamp (выделено жирным шрифтом):

Возвращает локальную дату и время, соответствующие метке времени POSIX, например, возвращается функцией time.time (). Если необязательный аргумент tz равен None или не указан, отметка времени преобразуется в локальную дату и время платформы, а возвращаемый объект datetime является наивным.

Если выЕсли вы хотите, чтобы он учитывал часовой пояс, вам нужно пропустить часовой пояс, он не будет выводить его для вас. Тот факт, что он не выполняет то, что, как вы думаете, должен делать, не делает его несовместимым или ошибочным.Он работает как задумано, и как задокументированоЭто в значительной степени противоположно багги.

...