datetime.datetime.utcnow()
Почему этот datetime
не имеет информации о часовом поясе, учитывая, что это явно UTC datetime
?
Я бы ожидал, что это будет содержать tzinfo
.
datetime.datetime.utcnow()
Почему этот datetime
не имеет информации о часовом поясе, учитывая, что это явно UTC datetime
?
Я бы ожидал, что это будет содержать tzinfo
.
Это означает, что это временная зона наивная, поэтому вы не можете использовать ее с помощью 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())
- он может завершиться неудачно во время перехода на конец DST, когда локальное время неоднозначно.
Стандартные библиотеки 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)
Обратите внимание, что для 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)
Модуль 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. Я подозреваю, что это не включено, потому что для библиотеки с исходным текстом времени по умолчанию используются наивные даты для перекрестной совместимости.
Жюльен Данджу написал хорошую статью, объясняющую почему вы никогда не должны иметь дело с часовыми поясами. Выдержка:
Действительно, API-интерфейс Datetime Python всегда возвращает недопустимые объекты datetime, что очень печально. Действительно, как только вы получите один из этих объекта, нет способа узнать, что такое часовой пояс, поэтому эти объекты довольно "бесполезны" сами по себе.
Увы, хотя вы можете использовать utcnow()
, вы все равно не увидите информацию о часовом поясе, как вы обнаружили.
Рекомендации:
Всегда используйте известные объекты
datetime
, т.е. информацию о часовом поясе. Что убедитесь, что вы можете сравнивать их напрямую (осознавая и не осознаваяdatetime
объекты не сопоставимы) и вернет их правильно пользователям. Используйте pytz, чтобы иметь объекты часового пояса.Используйте ISO 8601 как входной и формат выходной строки. Используйте
datetime.datetime.isoformat()
для возврата timestamps как строка, форматированная с использованием этого формата, которая включает в себя информация о часовом поясе.Если вам нужно проанализировать строки, содержащие временные метки формата ISO 8601, вы можете положиться на
iso8601
, который возвращает отметки времени с правильными информация о часовом поясе. Это делает отметки времени сопоставимыми.
import datetime
>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'
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]
Даты UTC не нуждаются в информации о часовом поясе, так как это UTC, что по определению означает, что у них нет смещения.