Преобразование pandas с учетом времени в DateTimeIndex в наивную временную метку, но в определенный часовой пояс

Вы можете использовать функцию tz_localize чтобы tz_localize Timestamp или DateTimeIndex, но как вы можете сделать обратное: как вы можете преобразовать tz_localize времени в наивную, сохраняя ее часовой пояс?

Пример:

 In [82]: t = pd.date_range(start="2013-05-18 12:00:00", periods=10, freq='s', tz="Europe/Brussels") In [83]: t Out[83]: <class 'pandas.tseries.index.DatetimeIndex'> [2013-05-18 12:00:00, ..., 2013-05-18 12:00:09] Length: 10, Freq: S, Timezone: Europe/Brussels 

Я могу удалить часовой пояс, установив его в None, но затем результат преобразуется в UTC (12 часов – 10):

 In [86]: t.tz = None In [87]: t Out[87]: <class 'pandas.tseries.index.DatetimeIndex'> [2013-05-18 10:00:00, ..., 2013-05-18 10:00:09] Length: 10, Freq: S, Timezone: None 

Есть ли другой способ преобразовать DateTimeIndex в наименьший часовой пояс, но, сохранив часовой пояс, он был установлен?


Некоторый контекст по причине, о которой я спрашиваю: я хочу работать с наименьшими временными часами (чтобы избежать лишних хлопот с часовыми поясами, и я не нуждаюсь в них для случая, над которым я работаю).
Но по какой-то причине мне приходится иметь дело с таймсерами с учетом часовых поясов в моем местном часовом поясе (Европа / Брюссель). Поскольку все мои другие данные являются наименее часовыми (но представленными в моем местном часовом поясе), я хочу преобразовать эти таймеры в наивную для дальнейшей работы с ней, но ее также нужно представлять в моем локальном часовом поясе (так что просто удаляйте информацию о часовом поясе, без преобразования видимого пользователем времени в UTC).

Я знаю, что время на самом деле внутренне хранится как UTC и только преобразуется в другой часовой пояс, когда вы его представляете, поэтому должно быть какое-то преобразование, когда я хочу «делокализовать» его. Например, с модулем datetime python вы можете «удалить» часовой пояс следующим образом:

 In [119]: d = pd.Timestamp("2013-05-18 12:00:00", tz="Europe/Brussels") In [120]: d Out[120]: <Timestamp: 2013-05-18 12:00:00+0200 CEST, tz=Europe/Brussels> In [121]: d.replace(tzinfo=None) Out[121]: <Timestamp: 2013-05-18 12:00:00> 

