Как преобразовать EST/EDT в GMT?

У меня есть несколько записей внутри столбца, которые представляют собой время EST или EDT. Мне нужно преобразовать это время в время по Гринвичу. Формат времени:

10/1/2010   0:0:0
10/1/2010   0:6:0
...
10/1/2010   23:54:0
...
10/3/2010   0:0:0
...

Может ли кто-нибудь помочь мне здесь? Благодарность


person widget    schedule 30.03.2011    source источник
comment
Это похоже на даты (1 октября 2010 г.), а не на время... поясните, пожалуйста.   -  person John Machin    schedule 30.03.2011
comment
Почему ты продолжаешь задавать один и тот же вопрос? Что было не так с вашими предыдущими попытками? stackoverflow .com/questions/5490141/ и stackoverflow.com/questions/5464410/. Возможно, было бы проще, если бы вы могли задать свой настоящий вопрос вместо этих других, неправильных вопросов, которые вам постоянно приходится менять.   -  person S.Lott    schedule 31.03.2011
comment
@S.Lott: в этом втором сообщении я пытался вручную преобразовать время в время по Гринвичу, что оказалось неэффективным. Для первой публикации я просто думал, что люди перестанут просматривать этот пост. думал удалить первый, но не смог, потому что на него уже были ответы   -  person widget    schedule 31.03.2011


Ответы (6)


Самый простой и надежный известный мне способ конвертации между часовыми поясами — использовать сторонний модуль 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. Например, «27.10.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), вот как преобразовать объекты datetime, представляющие местное время, в объекты datetime, представляющие время по Гринвичу, и наоборот:

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)
person unutbu    schedule 30.03.2011
comment
@unutbu: когда дата находится в часовом поясе летнего времени, а UTC - нет????? UTC неизменен по отношению к летнему времени. В настоящее время в Великобритании используется BST (британское летнее время), которое определяется как UTC+1. - person John Machin; 31.03.2011
comment
@unutbu: я только что попробовал ваши коды (второй метод). Проблема с первым в том, что у меня нет пакета pytz. Для второго способа теперь у меня есть результат 2010-12-01 05:00:00 из '12/1/2010 0:0:0', так что это кажется идеальным. В любом случае, есть ли способ преобразовать его в исходный формат: «12/1/2010 5:0:0»? Теперь я знаю, что для преобразования других форматов в формат даты я мог бы использовать что-то вроде date=dt.datetime.strptime(text,%m/%d/%Y %H:%M:%S) , но не знаю, как для форматирования формата даты в другие. Кроме того, еще один вопрос: что, если у меня есть время по Гринвичу и я хочу преобразовать его в время EST/EDT? - person widget; 31.03.2011
comment
@widget: вы можете форматировать объекты datetime с помощью метода strftime. Например, date.strftime('%m/%d/%Y%l:%M:%S') вернет '12/01/2010 5:00:00'. Однако встроенного формата для минут и секунд, состоящих из одной цифры, не существует. Вы могли бы найти это с помощью большего количества кода, но это уродливо. Вам это действительно нужно и нужно? - person unutbu; 31.03.2011
comment
@widget: вы можете посмотреть доступные директивы строки формата strftime здесь: docs.python.org/library/. - person unutbu; 31.03.2011
comment
@widget: попробуйте выполнить инструкции здесь: pytz.sourceforge.net/#installation. Если у вас возникнут проблемы, откройте новый вопрос и укажите, какую ОС вы используете. - person unutbu; 31.03.2011
comment
@unutbu: у меня получилось. спасибо знание форматирования даты было бы очень полезно - person widget; 31.03.2011
comment
@widget: Был ли дан ответ на ваш вопрос о форматировании даты или вы ищете что-то еще? - person unutbu; 31.03.2011
comment
@unutbu: я только что нашел вопрос в ваших кодах с использованием пакета pytz: date_est=east.localize(date,is_dst=None). Если это серия разных дат, как вы могли бы просто использовать: is_dst=None для локализации наивной даты и времени? Он не конвертирует время правильно. Если вы установите для него значение None, то он будет добавлять 5 часов ко всему времени, независимо от того, EDT или EST. не могли бы вы объяснить? спасибо - person widget; 31.03.2011

