Как преобразовать строку местного времени в UTC?

Как преобразовать datetime строка по местному времени в строка по времени UTC?

Я уверен, что делал это раньше, но не могу найти, и SO, надеюсь, поможет мне (и другим) сделать это в будущем.

Разъяснение: Например, если у меня 2008-09-17 14:02:00 в моем часовом поясе (+10), я хотел бы сгенерировать строку с эквивалентным временем UTC: 2008-09-17 04:02:00.

Кроме того, из http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/ обратите внимание, что в целом это невозможно, поскольку с DST и другими проблемами нет уникального преобразования из местного времени во время UTC.

Имейте в виду, что метод mktime () принимает в качестве входных данных "местное время", которое может быть не тем, что вы ожидаете, я использовал его, и он все испортил. Пожалуйста, взгляните на эта ссылка

Haifeng Zhang 01.03.2014 01:19
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
338
2
493 764
23
Перейти к ответу Данный вопрос помечен как решенный

Ответы 23

def local_to_utc(t):
    secs = time.mktime(t)
    return time.gmtime(secs)

def utc_to_local(t):
    secs = calendar.timegm(t)
    return time.localtime(secs)

Источник: http://feihonghsu.blogspot.com/2008/02/converting-from-local-time-to-utc.html

Пример использования из bd808: Если ваш источник - объект datetime.datetimet, вызовите как:

local_to_utc(t.timetuple())

Если ваш источник - объект datetime.datetime t, вызовите как: local_to_utc (t.timetuple ())

bd808 18.12.2008 07:50

Вызов .timetuple() устанавливает tm_isdst в -1; вероятность отказа mktime() во время перехода на летнее время составляет 50%.

jfs 05.12.2013 12:24

Решение Чака теряет информацию о миллисекундах.

Luca 22.01.2015 01:23

Сначала проанализируйте строку в наивном объекте datetime. Это экземпляр datetime.datetime без прикрепленной информации о часовом поясе. См. Его документация.

Используйте модуль pytz, который поставляется с полным списком часовых поясов + UTC. Выясните, что такое местный часовой пояс, создайте из него объект часового пояса, манипулируйте им и прикрепите его к наивному datetime.

Наконец, используйте метод datetime.astimezone() для преобразования даты и времени в UTC.

Исходный код с использованием местного часового пояса "America / Los_Angeles" для строки "2001-2-3 10:11:12":

from datetime import datetime   
import pytz

local = pytz.timezone("America/Los_Angeles")
naive = datetime.strptime("2001-2-3 10:11:12", "%Y-%m-%d %H:%M:%S")
local_dt = local.localize(naive, is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc)

Оттуда вы можете использовать метод strftime() для форматирования даты и времени UTC по мере необходимости:

utc_dt.strftime("%Y-%m-%d %H:%M:%S")

Отредактируйте свой ответ, используя следующий код: [code] local.localize (наивный) [/ code] См. Документ: связь К сожалению, использование аргумента tzinfo стандартных конструкторов datetime «не работает» с pytz для многих часовых поясов. >>> datetime (2002, 10, 27, 12, 0, 0, tzinfo = a Amsterdam) .strftime (fmt) '2002-10-27 12:00:00 AMT + 0020'

Sam Stoelinga 15.04.2011 12:40

Очевидно, шаг «выяснить, какой местный часовой пояс» доказывает сложнее, чем кажется (практически невозможно).

Jason R. Coombs 15.09.2011 17:20

Используйте local.localize, как предлагает @SamStoelinga, иначе вы не будете учитывать переход на летнее время.

Emil Stenström 25.05.2012 19:22

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

Steven Mercatante 26.11.2013 02:43

вы можете использовать используйте tzlocal.get_localzone(), чтобы получить местный часовой пояс как объект pytz tzinfo

jfs 27.03.2015 11:47

