Python: как получить значение datetime.сегодня () это"часовой пояс"?

Я пытаюсь вычесть одно значение даты из значения datetime.today() чтобы вычислить, как давно было-то. Но он жалуется:

TypeError: can't subtract offset-naive and offset-aware datetimes

значение datetime.today() не похоже, что "часовой пояс знает", в то время как мое другое значение даты. Как получить значение datetime.today() что часовой пояс в курсе? Прямо сейчас он дает мне время по местному времени, которое, оказывается, PST, т. е. UTC-8hrs. В худшем случае, есть ли способ вручную ввести значение часового пояса в

14 ответов


в стандартной библиотеке нет кросс-платформенного способа создания осведомленных часовых поясов без создания собственного класса часовых поясов.

на Windows, есть win32timezone.utcnow(), но это часть pywin32. Я бы скорее предложил использовать pytz библиотека, который имеет постоянно обновляемую базу самых часовых поясов.

работа с локальными часовыми поясами может быть очень сложной (см. ссылки "дальнейшее чтение" ниже), поэтому вы можете использовать UTC во всем своем приложении, специально для арифметических операций, таких как вычисление разницы между двумя временными точками.

вы можете получить текущую дату/время вот так:

import pytz
from datetime import datetime
datetime.utcnow().replace(tzinfo=pytz.utc)

имейте в виду, что datetime.today() и datetime.now() вернуть местные время, а не время UTC, поэтому применение .replace(tzinfo=pytz.utc) им было бы неправильно.

еще один хороший способ сделать это:

datetime.now(pytz.utc)

, который немного короче и делает то же самое.


дальнейшее чтение / просмотр почему предпочитайте UTC во многих случаях:


получить текущее время в определенном часовом поясе:

import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))

в Python 3 стандартная библиотека упрощает работу:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2016, 8, 26, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)

Если вам нужно решение, которое использует только стандартную библиотеку и работает как в Python 2, так и в Python 3, см. ответ Дж. Ф. Себастьяна.


вот решение stdlib, которое работает как на Python 2, так и на 3:

from datetime import datetime

now = datetime.now(utc) # timezone-aware datetime.utcnow()
today = datetime(now.year, now.month, now.day, tzinfo=utc) # midnight

здесь today является осведомленным экземпляром datetime, представляющим начало дня (полночь) в UTC и utc является объектом tzinfo (пример из docs):

from datetime import tzinfo, timedelta

ZERO = timedelta(0)

class UTC(tzinfo):
    def utcoffset(self, dt):
        return ZERO

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

    def dst(self, dt):
        return ZERO

utc = UTC()

обзоры: сравнение производительности несколько способов получить полночь (начало дня) для данного времени UTC.
Примечание: это сложнее, чтобы получить полночь для часового пояса с нефиксированное смещение utc.


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

import datetime
import pytz

pytz.utc.localize( datetime.datetime.utcnow() )  

Если вы используете Django, вы можете установить даты без TZ (только utc).

комментарий следующая строка в settings.py:

USE_TZ = True

pytz - это библиотека Python, которая позволяет выполнять точные и кросс-платформенные вычисления часового пояса с использованием Python 2.3 или выше.

с помощью stdlib это невозможно.

посмотреть похожие на вопрос так.


вот один из способов создать его с помощью stdlib:

import time
from datetime import datetime

FORMAT='%Y-%m-%dT%H:%M:%S%z'
date=datetime.strptime(time.strftime(FORMAT, time.localtime()),FORMAT)

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

date
datetime.datetime(2017, 8, 1, 12, 15, 44, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

date.tzname()
'UTC+02:00'

ключ добавить %z директива к формату представления, для указания смещения UTC сгенерированного структура времени. С другими форматами представления можно ознакомиться в модуле datetime docs

Если вам нужна дата в часовом поясе UTC, вы можете заменить времени.местное время() С времени.gmtime()

date=datetime.strptime(time.strftime(FORMAT, time.gmtime()),FORMAT)

date    
datetime.datetime(2017, 8, 1, 10, 23, 51, tzinfo=datetime.timezone.utc)

date.tzname()
'UTC'

редактировать

это работает только на python3. Директива z недоступна на python 2 _strptime.py код


почему не использовать dateutil, как описано здесь: http://joelinoff.com/blog/?p=802

from dateutil.tz import tzlocal
# Get the current date/time with the timezone.
now = datetime.datetime.now(tzlocal())

получение даты с учетом часового пояса в utc часовой пояс достаточно для вычитания даты для работы.

но если вы хотите, чтобы часовой пояс знал дату в текущем часовом поясе,tzlocal путь:

from tzlocal import get_localzone  # pip install tzlocal
from datetime import datetime
datetime.now(get_localzone())

PS dateutil имеет аналогичную функцию (dateutil.tz.tzlocal). Но несмотря на совместное использование имени, он имеет совершенно другую кодовую базу, которая как отметить Дж. Ф. Себастьян может дать неверные результаты.


вы можете создать локальную timezone С помощью datetime парсинг вывода time.strftime вызова, который использует %z директива (введена в Python 3.3), Как показано jcazor. Вы можете использовать timezone чтобы создать aware datetime экземпляр с однострочным:

import time
from datetime import datetime

aware_local_now = datetime.now(
    tz=datetime.strptime(time.strftime("%z", time.localtime()), "%z").tzinfo)

print(aware_local_now)
2018-03-01 13:41:26.753644-08:00

используйте часовой пояс, как показано ниже для часового пояса, по умолчанию UTC:

    from django.utils import timezone
    today = timezone.now() 

Если вы получаете текущее время и дату в python,то импортируйте дату и время, пакет pytz в python после того, как вы получите текущую дату и время, как as..

from datetime import datetime
import pytz
import time
str(datetime.strftime(datetime.now(pytz.utc),"%Y-%m-%d %H:%M:%S%t"))

Другой альтернативой, на мой взгляд, лучше, является использование Pendulum вместо pytz. Рассмотрим следующий простой код:

>>> import pendulum

>>> dt = pendulum.now().to_iso8601_string()
>>> print (dt)
2018-03-27T13:59:49+03:00
>>>

чтобы установить маятник и посмотреть их документацию, перейдите здесь. Он имеет множество опций (например, простая поддержка формата ISO8601, RFC3339 и многих других), лучшую производительность и, как правило, дает более простой код.