Псевдокод для каждой записи:

сделать строку отметки времени: field[0].strip() + " " + field[1].strip()

используйте datetime.datetime.strptime(), чтобы преобразовать это в экземпляр datetime.datetime

добавить timedelta, например. timedelta(hours=-4) к вашей метке времени

используйте timestamp.strftime() для создания любого строкового представления, которое вы хотите для вывода.

Для случая, когда поле времени пусто: если это означает 0:0:0, измените вышеприведенное в соответствии с требованиями. Если это означает «время неизвестно», вам нужно будет сделать что-то еще...

person John Machin    schedule 30.03.2011

Предположим, что у нас есть строка даты и времени как «2019-04-09T23:59:55ET» по американскому/восточному времени. Вот функция для преобразования строки в UTC:

from datetime import datetime
import pytz

eastern = pytz.timezone('US/Eastern')

def convent_est_to_utc(datetime_str):
    dt = datetime.strptime(datetime_str, '%Y-%m-%dT%H:%M:%SET')
    return dt.replace(tzinfo=eastern).astimezone(pytz.utc)

# testing
convent_est_to_utc("2019-04-09T23:59:55ET")

# The result: 2019-04-10 04:55:55+00:00

person David P    schedule 04.04.2019

Без связанного времени часовой пояс не имеет значения ... и дату нельзя перевести в другой часовой пояс. Есть ли связанное время в другом столбце?

РЕДАКТИРОВАТЬ: Хорошо, теперь, когда ЕСТЬ время, я позволю гуру Python вступить во владение. ;]

person Joe McBride    schedule 30.03.2011
comment
Если вы добавляете новый столбец для времени, просто используйте 4:00 и измените часовой пояс на GMT (EST — это GMT-4:00). Это будет означать, что дата 00:00 EST. Я не думаю, что вам нужно было бы делать что-то еще необычное. - person Joe McBride; 30.03.2011
comment
Вы не задумывались о том, что делать, когда временные метки ввода и вывода выходят за пределы месяца. - person John Machin; 31.03.2011
comment
@John Machin: Я думал об этом, но оставил это как упражнение для виджета. - person Joe McBride; 31.03.2011

Мне пришлось создать пользовательскую функцию на Python для преобразования EST в GMT, вот код, который я написал:

#convert est time to gmt. Make sure you assign the current EST values
#to the following variables
        est_year
        est_month
        est_day
        est_hour
        est_min

        gmt_year = est_year
        gmt_month = est_month
        gmt_day = est_day
        gmt_hour = est_hour + 5 #gmt is ahead by 5 hrs
        gmt_min = est_min

        if gmt_hour > 23:
          gmt_hour = gmt_hour - 23
          gmt_day = est_day + 1

        days_in_month = calendar.monthrange(est_year,est_month)[1] #in case the no days becomes 32..

        if gmt_day > days_in_month:
          gmt_day = 1
          gmt_month = gmt_month + 1

        if gmt_month > 12:
          gmt_month = 1
          gmt_year = gmt_year + 1

        gmttime = datetime.datetime(gmt_year, gmt_month, gmt_day, gmt_hour, gmt_min, 0)

Я не добавил поддержку EDT. В настоящее время февраль, и EST отслеживается. Любые изменения и исправления приветствуются!

person Bilbo Baggins    schedule 14.02.2014

Вы можете использовать pandas.DataFrame.tz_convert() следующим образом. :

import pandas as pd
from datetime import datetime

df = pd.read_csv("your_data_file_path.csv", index_col=False, engine='python')
df['Date'] = pd.to_datetime(df['Date'])
df['Date'] = df['Date'].dt.tz_localize('US/Eastern').dt.tz_convert('UTC')
df['Date'] = df['Date'].apply(lambda x: datetime.replace(x, tzinfo=None))

Что делает последняя строка, так это удаляет информацию о часовом поясе из объекта datetime, поэтому вы можете работать только с датой и временем (не волнуйтесь, это не меняет часовой пояс снова, он просто удаляет его из строки метки времени).

person tsveti_iko    schedule 27.08.2020