Это работает, спасибо. В зависимости от потребностей решение, предоставляемое @monkut, менее подробное. Кроме того, tzlocal.get_localzone (). Zone - это то, что предоставляет параметр строкового значения для pytz.timezone () выше. Например. 'Азия / Токио'

arcseldon 25.11.2015 04:38

@arcseldon: ответ монкута совершенно неправильный. Неважно, как долго это будет. Прочитать мой комментарий там

jfs 28.03.2016 06:40

Использование python-dateutil избавит вас от невзгод, связанных с strptime! `from dateutil import parser local_dt = parser.parse (" 2001-2-3 10:11:12 ") utc_dt = local_dt.astimezone (pytz.utc)`

deepdive 10.03.2020 03:55

Обратите внимание, что начиная с python 3.9 (zoneinfo) или 3.6+ (backports.zoneinfo) может заменить pytz для часового пояса IANA

Orelus 16.07.2020 12:24

Мне неясно, исправлен ли этот ответ на летнее время? Похоже, что для статуса DST жестко задано значение «Нет». Если да, то как определить правильное значение is_dst? Я получаю даты из широкого спектра приложений в формате даты, времени и часового пояса (01.01.2021 20:00 «Америка / Лос-Анджелес»). Я не уверен, правильный ли этот ответ, поскольку is_dst будет меняться для каждой даты. ?

Doug Bower 17.01.2021 11:09
Ответ принят как подходящий

Спасибо @rofly, полное преобразование из строки в строку выглядит следующим образом:

time.strftime("%Y-%m-%d %H:%M:%S", 
              time.gmtime(time.mktime(time.strptime("2008-09-17 14:04:00", 
                                                    "%Y-%m-%d %H:%M:%S"))))

Мое резюме функций time / calendar:

time.strptime
строка -> кортеж (часовой пояс не применяется, поэтому соответствует строке)

time.mktime
кортеж местного времени -> секунд с эпохи (всегда местное время)

time.gmtime
секунд с эпохи -> кортеж в формате UTC

и

calendar.timegm
кортеж в формате UTC -> секунд с эпохи

time.localtime
секунд с эпохи → кортеж в местном часовом поясе

(always local time) кажется неправильным: вход в mktime () - местное время, выход - секунды с эпохи (1970-01-01 00:00:00 +0000 (UTC)), которая не зависит от часового пояса.

jfs 11.08.2012 00:51

Также существует вероятность 50% сбоя при переходе на летнее время. См. Проблемы с местным временем

jfs 11.08.2012 01:01

Как насчет -

time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))

если секунды - это None, то он преобразует местное время во время UTC, иначе преобразует переданное время в UTC.

ПРИМЕЧАНИЕ - С 2020 года вы не должны использовать .utcnow() или .utcfromtimestamp(xxx). Поскольку вы, по-видимому, перешли на python3, вам следует использовать объекты datetime, учитывающие часовой пояс.

>>> from datetime import timezone
>>> dt_now = datetime.now(tz=timezone.utc)
>>> dt_ts = datetime.fromtimestamp(1571595618.0, tz=timezone.utc)

подробности см .: см .: https://blog.ganssle.io/articles/2019/11/utcnow.html

оригинальный ответ (с 2010 года):

Функция utcnow () модуля datetime может использоваться для получения текущего времени UTC.

>>> import datetime
>>> utc_datetime = datetime.datetime.utcnow()
>>> utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2010-02-01 06:59:19'

Как говорится в ссылке, упомянутой выше Томом: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/:

UTC is a timezone without daylight saving time and still a timezone without configuration changes in the past.

Always measure and store time in UTC.

If you need to record where the time was taken, store that separately. Do not store the local time + timezone information!

ПРИМЕЧАНИЕ - Если какие-либо из ваших данных находятся в регионе, который использует DST, используйте pytz и посмотрите ответ Джона Милликина.

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

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