Поэтому, основываясь на этом, я мог бы сделать следующее, но я полагаю, что это будет не очень эффективно при работе с более крупными серверами времени:

 In [124]: t Out[124]: <class 'pandas.tseries.index.DatetimeIndex'> [2013-05-18 12:00:00, ..., 2013-05-18 12:00:09] Length: 10, Freq: S, Timezone: Europe/Brussels In [125]: pd.DatetimeIndex([i.replace(tzinfo=None) for i in t]) Out[125]: <class 'pandas.tseries.index.DatetimeIndex'> [2013-05-18 12:00:00, ..., 2013-05-18 12:00:09] Length: 10, Freq: None, Timezone: None 

  • datetime до метки времени Unix с точностью до миллисекунды
  • Как читать файл по строкам в Python?
  • Могу ли я гнездо TestCases с носом?
  • Numpy: внешний продукт из n векторов
  • Полосы пробелов / вкладки / новые строки - python
  • Как расширить модуль python? (Python-Twitter)
  • Проблемы с numpy в PyCharm
  • Python Script выполняет команды в терминале
  • 4 Solutions collect form web for “Преобразование pandas с учетом времени в DateTimeIndex в наивную временную метку, но в определенный часовой пояс”

    Чтобы ответить на мой собственный вопрос, эта функциональность была добавлена ​​к пандам тем временем. Начиная с pandas 0.15.0 , вы можете использовать tz_localize(None) чтобы удалить часовой пояс, приводящий к местному времени.
    См. Whatsnew запись: http://pandas.pydata.org/pandas-docs/stable/whatsnew.html#timezone-handling-improvements

    Итак, с моим примером сверху:

     In [4]: t = pd.date_range(start="2013-05-18 12:00:00", periods=2, freq='H', tz= "Europe/Brussels") In [5]: t Out[5]: DatetimeIndex(['2013-05-18 12:00:00+02:00', '2013-05-18 13:00:00+02:00'], dtype='datetime64[ns, Europe/Brussels]', freq='H') 

    использование tz_localize(None) удаляет информацию о часовом поясе, приводящую к наивному местному времени :

     In [6]: t.tz_localize(None) Out[6]: DatetimeIndex(['2013-05-18 12:00:00', '2013-05-18 13:00:00'], dtype='datetime64[ns]', freq='H') 

    Кроме того, вы можете также использовать tz_convert(None) для удаления информации о часовом поясе, но конвертирования в UTC, что дает наивное время UTC :

     In [7]: t.tz_convert(None) Out[7]: DatetimeIndex(['2013-05-18 10:00:00', '2013-05-18 11:00:00'], dtype='datetime64[ns]', freq='H') 

    Это намного эффективнее, чем решение datetime.replace :

     In [31]: t = pd.date_range(start="2013-05-18 12:00:00", periods=10000, freq='H', tz="Europe/Brussels") In [32]: %timeit t.tz_localize(None) 1000 loops, best of 3: 233 µs per loop In [33]: %timeit pd.DatetimeIndex([i.replace(tzinfo=None) for i in t]) 10 loops, best of 3: 99.7 ms per loop 

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

    Основная проблема заключается в том, что временные метки (как вам кажется) состоят из двух частей. Данные, представляющие время UTC, и часовой пояс tz_info. Информация о часовом поясе используется только для показа при печати временной шкалы на экране. Во время отображения данные смещаются соответственно, а в строку добавляется +01: 00 (или аналогичный). Снятие значения tz_info (с использованием tz_convert (tz = None)) фактически не изменяет данные, представляющие наивную часть метки времени.

    Таким образом, единственный способ сделать то, что вам нужно, – изменить базовые данные (pandas не позволяет это … DatetimeIndex неизменяемы – см. Справку по DatetimeIndex) или создать новый набор объектов timestamp и обернуть их в новом DatetimeIndex. Ваше решение делает последнее:

     pd.DatetimeIndex([i.replace(tzinfo=None) for i in t]) 

    Для справки, здесь используется метод replace Timestamp (см. Tslib.pyx):

     def replace(self, **kwds): return Timestamp(datetime.replace(self, **kwds), offset=self.offset) 

    Вы можете обратиться к документам datetime.datetime чтобы увидеть, что datetime.datetime.replace также создает новый объект.

    Если вы можете, лучшим вариантом для эффективности является изменение источника данных, чтобы он (некорректно) сообщал временные метки без их часового пояса. Ты упомянул:

    Я хочу работать с наименьшими временными часами (чтобы избежать лишних хлопот с часовыми поясами, и я не нуждаюсь в них для случая, над которым я работаю)

    Мне было бы любопытно, что лишний хлопот вы имеете в виду. Я рекомендую в качестве общего правила для всей разработки программного обеспечения, сохраняйте ваши наивные значения timestamp в UTC. Существует немного хуже, чем смотреть на два разных значения int64, интересующихся, к какому временному диапазону они относятся. Если вы всегда, всегда, всегда используете UTC для внутреннего хранилища, тогда вы избежите бесчисленных головных болей. Моя мантра Timezones предназначена только для ввода / вывода людей .

    Кажется, что значение атрибута tz индекса явно работает:

     ts_utc = ts.tz_convert("UTC") ts_utc.index.tz = None 

    Основываясь на предположении DA, что « единственный способ сделать то, что вы хотите, – изменить базовые данные » и использовать numpy для изменения базовых данных …

    Это работает для меня, и довольно быстро:

     def tz_to_naive(datetime_index): """Converts a tz-aware DatetimeIndex into a tz-naive DatetimeIndex, effectively baking the timezone into the internal representation. Parameters ---------- datetime_index : pandas.DatetimeIndex, tz-aware Returns ------- pandas.DatetimeIndex, tz-naive """ # Calculate timezone offset relative to UTC timestamp = datetime_index[0] tz_offset = (timestamp.replace(tzinfo=None) - timestamp.tz_convert('UTC').replace(tzinfo=None)) tz_offset_td64 = np.timedelta64(tz_offset) # Now convert to naive DatetimeIndex return pd.DatetimeIndex(datetime_index.values + tz_offset_td64) 
    Python - лучший язык программирования в мире.