Почему datetime.datetime.utcnow () не содержит информацию о часовом поясе? - PullRequest
221 голосов
/ 25 февраля 2010
datetime.datetime.utcnow()

Почему у этого datetime нет информации о часовом поясе, если это явно UTC datetime?

Я ожидаю, что это будет содержать tzinfo.

Ответы [ 8 ]

169 голосов
/ 25 февраля 2010

Это означает, что часовой пояс наивен, поэтому вы не можете использовать его с datetime.astimezone

Вы можете указать часовой пояс, подобный этому

import pytz  # 3rd party: $ pip install pytz

u = datetime.utcnow()
u = u.replace(tzinfo=pytz.utc) #NOTE: it works only with a fixed utc offset

теперь вы можете менять часовые пояса

print(u.astimezone(pytz.timezone("America/New_York")))

Чтобы получить текущее время в заданном часовом поясе, вы можете передать tzinfo datetime.now() напрямую:

#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz

print(datetime.now(pytz.timezone("America/New_York")))

Он работает для любого часового пояса, включая те, которые соблюдают переход на летнее время (DST), т. Е. Он работает для часовых поясов, которые могут иметь разные смещения utc в разное время (нефиксированное смещение utc). Не используйте tz.localize(datetime.now()) - может произойти сбой во время перехода в конец летнего времени, когда местное время неоднозначно.

98 голосов
/ 10 июля 2014

Обратите внимание, что для Python 3.2 и далее модуль datetime содержит datetime.timezone. Документация для datetime.utcnow() гласит:

Точную дату и время UTC можно узнать по телефону datetime.now(timezone.utc).

Так что вы можете сделать:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)
67 голосов
/ 25 февраля 2010

Стандартные библиотеки Python не включают в себя классы tzinfo (но см. Pep 431 ). Я могу только догадываться по причинам. Лично я думаю, что было ошибкой не включать класс tzinfo для UTC, потому что он достаточно спорный, чтобы иметь стандартную реализацию.

Редактировать: Хотя в библиотеке нет реализации, в качестве примера в документации tzinfo приводится .

from datetime import timedelta, tzinfo

ZERO = timedelta(0)

# A UTC class.

class UTC(tzinfo):
    """UTC"""

    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

Чтобы использовать его, чтобы получить текущее время как осведомленный объект datetime:

from datetime import datetime 

now = datetime.now(utc)

В Python 3.2 + есть datetime.timezone.utc:

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)
19 голосов
/ 07 ноября 2013

Модуль pytz - это одна опция, и есть другая python-dateutil, которая, хотя и является пакетом стороннего производителя, может быть уже доступна в зависимости от других зависимостей и операционной системы.

Я просто хотел включить эту методологию для справки - если вы уже установили python-dateutil для других целей, вы можете использовать tzinfo вместо дублирования с pytz

import datetime
import dateutil.tz

# Get the UTC time with datetime.now:
utcdt = datetime.datetime.now(dateutil.tz.tzutc())

# Get the UTC time with datetime.utcnow:
utcdt = datetime.datetime.utcnow()
utcdt = utcdt.replace(tzinfo=dateutil.tz.tzutc())

# For fun- get the local time
localdt = datetime.datetime.now(dateutil.tz.tzlocal())

Я склонен согласиться, что звонки на utcnow должны включать информацию о часовом поясе UTC. Я подозреваю, что это не включено, потому что собственная библиотека datetime по умолчанию имеет наивные datetime для перекрестной совместимости.

9 голосов
/ 08 сентября 2015

Жюльен Данджу написал хорошую статью, объясняющую , почему вы никогда не должны иметь дело с часовыми поясами . Выдержка:

Действительно, Python datetime API всегда возвращает незнакомые объекты datetime, что очень неудачно. Действительно, как только вы получите один из этого объект, нет никакого способа узнать, что такое часовой пояс, поэтому эти объекты довольно "бесполезны" сами по себе.

Увы, хотя вы можете использовать utcnow(), вы все равно не увидите информацию о часовом поясе, как обнаружили.

Рекомендации:

  • Всегда используйте осведомленные datetime объекты, т.е. с информацией о часовом поясе. Тот удостоверяется, что вы можете сравнить их напрямую (осведомлен и не осведомлен datetime объекты не сопоставимы) и будут правильно возвращать их пользователям. Плечо pytz , чтобы иметь объекты часового пояса.

  • Используйте ISO 8601 в качестве входа и формат выходной строки. Используйте datetime.datetime.isoformat(), чтобы вернуться временные метки в виде строки, отформатированной с использованием этого формата, который включает в себя информация о часовом поясе.

  • Если вам нужно проанализировать строки, содержащие метки времени в формате ISO 8601, Вы можете положиться на iso8601, который возвращает временные метки с правильными информация о часовом поясе. Это делает временные метки напрямую сопоставимыми.

4 голосов
/ 02 сентября 2017

Для добавления timezone информации в Python 3.2 +

import datetime

>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'
0 голосов
/ 29 июля 2014
from datetime import datetime 
from dateutil.relativedelta import relativedelta
d = datetime.now()
date = datetime.isoformat(d).split('.')[0]
d_month = datetime.today() + relativedelta(months=1)
next_month = datetime.isoformat(d_month).split('.')[0]
0 голосов
/ 25 февраля 2010

Даты в формате UTC не нуждаются в информации о часовом поясе, так как они являются UTC, что по определению означает, что они не имеют смещения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...