>>> # Obtain the UTC Offset for the current system:
>>> UTC_OFFSET_TIMEDELTA = datetime.datetime.utcnow() - datetime.datetime.now()
>>> local_datetime = datetime.datetime.strptime("2008-09-17 14:04:00", "%Y-%m-%d %H:%M:%S")
>>> result_utc_datetime = local_datetime + UTC_OFFSET_TIMEDELTA
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'

-> Или, исходя из известного смещения, используя datetime.timedelta ():

>>> UTC_OFFSET = 10
>>> result_utc_datetime = local_datetime - datetime.timedelta(hours=UTC_OFFSET)
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'

ОБНОВИТЬ:

Поскольку доступен Python 3.2 datetime.timezone. Вы можете сгенерировать объект datetime с учетом часового пояса с помощью следующей команды:

import datetime

timezone_aware_dt = datetime.datetime.now(datetime.timezone.utc)

Если вы готовы заняться преобразованием часовых поясов, прочтите это:

https://medium.com/@eleroy/10-things-you-need-to-know-about-date-and-time-in-python-with-datetime-pytz-dateutil-timedelta-309bfbafb3f7

Это только преобразует текущее время, мне нужно взять любое заданное время (в виде строки) и преобразовать в UTC.

Tom 02.02.2010 07:29

Я не думаю, что это должно иметь значение, если вы используете стандартные значения смещения. local_time = utc_time + utc_offset И utc_time = local_time - utc_offset.

monkut 10.02.2011 06:18

Он работает только с текущим временем, потому что прошлые и будущие временные метки могут иметь разное смещение UTC из-за летнего времени.

Alex B 17.02.2011 02:55

хороший момент ... если вам нужно иметь дело с DST, вам, вероятно, следует использовать pytz, как упоминал Джон Милликин.

monkut 18.02.2011 04:50

Между вызовами utcnow () и now () существует спорадическая разница. Это опасная строка кода, которая позже может привести к странным ошибкам, таким как tzinfo.utcoffset() must return a whole number of minutes и так далее.

Pavel Vlasov 23.05.2012 04:23

Раньше у меня не было проблем с этим, но вы правы. Вы всегда можете преобразовать дельту как: clean_delta = datetime.timedelta (hours = int (UTC_OFFSET_TIMEDELTA.total_seco‌ nds () /60.0/60.0)) Но имейте в виду, что есть такие места, как Индия (UTC + 05:30) .

monkut 23.05.2012 04:39

1. Смещение utc для местного часового пояса может зависеть от даты и времени; поэтому может быть неправильно применять смещение utc, вычисленное для текущего времени, к другим моментам в будущем / прошлом, например, до / после перехода на летнее время. 2. не существует такой вещи, как местный UTC, если только вы не говорите о синхронизации часов компьютера, которая не связана с вопросом. «Который сейчас час по всемирному координированному времени» имеет один и тот же единственный ответ для любого места на Земле (около 19:00 во время комментария).

jfs 14.11.2012 23:02

Другой способ избавиться от разницы между utc now () и now () - это UTC_OFFSET_TIMEDELTA = datetime.utcnow().replace(minute=0, second=0, microsecond=0) - datetime.now().replace(minute=0, second=0, microsecond=0). Примечание: иногда это может пойти не так, если один раз до минуты и один после.

Erik van Oosten 26.09.2013 13:29

если вы предпочитаете datetime.datetime:

dt = datetime.strptime("2008-09-17 14:04:00","%Y-%m-%d %H:%M:%S")
utc_struct_time = time.gmtime(time.mktime(dt.timetuple()))
utc_dt = datetime.fromtimestamp(time.mktime(utc_struct_time))
print dt.strftime("%Y-%m-%d %H:%M:%S")

Конечно, но я не понимаю, почему ты предпочитаешь это. Требуется дополнительный импорт и на 3 вызова функций больше, чем в моей версии ...

Tom 04.03.2010 05:36

% Z и% z по-прежнему печатают пробелы.

Pavel Vlasov 22.05.2012 19:09

