Как преобразовать 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.
в обратном направлении: Как преобразовать datetime python utc в локальное datetime, используя только стандартную библиотеку python?






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 ())
Вызов .timetuple() устанавливает tm_isdst в -1; вероятность отказа mktime() во время перехода на летнее время составляет 50%.
Решение Чака теряет информацию о миллисекундах.
Сначала проанализируйте строку в наивном объекте 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'
Очевидно, шаг «выяснить, какой местный часовой пояс» доказывает сложнее, чем кажется (практически невозможно).
Используйте local.localize, как предлагает @SamStoelinga, иначе вы не будете учитывать переход на летнее время.
Этот ответ мне очень помог, но я хотел бы указать на ловушку, с которой я столкнулся. Если вы укажете время, но не дату, вы можете получить неожиданные результаты. Поэтому не забудьте указать полную временную метку.
вы можете использовать используйте tzlocal.get_localzone(), чтобы получить местный часовой пояс как объект pytz tzinfo
Это работает, спасибо. В зависимости от потребностей решение, предоставляемое @monkut, менее подробное. Кроме того, tzlocal.get_localzone (). Zone - это то, что предоставляет параметр строкового значения для pytz.timezone () выше. Например. 'Азия / Токио'
@arcseldon: ответ монкута совершенно неправильный. Неважно, как долго это будет. Прочитать мой комментарий там
Использование python-dateutil избавит вас от невзгод, связанных с strptime! `from dateutil import parser local_dt = parser.parse (" 2001-2-3 10:11:12 ") utc_dt = local_dt.astimezone (pytz.utc)`
Обратите внимание, что начиная с python 3.9 (zoneinfo) или 3.6+ (backports.zoneinfo) может заменить pytz для часового пояса IANA
Мне неясно, исправлен ли этот ответ на летнее время? Похоже, что для статуса DST жестко задано значение «Нет». Если да, то как определить правильное значение is_dst? Я получаю даты из широкого спектра приложений в формате даты, времени и часового пояса (01.01.2021 20:00 «Америка / Лос-Анджелес»). Я не уверен, правильный ли этот ответ, поскольку is_dst будет меняться для каждой даты. ?
Спасибо @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)), которая не зависит от часового пояса.
Также существует вероятность 50% сбоя при переходе на летнее время. См. Проблемы с местным временем
Как насчет -
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
Функция 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)
Если вы готовы заняться преобразованием часовых поясов, прочтите это:
Это только преобразует текущее время, мне нужно взять любое заданное время (в виде строки) и преобразовать в UTC.
Я не думаю, что это должно иметь значение, если вы используете стандартные значения смещения. local_time = utc_time + utc_offset И utc_time = local_time - utc_offset.
Он работает только с текущим временем, потому что прошлые и будущие временные метки могут иметь разное смещение UTC из-за летнего времени.
хороший момент ... если вам нужно иметь дело с DST, вам, вероятно, следует использовать pytz, как упоминал Джон Милликин.
Между вызовами utcnow () и now () существует спорадическая разница. Это опасная строка кода, которая позже может привести к странным ошибкам, таким как tzinfo.utcoffset() must return a whole number of minutes и так далее.
Раньше у меня не было проблем с этим, но вы правы. Вы всегда можете преобразовать дельту как: clean_delta = datetime.timedelta (hours = int (UTC_OFFSET_TIMEDELTA.total_seco nds () /60.0/60.0)) Но имейте в виду, что есть такие места, как Индия (UTC + 05:30) .
1. Смещение utc для местного часового пояса может зависеть от даты и времени; поэтому может быть неправильно применять смещение utc, вычисленное для текущего времени, к другим моментам в будущем / прошлом, например, до / после перехода на летнее время. 2. не существует такой вещи, как местный UTC, если только вы не говорите о синхронизации часов компьютера, которая не связана с вопросом. «Который сейчас час по всемирному координированному времени» имеет один и тот же единственный ответ для любого места на Земле (около 19:00 во время комментария).
Другой способ избавиться от разницы между utc now () и now () - это UTC_OFFSET_TIMEDELTA = datetime.utcnow().replace(minute=0, second=0, microsecond=0) - datetime.now().replace(minute=0, second=0, microsecond=0). Примечание: иногда это может пойти не так, если один раз до минуты и один после.
если вы предпочитаете 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 вызова функций больше, чем в моей версии ...
% Z и% z по-прежнему печатают пробелы.
это неверно. Это не удается, если местный часовой пояс отличается от UTC. mktime() ожидает на входе местное время. fromtimestamp() возвращает местное время, а не utc. Если исправишь то увидишь эти дополнительные проблемы (например, dateutil, решение только для stdlib может дать сбой)
Как насчет -
time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))
если секунды - это None, то он преобразует местное время во время UTC, иначе преобразует переданное время в UTC.
Это не помогает, вопрос состоял в том, чтобы преобразовать заданную строку местного времени в строку utc.
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'
Для экономии дневного света и т. д.
Ни один из приведенных выше ответов мне особо не помог. Приведенный ниже код работает для 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.
@ JFSebastian: Не слышал об этом - где мы можем получить больше информации?
возьмите машину с Windows, установите любой часовой пояс, который в прошлом имел другое смещение utc, например, Европа / Москва. Сравнить результаты с pytz. Кроме того, вы можете протестируйте эту ошибку, которая не работает даже на Ubuntu, хотя я не уверен в правильном использовании API в этом случае.
Что на выходе? Пожалуйста, опубликуйте вывод.
Еще один пример с 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
Вот краткое изложение общих преобразований времени Python.
Некоторые методы отбрасывают доли секунды и отмечены (s). Вместо этого можно использовать явную формулу, такую как ts = (d - epoch) / unit (спасибо jfs).
calendar.timegm(struct_time)calendar.timegm(stz.localize(dt, is_dst=None).utctimetuple())calendar.timegm(dt.utctimetuple())calendar.timegm(dt.utctimetuple())time.gmtime(t)stz.localize(dt, is_dst=None).utctimetuple()dt.utctimetuple()dt.utctimetuple()datetime.fromtimestamp(t, None)datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz).replace(tzinfo=None)dt.replace(tzinfo=UTC).astimezone(tz).replace(tzinfo=None)dt.astimezone(tz).replace(tzinfo=None)datetime.utcfromtimestamp(t)datetime.datetime(*struct_time[:6])stz.localize(dt, is_dst=None).astimezone(UTC).replace(tzinfo=None)dt.astimezone(UTC).replace(tzinfo=None)datetime.fromtimestamp(t, tz)datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz)stz.localize(dt, is_dst=None)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.
(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)
я бы хотел, чтобы это было в таблице, чтобы было легче читать (это в ссылке)
@MichaelChirico, этот ответ заявляет, что «Мы не разрешаем (и не будем) разрешать теги <table>. Извините. Это сделано намеренно и намеренно. Если вам нужна быстрая и грязная« таблица », используйте <pre> и макет ASCII». Я не верю, что таблица ASCII будет более читаемой, чем список выше.
ну это прискорбно. у вас все равно есть мой голос ... может быть, сослаться на таблицу в ссылке в вашем ответе?
@MichaelChirico, ответ уже содержит ссылку на исходную таблицу Таави Бернса.
Использование 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'). наивный
В python3:
pip install python-dateutil
from dateutil.parser import tz
mydt.astimezone(tz.gettz('UTC')).replace(tzinfo=None)
это, похоже, не работает, это вызывает исключение ValueError: ValueError: astimezone () не может применяться к наивному datetime
Должно быть: from dateutil import tz
У меня так получилось:
>>> 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
это не работает для летнего времени - например, если сейчас лето, а дата конвертации - зима. и вопрос был о преобразовании дат, хранящихся в виде строк ...
К вашему сведению. Самая большая проблема с этим методом (помимо перехода на летнее время) - это несколько миллисекунд, через которые дельта будет отключена. Все приглашения в моем календаре отображаются как отключенные через 1 минуту.
Я нашел лучший ответ на другой вопрос здесь. Он использует только встроенные библиотеки 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
Имейте в виду, что метод mktime () принимает в качестве входных данных "местное время", которое может быть не тем, что вы ожидаете, я использовал его, и он все испортил. Пожалуйста, взгляните на эта ссылка