Часовой пояс Python с учетом локальной строки (отказ от смещения UTC)

У меня есть входящие строки в формате UTC с учетом часового пояса, например:

'2014-11-25 01:01:00+00:00'

и хотите показать это в собственном локализованном часовом поясе - БЕЗ бита смещения UTC в конце.

например, приведенный выше пример для США/Востока должен отображаться как:

'2014-11-24 20:01:00'

Теперь я сделал небольшой метод, который будет принимать входную строку и делать это, возвращая желаемое значение. Тем не менее, это кажется ужасно неэффективным. Я использую pandas для манипулирования данными, и этот метод применяется ко всему столбцу строковых данных временных рядов в указанном выше строковом формате. Вызов метода применения через интерактивную оболочку завершил выполнение за ~ 2 секунды, но, как ни странно, выполнение кода, скомпилированного/интерпретированного в том же фрейме данных, занимает больше 15-20 секунд. Почему это? Вот как я называю это для фрейма/серии данных:

df['created_at'] = df['created_at'].apply(timeremap)

Я самоучка и явно не лучший программист. Скажите, пожалуйста, что я могу сделать, чтобы упростить этот процесс? Судя по поиску в Google, существует 5000 способов преобразования времени в python. Я открыт для любого модуля/пакета, но желательно, чтобы это было сделано в существующем стандартном питоне или пандах. Что такое «Правильный путь» для этого?

Вот мой маленький дудл:

from pandas.tseries.tools import parse_time_string
from pytz import timezone
import calendar
import datetime

def timeremap(intimestr, tz=timezone('US/Eastern')):
    temp = parse_time_string(intimestr)[0]
    loc = temp.astimezone(tz)
    return str(dt(ut(loc)))

def dt(u):
    return datetime.datetime.utcfromtimestamp(u)
def ut(d):
    return calendar.timegm(d.timetuple())

person ACVentures    schedule 27.11.2014    source источник


Ответы (1)


Если вам предоставлен CSV-файл с данными, проиндексированными по времени:

time,value
2015-11-01 08:30:00+03:00,0
2015-11-01 08:45:00+03:00,1
2015-11-01 09:00:00+03:00,2
2015-11-01 09:15:00+03:00,3
2015-11-01 09:30:00+03:00,4
2015-11-01 09:45:00+03:00,5
2015-11-01 10:00:00+03:00,6
2015-11-01 10:15:00+03:00,7

Вы можете использовать read_csv(), чтобы прочитать его и проанализировать строку времени, и tz_convert(), чтобы преобразовать ввод в часовой пояс назначения:

#!/usr/bin/env python
import sys
import pandas
import pytz

filename = 'dataframe'
local_tz = pytz.timezone('America/New_York')

df = pandas.read_csv(filename, parse_dates=True, index_col=0)
df.index = df.index.tz_localize(pytz.utc).tz_convert(local_tz)
df.head().to_csv(sys.stdout)
df.head().to_csv(sys.stdout, date_format='%Y-%m-%d %H:%M:%S')

Здесь каждое значение индекса изначально сохраняется как время по Гринвичу без связанного часового пояса (до преобразования):

print(repr(df.index[0]))
# -> Timestamp('2015-11-01 05:30:00', tz=None)

Или вы можете преобразовать время во время чтения:

from dateutil.parser import parse

def parse_datetime(time_string, tz=local_tz):
    return tz.normalize(parse(time_string).astimezone(tz))

df = pandas.read_csv(filename, date_parser=parse_datetime, index_col=0)
df.head().to_csv(sys.stdout)
df.head().to_csv(sys.stdout, date_format='%Y-%m-%d %H:%M:%S')

Здесь каждое значение индекса имеет связанный часовой пояс:

print(repr(df.index[0]))
# -> Timestamp('2015-11-01 01:30:00-0400', tz='America/New_York')

Выход

time,value
2015-11-01 01:30:00-04:00,0
2015-11-01 01:45:00-04:00,1
2015-11-01 01:00:00-05:00,2
2015-11-01 01:15:00-05:00,3
2015-11-01 01:30:00-05:00,4
time,value
2015-11-01 01:30:00,0
2015-11-01 01:45:00,1
2015-11-01 01:00:00,2
2015-11-01 01:15:00,3
2015-11-01 01:30:00,4

Оба метода дают одинаковый результат.

Обратите внимание: как date_format используется для «отбрасывания» смещения utc, которое устраняет неоднозначность строк времени (переход конца летнего времени 1 ноября 2015 года в часовом поясе Америки/Нью-Йорка).

person jfs    schedule 01.03.2015