это неверно. Это не удается, если местный часовой пояс отличается от UTC. mktime() ожидает на входе местное время. fromtimestamp() возвращает местное время, а не utc. Если исправишь то увидишь эти дополнительные проблемы (например, dateutil, решение только для stdlib может дать сбой)

jfs 20.01.2015 13:07

Как насчет -

time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))

если секунды - это None, то он преобразует местное время во время UTC, иначе преобразует переданное время в UTC.

Это не помогает, вопрос состоял в том, чтобы преобразовать заданную строку местного времени в строку utc.

Tom 17.07.2011 06:47

import time

import datetime

def Local2UTC(LocalTime):

    EpochSecond = time.mktime(LocalTime.timetuple())
    utcTime = datetime.datetime.utcfromtimestamp(EpochSecond)

    return utcTime

>>> LocalTime = datetime.datetime.now()

>>> UTCTime = Local2UTC(LocalTime)

>>> LocalTime.ctime()

'Thu Feb  3 22:33:46 2011'

>>> UTCTime.ctime()

'Fri Feb  4 05:33:46 2011'
mktime(dt.timetuple()) может выйти из строя во время перехода на летнее время. There is LocalTimezone in the docs (it works for the most recent timezone definition but can fail for past dates (unrelated to DST))
jfs 05.12.2013 12:44

Для экономии дневного света и т. д.

Ни один из приведенных выше ответов мне особо не помог. Приведенный ниже код работает для GMT.

def get_utc_from_local(date_time, local_tz=None):
    assert date_time.__class__.__name__ == 'datetime'
    if local_tz is None:
        local_tz = pytz.timezone(settings.TIME_ZONE) # Django eg, "Europe/London"
    local_time = local_tz.normalize(local_tz.localize(date_time))
    return local_time.astimezone(pytz.utc)

import pytz
from datetime import datetime

summer_11_am = datetime(2011, 7, 1, 11)
get_utc_from_local(summer_11_am)
>>>datetime.datetime(2011, 7, 1, 10, 0, tzinfo=<UTC>)

winter_11_am = datetime(2011, 11, 11, 11)
get_utc_from_local(winter_11_am)
>>>datetime.datetime(2011, 11, 11, 11, 0, tzinfo=<UTC>)

Мне повезло с dateutil (который широко рекомендуется в SO для других связанных вопросов):

from datetime import *
from dateutil import *
from dateutil.tz import *

# METHOD 1: Hardcode zones:
utc_zone = tz.gettz('UTC')
local_zone = tz.gettz('America/Chicago')
# METHOD 2: Auto-detect zones:
utc_zone = tz.tzutc()
local_zone = tz.tzlocal()

# Convert time string to datetime
local_time = datetime.strptime("2008-09-17 14:02:00", '%Y-%m-%d %H:%M:%S')

# Tell the datetime object that it's in local time zone since 
# datetime objects are 'naive' by default
local_time = local_time.replace(tzinfo=local_zone)
# Convert time to UTC
utc_time = local_time.astimezone(utc_zone)
# Generate UTC time string
utc_string = utc_time.strftime('%Y-%m-%d %H:%M:%S')

(Код был получен из этого ответа на Преобразование строки даты и времени UTC в локальную дату и время)

dateutil может выйти из строя для прошлых дат, если местный часовой пояс имел другое смещение utc (не связанное с переходами на летнее время) в системах, в которых реализация не использует базу данных исторических часовых поясов (особенно Windows). Вместо него можно использовать pytz + tzlocal.

jfs 05.12.2013 12:29

@ JFSebastian: Не слышал об этом - где мы можем получить больше информации?

Yarin 27.12.2013 01:30

возьмите машину с Windows, установите любой часовой пояс, который в прошлом имел другое смещение utc, например, Европа / Москва. Сравнить результаты с pytz. Кроме того, вы можете протестируйте эту ошибку, которая не работает даже на Ubuntu, хотя я не уверен в правильном использовании API в этом случае.

jfs 27.12.2013 12:46

Что на выходе? Пожалуйста, опубликуйте вывод.

