Что я должен сделать
У меня есть объект datetime, не поддерживающий часовой пояс, к которому мне нужно добавить часовой пояс, чтобы иметь возможность сравнивать его с другими объектами datetime с учетом часового пояса. Я не хочу преобразовывать все мое приложение в часовой пояс, не подозревая об этом унаследованном случае.
Что я пробовал
Во-первых, чтобы продемонстрировать проблему:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> import pytz
>>> unaware = datetime.datetime(2011,8,15,8,15,12,0)
>>> unaware
datetime.datetime(2011, 8, 15, 8, 15, 12)
>>> aware = datetime.datetime(2011,8,15,8,15,12,0,pytz.UTC)
>>> aware
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> aware == unaware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
Сначала я попробовал astimezone:
>>> unaware.astimezone(pytz.UTC)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: astimezone() cannot be applied to a naive datetime
>>>
Неудивительно, что это не удалось, так как он пытается конвертировать. Заменить казалось лучшим выбором (согласно Python: как получить значение datetime.today (), которое «учитывает часовой пояс»? ):
>>> unaware.replace(tzinfo=pytz.UTC)
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> unaware == aware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
>>>
Но, как вы можете видеть, замена, кажется, устанавливает tzinfo, но не делает объект осведомленным. Я собираюсь вернуться к лечению входной строки, чтобы иметь часовой пояс перед его синтаксическим анализом (я использую dateutil для анализа, если это имеет значение), но это кажется невероятно грязным.
Кроме того, я пробовал это и в Python 2.6 и Python 2.7, с одинаковыми результатами.
контекст
Я пишу парсер для некоторых файлов данных. Существует старый формат, который мне нужно поддерживать, когда строка даты не имеет индикатора часового пояса. Я уже исправил источник данных, но мне все еще нужно поддерживать устаревший формат данных. Однократное преобразование устаревших данных не подходит по различным причинам бизнес-BS. Хотя в целом мне не нравится идея жесткого кодирования часового пояса по умолчанию, в этом случае он кажется наилучшим вариантом. Я с достаточной уверенностью знаю, что все унаследованные данные находятся в UTC, поэтому я готов принять на себя риск невыполнения этого требования в этом случае.
unaware.replace()
вернулсяNone
бы, если бы он изменялunaware
объект на месте. REPL показывает, что.replace()
возвращает новыйdatetime
объект здесь.import datetime; datetime.datetime.now(datetime.timezone.utc)
tz
аргумент, чтобы быть более читабельным:datetime.datetime.now(tz=datetime.timezone.utc)
Ответы:
В общем, чтобы сделать наивный точный часовой пояс даты и времени, используйте метод локализации :
Для часового пояса UTC использование на самом деле не является необходимым,
localize
так как нет никакого расчета летнего времени для обработки:работает. (
.replace
возвращает новую дату и время; она не изменяетсяunaware
.)источник
aware = datetime(..., tz)
используйте.localize()
вместо этого.tz.localize(..., is_dst=None)
утверждает, что это не так.Во всех этих примерах используется внешний модуль, но вы можете достичь того же результата, используя только модуль datetime, как также представлено в этом ответе SO :
Меньше зависимостей и нет проблем с Pytz.
ПРИМЕЧАНИЕ: Если вы хотите использовать это с python3 и python2, вы можете использовать это также для импорта часового пояса (жестко задано для UTC):
источник
pytz
проблем, я рад, что прокрутил немного вниз! Не хотел заниматьсяpytz
на моих удаленных серверах действительно :)from datetime import timezone
работает в py3, но не py2.7.dt.replace(tzinfo=timezone.utc)
возвращает новое время и дату, оно не изменяетсяdt
на месте. (Я буду редактировать, чтобы показать это).tz = pytz.timezone('America/Chicago')
Я использовал от dt_aware до dt_unaware
и dt_unware для dt_aware
но ответ раньше тоже хорошее решение.
источник
localtz.localize(dt_unware, is_dst=None)
чтобы вызвать исключение, если оноdt_unware
представляет собой несуществующее или неоднозначное местное время (примечание: в предыдущей редакции вашего ответа такой проблемы неlocaltz
было, когда было UTC, потому что в UTC нет переходов DSTЯ использую это утверждение в Django, чтобы преобразовать неосведомленное время в осведомленное:
источник
Я согласен с предыдущими ответами, и это нормально, если вы можете начать в UTC. Но я думаю, что это также распространенный сценарий, когда люди работают со значением, учитывающим tz, которое имеет дату и время, а не местный часовой пояс UTC.
Если бы вы просто пошли по имени, можно было бы предположить, что replace () будет применим и создаст правильный объект с указанием даты и времени. Это не вариант.
замена (tzinfo = ...) кажется случайной в своем поведении . Поэтому бесполезно. Не используйте это!
localize - это правильная функция для использования. Пример:
Или более полный пример:
дает мне текущее местное время с учетом даты и времени:
источник
replace(tzinfo=...)
это в часовом поясе, отличном от UTC, испортит ваше время. Я получил-07:53
вместо,-08:00
например. См stackoverflow.com/a/13994611/1224827replace(tzinfo=...)
неожиданного поведения?Используйте,
dateutil.tz.tzlocal()
чтобы получить часовой пояс в вашем использованииdatetime.datetime.now()
иdatetime.datetime.astimezone()
:Обратите внимание, что
datetime.astimezone
сначала будет преобразован вашdatetime
объект в UTC, а затем в часовой пояс, который аналогичен вызовуdatetime.replace
с исходной информацией часового поясаNone
.источник
.replace(tzinfo=dateutil.tz.UTC)
.replace(tzinfo=datetime.timezone.utc)
Это систематизирует ответы @ Sérgio и @ unutbu . Он будет «просто работать» с
pytz.timezone
объектом или строкой часового пояса IANA .Это похоже на то, что
datetime.localize()
(или.inform()
или.awarify()
) должно делать, принимать как строки, так и объекты часового пояса для аргумента tz и по умолчанию UTC, если часовой пояс не указан.источник
Python 3.9 добавляет
zoneinfo
модуль, поэтому теперь нужна только стандартная библиотека!Прикрепить часовой пояс:
Присоедините местный часовой пояс системы:
Впоследствии он правильно конвертируется в другие часовые пояса:
Википедия список доступных часовых поясов
Windows не имеет базы данных системного часового пояса, поэтому здесь необходим дополнительный пакет:
Существует бэкпорт, позволяющий использовать в Python 3.6 до 3.8 :
Затем:
источник
pip install tzdata
В формате ответа unutbu; Я сделал служебный модуль, который обрабатывает подобные вещи с более интуитивным синтаксисом. Может быть установлен с помощью пипа.
источник
для тех, кто просто хочет узнать дату и время
источник
совершенно новый для Python, и я столкнулся с той же проблемой. Я нахожу это решение довольно простым, и для меня оно отлично работает (Python 3.6):
источник
Переключение между часовыми поясами
источник