Самый простой и надежный способ преобразования часовых поясов, который я знаю, - это использовать сторонний модуль pytz :
import pytz
import datetime as dt
utc=pytz.utc
eastern=pytz.timezone('US/Eastern')
fmt='%Y-%m-%d %H:%M:%S %Z%z'
text='''\
10/1/2010 0:0:0
10/1/2010 0:6:0
10/1/2010 23:54:0
10/3/2010 0:0:0
'''
for datestring in text.splitlines():
date=dt.datetime.strptime(datestring,"%m/%d/%Y %H:%M:%S")
date_eastern=eastern.localize(date,is_dst=None)
date_utc=date_eastern.astimezone(utc)
print(date_utc.strftime(fmt))
Выходы:
2010-10-01 04:00:00 UTC+0000
2010-10-01 04:06:00 UTC+0000
2010-10-02 03:54:00 UTC+0000
2010-10-03 04:00:00 UTC+0000
Обратите внимание, однако, что ваши данные не указывают, находится ли дата и время в часовом поясе EST или EDT.
Есть некоторые моменты, которые неоднозначны, когда вы не указываете EST или EDT. Например, «10/27/2002 1:30:00» будет неоднозначным:
>>> eastern.localize(datetime(2002, 10, 27, 1, 30, 00), is_dst=None)
AmbiguousTimeError: 2002-10-27 01:30:00
, поскольку это время произошло дважды из-за перехода на летнее время.
Также некоторые даты, такие как 2002-04-07 02:30:00,
не существует. Смотрите эту ссылку
для обсуждения этих и даже более странных вопросов, возникающих при работе с местным временем.
Если вы хотите пропустить эти запутанные угловые случаи, и если ваша машина настроена в местном часовом поясе (например, EST / EDT),
есть способ конвертировать между местным и часовым поясом UTC, который делает
не требует установки pytz
. Идея состоит в том, чтобы преобразовать datetime -> timetuple -> timestamp -> UTC datetime. Цепочка преобразований сделана с
dt.datetime.utcfromtimestamp(time.mktime(date.timetuple()))
Например:
import time
import datetime as dt
import pytz
utc=pytz.utc
eastern=pytz.timezone('US/Eastern')
fmt='%Y-%m-%d %H:%M:%S %Z%z'
text='''\
10/1/2010 0:0:0
10/1/2010 0:6:0
10/1/2010 23:54:0
10/3/2010 0:0:0
3/13/2011 1:55:0
3/13/2011 3:00:0
'''
for datestring in text.splitlines():
date=dt.datetime.strptime(datestring,"%m/%d/%Y %H:%M:%S")
date_est=eastern.localize(date,is_dst=None)
date_utc=date_est.astimezone(utc)
date_utc2=dt.datetime.utcfromtimestamp(time.mktime(date.timetuple()))
print('{d} --> {d_utc} {d_utc2}'.format(
d=date.strftime(fmt),
d_utc=date_utc.strftime(fmt),
d_utc2=date_utc2.strftime(fmt),
))
assert date_utc.hour == date_utc2.hour
выходы
2010-10-01 00:00:00 EDT-0400 --> 2010-10-01 04:00:00 UTC+0000 2010-10-01 04:00:00
2010-10-01 00:06:00 EDT-0400 --> 2010-10-01 04:06:00 UTC+0000 2010-10-01 04:06:00
2010-10-01 23:54:00 EDT-0400 --> 2010-10-02 03:54:00 UTC+0000 2010-10-02 03:54:00
2010-10-03 00:00:00 EDT-0400 --> 2010-10-03 04:00:00 UTC+0000 2010-10-03 04:00:00
2011-03-13 01:55:00 EST-0500 --> 2011-03-13 06:55:00 UTC+0000 2011-03-13 06:55:00
2011-03-13 03:00:00 EDT-0400 --> 2011-03-13 07:00:00 UTC+0000 2011-03-13 07:00:00
Последние две даты, проверенные выше, показывают, что преобразование работает корректно даже при временах, близких к переключению между EST и EDT.
В итоге, используя альтернативный метод (без pytz), здесь показано, как преобразовать объекты даты и времени, представляющие локальное время, в объекты даты и времени, представляющие GMT
время и наоборот:
In [83]: import datetime as dt
In [84]: import time
In [85]: import calendar
In [86]: date=dt.datetime(2010,12,1,0,0,0)
In [87]: date
Out[87]: datetime.datetime(2010, 12, 1, 0, 0)
In [88]: date_utc=dt.datetime.utcfromtimestamp(time.mktime(date.timetuple()))
In [89]: date_utc
Out[89]: datetime.datetime(2010, 12, 1, 5, 0)
In [90]: date_local=dt.datetime.fromtimestamp(calendar.timegm(date_utc.timetuple()))
In [91]: date_local
Out[91]: datetime.datetime(2010, 12, 1, 0, 0)