not2qubit 18.01.2018 19:15

Еще один пример с pytz, но включает localize (), что спасло меня.

import pytz, datetime
utc = pytz.utc
fmt = '%Y-%m-%d %H:%M:%S'
amsterdam = pytz.timezone('Europe/Amsterdam')

dt = datetime.datetime.strptime("2012-04-06 10:00:00", fmt)
am_dt = amsterdam.localize(dt)
print am_dt.astimezone(utc).strftime(fmt)
'2012-04-06 08:00:00'

Вы можете сделать это с помощью:

>>> from time import strftime, gmtime, localtime
>>> strftime('%H:%M:%S', gmtime()) #UTC time
>>> strftime('%H:%M:%S', localtime()) # localtime

Наибольший успех у меня получился с python-dateutil:

from dateutil import tz

def datetime_to_utc(date):
    """Returns date in UTC w/o tzinfo"""
    return date.astimezone(tz.gettz('UTC')).replace(tzinfo=None) if date.tzinfo else date
dateutil может выйти из строя за прошлые даты
jfs 05.12.2013 12:42

Вот краткое изложение общих преобразований времени Python.

Некоторые методы отбрасывают доли секунды и отмечены (s). Вместо этого можно использовать явную формулу, такую ​​как ts = (d - epoch) / unit (спасибо jfs).

  • struct_time (UTC) → POSIX (s):
    calendar.timegm(struct_time)
  • Наивное datetime (местное) → POSIX (s):
    calendar.timegm(stz.localize(dt, is_dst=None).utctimetuple())
    (исключение во время переходов на летнее время, см. Комментарий от jfs)
  • Наивное datetime (UTC) → POSIX (s):
    calendar.timegm(dt.utctimetuple())
  • Зная datetime → POSIX (s):
    calendar.timegm(dt.utctimetuple())
  • POSIX → struct_time (UTC, s):
    time.gmtime(t)
    (см. Комментарий от jfs)
  • Наивное datetime (локальное) → struct_time (UTC, s):
    stz.localize(dt, is_dst=None).utctimetuple()
    (исключение во время переходов на летнее время, см. Комментарий от jfs)
  • Наивное datetime (UTC) → struct_time (UTC, s):
    dt.utctimetuple()
  • Зная datetime → struct_time (UTC, s):
    dt.utctimetuple()
  • POSIX → Naïve datetime (local):
    datetime.fromtimestamp(t, None)
    (может не работать в определенных условиях, см. Комментарий от jfs ниже)
  • struct_time (UTC) → Naïve datetime (local, s):
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
    (не может представлять дополнительные секунды, см. комментарий от jfs)
  • Наивное datetime (UTC) → Наивное datetime (местное):
    dt.replace(tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
  • Осведомленное datetime → Наивное datetime (местное):
    dt.astimezone(tz).replace(tzinfo=None)
  • POSIX → Наивное datetime (UTC):
    datetime.utcfromtimestamp(t)
  • struct_time (UTC) → Наивное datetime (UTC, s):
    datetime.datetime(*struct_time[:6])
    (не может представлять дополнительные секунды, см. комментарий от jfs)
  • Наивное datetime (локальное) → Наивное datetime (UTC):
    stz.localize(dt, is_dst=None).astimezone(UTC).replace(tzinfo=None)
    (исключение во время переходов на летнее время, см. Комментарий от jfs)
  • Осведомленное datetime → Наивное datetime (UTC):
    dt.astimezone(UTC).replace(tzinfo=None)
  • POSIX → Aware datetime:
    datetime.fromtimestamp(t, tz)
    (может не работать для часовых поясов, отличных от pytz)
  • struct_time (UTC) → Aware datetime (s):
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz)
    (не может представлять дополнительные секунды, см. комментарий от jfs)
  • Naïve datetime (local) → Aware datetime:
    stz.localize(dt, is_dst=None)
    (исключение во время переходов на летнее время, см. Комментарий от jfs)
  • Наивное datetime (UTC) → Знающее datetime:
    dt.replace(tzinfo=UTC)

Источник: taaviburns.ca

(1) fromtimestamp(t, None) может выйти из строя, если местный часовой пояс имел другое смещение utc в t. и Библиотека C не имеет доступа к базе данных tz на данной платформе. Вы можете использовать tzlocal.get_localzone() для предоставления tzdata переносимым способом. (2) fromtimestamp(t, tz) может не работать для часовых поясов, отличных от pytz. (3) datetime(*struct_time[:6]) вам не хватает *. (4) Растворы на основе timegm(), utctimetuple(), struct_time падают за доли секунды. Вместо этого вы можете использовать явную формулу, например: ts = (d - epoch) / unit.

jfs 09.09.2015 18:36

(5) stz.localize(dt, is_dst=None) вызывает исключение для неоднозначного или несуществующего местного времени, например, во время перехода на летнее время. Чтобы избежать исключения, используйте stz.normalize(stz.localize(dt)), который может возвращать неточные результаты. (6) datetime () не может представлять дополнительную секунду. Преобразуйте struct_time в «секунды с эпохи» в качестве временного решения. (7) time.gmtime(t), в отличие от calendar.timegm(), может ожидать ввода не-POSIX, если используется "правильный" часовой пояс. Используйте явную формулу, если вместо этого вводится POSIX: gmtime = lambda t: datetime(1970,1,1, tzinfo=utc) + timedelta(seconds=t)

jfs 09.09.2015 18:37

я бы хотел, чтобы это было в таблице, чтобы было легче читать (это в ссылке)

MichaelChirico 16.03.2018 14:33

@MichaelChirico, этот ответ заявляет, что «Мы не разрешаем (и не будем) разрешать теги <table>. Извините. Это сделано намеренно и намеренно. Если вам нужна быстрая и грязная« таблица », используйте <pre> и макет ASCII». Я не верю, что таблица ASCII будет более читаемой, чем список выше.

akaihola 21.05.2018 21:44

ну это прискорбно. у вас все равно есть мой голос ... может быть, сослаться на таблицу в ссылке в вашем ответе?

MichaelChirico 22.05.2018 02:02

@MichaelChirico, ответ уже содержит ссылку на исходную таблицу Таави Бернса.

akaihola 09.06.2018 23:31

Использование http://crsmithdev.com/arrow/

arrowObj = arrow.Arrow.strptime('2017-02-20 10:00:00', '%Y-%m-%d %H:%M:%S' , 'US/Eastern')

arrowObj.to('UTC') or arrowObj.to('local') 

Эта библиотека упрощает жизнь :)

стрелка потрясающая: arrow.get (datetime.now (), 'local'). to ('utc'). наивный

SteveJ 22.06.2017 21:28

В python3:

pip install python-dateutil

from dateutil.parser import tz

mydt.astimezone(tz.gettz('UTC')).replace(tzinfo=None) 

это, похоже, не работает, это вызывает исключение ValueError: ValueError: astimezone () не может применяться к наивному datetime

Stormsson 12.05.2018 11:20

Должно быть: from dateutil import tz

Javier 04.07.2018 12:34

Простой

У меня так получилось:

>>> utc_delta = datetime.utcnow()-datetime.now()
>>> utc_time = datetime(2008, 9, 17, 14, 2, 0) + utc_delta
>>> print(utc_time)
2008-09-17 19:01:59.999996

Необычная реализация

Если хотите пофантазировать, можете превратить это в функтор:

class to_utc():
    utc_delta = datetime.utcnow() - datetime.now()

    def __call__(cls, t):
        return t + cls.utc_delta

Результат:

>>> utc_converter = to_utc()
>>> print(utc_converter(datetime(2008, 9, 17, 14, 2, 0)))
2008-09-17 19:01:59.999996

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

Tom 04.05.2018 02:27

К вашему сведению. Самая большая проблема с этим методом (помимо перехода на летнее время) - это несколько миллисекунд, через которые дельта будет отключена. Все приглашения в моем календаре отображаются как отключенные через 1 минуту.

Nostalg.io 15.10.2018 23:36

Я нашел лучший ответ на другой вопрос здесь. Он использует только встроенные библиотеки python и не требует ввода вашего местного часового пояса (требование в моем случае)

import time
import calendar

local_time = time.strptime("2018-12-13T09:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
local_seconds = time.mktime(local_time)
utc_time = time.gmtime(local_seconds)

Я публикую ответ здесь, так как этот вопрос появляется в Google вместо связанного вопроса в зависимости от ключевых слов поиска.

У меня есть этот код в одном из моих проектов:

from datetime import datetime
## datetime.timezone works in newer versions of python
try:
    from datetime import timezone
    utc_tz = timezone.utc
except:
    import pytz
    utc_tz = pytz.utc

def _to_utc_date_string(ts):
    # type (Union[date,datetime]]) -> str
    """coerce datetimes to UTC (assume localtime if nothing is given)"""
    if (isinstance(ts, datetime)):
        try:
            ## in python 3.6 and higher, ts.astimezone() will assume a
            ## naive timestamp is localtime (and so do we)
            ts = ts.astimezone(utc_tz)
        except:
            ## in python 2.7 and 3.5, ts.astimezone() will fail on
            ## naive timestamps, but we'd like to assume they are
            ## localtime
            import tzlocal
            ts = tzlocal.get_localzone().localize(ts).astimezone(utc_tz)
    return ts.strftime("%Y%m%dT%H%M%SZ")

Если у вас уже есть объект datetime my_dt, вы можете изменить его на UTC с помощью:

datetime.datetime.utcfromtimestamp(my_dt.timestamp())

Вкратце, чтобы преобразовать любую дату datetime во время UTC:

from datetime import datetime

def to_utc(date):
    return datetime(*date.utctimetuple()[:6])

Поясним на примере. Во-первых, нам нужно создать datetime из строки:

>>> date = datetime.strptime("11 Feb 2011 17:33:54 -0800", "%d %b %Y %H:%M:%S %z")

Затем мы можем вызвать функцию:

>>> to_utc(date)
datetime.datetime(2011, 2, 12, 1, 33, 54)

Пошагово, как работает функция:

>>> date.utctimetuple()
time.struct_time(tm_year=2011, tm_mon=2, tm_mday=12, tm_hour=1, tm_min=33, tm_sec=54, tm_wday=5, tm_yday=43, tm_isdst=0)
>>> date.utctimetuple()[:6]
(2011, 2, 12, 1, 33, 54)
>>> datetime(*date.utctimetuple()[:6])
datetime.datetime(2011, 2, 12, 1, 33, 54)

В этом потоке, похоже, отсутствует опция, доступная начиная с Python 3.6: datetime.astimezone(tz=None) можно использовать для получения осведомленного объекта datetime, представляющего местное время (документы). Затем это можно легко преобразовать в UTC.

from datetime import datetime, timezone
s = "2008-09-17 14:02:00"

# to datetime object:
dt = datetime.fromisoformat(s) # Python 3.7

# I'm on time zone Europe/Berlin; CEST/UTC+2 during summer 2008
dt = dt.astimezone()
print(dt)
# 2008-09-17 14:02:00+02:00

# ...and to UTC:
dtutc = dt.astimezone(timezone.utc)
print(dtutc)
# 2008-09-17 12:02:00+00:00

Однако есть одно предостережение, см. astimezone (None) дает осведомленность о дате и времени, не зная о летнем времени.

В python 3.9.0 после того, как вы проанализировали местное время local_time в объект datetime.datetime, просто используйте local_time.astimezone(datetime.timezone.utc).

этот ответ был бы лучше, если бы вы показали, как анализировать местное время в объекте datetime

Connor 09.12.2020 21:51

Другие вопросы по теме