Преобразование между datetime, Timestamp и datetime64

как преобразовать numpy.datetime64 объект datetime.datetime (или Timestamp)?

в следующем коде я создаю объекты datetime, timestamp и datetime64.

import datetime
import numpy as np
import pandas as pd
dt = datetime.datetime(2012, 5, 1)
# A strange way to extract a Timestamp object, there's surely a better way?
ts = pd.DatetimeIndex([dt])[0]
dt64 = np.datetime64(dt)

In [7]: dt
Out[7]: datetime.datetime(2012, 5, 1, 0, 0)

In [8]: ts
Out[8]: <Timestamp: 2012-05-01 00:00:00>

In [9]: dt64
Out[9]: numpy.datetime64('2012-05-01T01:00:00.000000+0100')

Примечание: легко получить datetime из метки времени:

In [10]: ts.to_datetime()
Out[10]: datetime.datetime(2012, 5, 1, 0, 0)

но как мы извлекаем datetime или Timestamp С numpy.datetime64 (dt64)?

.

Update: несколько неприятный пример в моем наборе данных (возможно, мотивирующий пример) кажется:

dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')

что должно быть datetime.datetime(2002, 6, 28, 1, 0), и не долго (!) (1025222400000000000L)...

12 ответов


преобразование numpy.datetime64 к объекту datetime, который представляет время в UTC on numpy-1.8:

>>> from datetime import datetime
>>> import numpy as np
>>> dt = datetime.utcnow()
>>> dt
datetime.datetime(2012, 12, 4, 19, 51, 25, 362455)
>>> dt64 = np.datetime64(dt)
>>> ts = (dt64 - np.datetime64('1970-01-01T00:00:00Z')) / np.timedelta64(1, 's')
>>> ts
1354650685.3624549
>>> datetime.utcfromtimestamp(ts)
datetime.datetime(2012, 12, 4, 19, 51, 25, 362455)
>>> np.__version__
'1.8.0.dev-7b75899'

в приведенном выше примере предполагается, что наивный datetime объект интерпретируется np.datetime64 как время в UTC.


преобразовать datetime в np.datetime64 и обратно (numpy-1.6):

>>> np.datetime64(datetime.utcnow()).astype(datetime)
datetime.datetime(2012, 12, 4, 13, 34, 52, 827542)

он работает как на одном np.объект datetime64 и массив numpy np.datetime64.

подумайте о np.datetime64 так же, как и о np.int8, np.int16 и т.д. и применять те же методы для преобразования beetween Python объектов, таких как int, datetime и соответствующих numpy объектов.

ваш "неприятный пример" работает правильно:

>>> from datetime import datetime
>>> import numpy 
>>> numpy.datetime64('2002-06-28T01:00:00.000000000+0100').astype(datetime)
datetime.datetime(2002, 6, 28, 0, 0)
>>> numpy.__version__
'1.6.2' # current version available via pip install numpy

Я могу воспроизвести long значение on numpy-1.8.0 установлен, как:

pip install git+https://github.com/numpy/numpy.git#egg=numpy-dev

тот же пример:

>>> from datetime import datetime
>>> import numpy
>>> numpy.datetime64('2002-06-28T01:00:00.000000000+0100').astype(datetime)
1025222400000000000L
>>> numpy.__version__
'1.8.0.dev-7b75899'

возвращает long потому что numpy.datetime64 тип .astype(datetime) эквивалентно .astype(object), который возвращает целое число Python (long) on numpy-1.8.

чтобы получить объект datetime можно:

>>> dt64.dtype
dtype('<M8[ns]')
>>> ns = 1e-9 # number of seconds in a nanosecond
>>> datetime.utcfromtimestamp(dt64.astype(int) * ns)
datetime.datetime(2002, 6, 28, 0, 0)

чтобы получить datetime64, который использует секунды напрямую:

>>> dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100', 's')
>>> dt64.dtype
dtype('<M8[s]')
>>> datetime.utcfromtimestamp(dt64.astype(int))
datetime.datetime(2002, 6, 28, 0, 0)

на numpy docs скажем, что API datetime является экспериментальным и может измениться в будущих версиях numpy.


вы можете просто использовать pd.Конструктор временных меток. Для этого и связанных с этим вопросов может быть полезна следующая диаграмма.

Conversions between time representations


Добро пожаловать в ад.

вы можете просто передать объект datetime64 в pandas.Timestamp:

In [16]: Timestamp(numpy.datetime64('2012-05-01T01:00:00.000000'))
Out[16]: <Timestamp: 2012-05-01 01:00:00>

я заметил, что это не работает правильно, хотя в NumPy 1.6.1:

numpy.datetime64('2012-05-01T01:00:00.000000+0100')

и pandas.to_datetime может использоваться (это выключено из версии dev, не проверено v0.9.1):

In [24]: pandas.to_datetime('2012-05-01T01:00:00.000000+0100')
Out[24]: datetime.datetime(2012, 5, 1, 1, 0, tzinfo=tzoffset(None, 3600))

я думаю, что могут быть более консолидированные усилия в ответе, чтобы лучше объяснить связь между модулем datetime Python, datetime64/timedelta64 numpy и объектами Timestamp/Timedelta pandas.

стандартная библиотека datetime Python

стандартная библиотека datetime имеет четыре основных объектов

  • время - время, измеряемое в часах, минутах, секундах и микросекундах
  • даты - только год, месяц и день
  • datetime-все компоненты времени и даты
  • timedelta-количество времени с максимальной единицей дней

создайте эти четыре объекта

>>> import datetime
>>> datetime.time(hour=4, minute=3, second=10, microsecond=7199)
datetime.time(4, 3, 10, 7199)

>>> datetime.date(year=2017, month=10, day=24)
datetime.date(2017, 10, 24)

>>> datetime.datetime(year=2017, month=10, day=24, hour=4, minute=3, second=10, microsecond=7199)
datetime.datetime(2017, 10, 24, 4, 3, 10, 7199)

>>> datetime.timedelta(days=3, minutes = 55)
datetime.timedelta(3, 3300)

>>> # add timedelta to datetime
>>> datetime.timedelta(days=3, minutes = 55) + \
    datetime.datetime(year=2017, month=10, day=24, hour=4, minute=3, second=10, microsecond=7199)
datetime.datetime(2017, 10, 27, 4, 58, 10, 7199)

объекты datetime64 и timedelta64 NumPy

NumPy не имеет отдельных объектов даты и времени, только один объект datetime64 для представления одного момента времени. Объект datetime модуля datetime имеет точность микросекунды (одна миллионная секунды). Объект datetime64 NumPy позволяет установить его точность от часов до аттосекунд (10 ^ -18). Это конструктор более гибкий и может принимать различные входные данные.

построить объекты datetime64 и timedelta64 NumPy

передать целое число со строкой для единиц. Смотрите все единицы здесь. Он преобразуется во многие единицы после эпохи UNIX: 1 января 1970

>>> np.datetime64(5, 'ns') 
numpy.datetime64('1970-01-01T00:00:00.000000005')

>>> np.datetime64(1508887504, 's')
numpy.datetime64('2017-10-24T23:25:04')

вы также можете использовать струны, пока они находятся в Формат ISO 8601.

>>> np.datetime64('2017-10-24')
numpy.datetime64('2017-10-24')

Timedeltas имеют один блок

>>> np.timedelta64(5, 'D') # 5 days
>>> np.timedelta64(10, 'h') 10 hours

также можно создать их, вычитая два объекта datetime64

>>> np.datetime64('2017-10-24T05:30:45.67') - np.datetime64('2017-10-22T12:35:40.123')
numpy.timedelta64(147305547,'ms')

панды отметка времени и Timedelta построить гораздо больше функциональности поверх NumPy

временная метка панды-это момент времени, очень похожий на datetime, но с гораздо большей функциональностью. Вы можете построить их с помощью любого pd.Timestamp или pd.to_datetime.

>>> pd.Timestamp(1239.1238934) #defautls to nanoseconds
Timestamp('1970-01-01 00:00:00.000001239')

>>> pd.Timestamp(1239.1238934, unit='D') # change units
Timestamp('1973-05-24 02:58:24.355200')

>>> pd.Timestamp('2017-10-24 05') # partial strings work
Timestamp('2017-10-24 05:00:00')

pd.to_datetime очень работает аналогично (с несколькими дополнительными параметрами) и может конвертировать список строк в метки времени.

>>> pd.to_datetime('2017-10-24 05')
Timestamp('2017-10-24 05:00:00')

>>> pd.to_datetime(['2017-1-1', '2017-1-2'])
DatetimeIndex(['2017-01-01', '2017-01-02'], dtype='datetime64[ns]', freq=None)

преобразование Python datetime в datetime64 и отметку времени

>>> dt = datetime.datetime(year=2017, month=10, day=24, hour=4, 
                   minute=3, second=10, microsecond=7199)
>>> np.datetime64(dt)
numpy.datetime64('2017-10-24T04:03:10.007199')

>>> pd.Timestamp(dt) # or pd.to_datetime(dt)
Timestamp('2017-10-24 04:03:10.007199')

преобразование numpy datetime64 в datetime и отметку времени

>>> dt64 = np.datetime64('2017-10-24 05:34:20.123456')
>>> unix_epoch = np.datetime64(0, 's')
>>> one_second = np.timedelta64(1, 's')
>>> seconds_since_epoch = (dt64 - unix_epoch) / one_second
>>> seconds_since_epoch
1508823260.123456

>>> datetime.datetime.utcfromtimestamp(seconds_since_epoch)
>>> datetime.datetime(2017, 10, 24, 5, 34, 20, 123456)

преобразовать в метку

>>> pd.Timestamp(dt64)
Timestamp('2017-10-24 05:34:20.123456')

преобразование из метки времени в datetime и datetime64

это довольно легко, так как временные метки панд очень мощные

>>> ts = pd.Timestamp('2017-10-24 04:24:33.654321')

>>> ts.to_pydatetime()   # Python's datetime
datetime.datetime(2017, 10, 24, 4, 24, 33, 654321)

>>> ts.to_datetime64()
numpy.datetime64('2017-10-24T04:24:33.654321000')

>>> dt64.tolist()
datetime.datetime(2012, 5, 1, 0, 0)

на DatetimeIndex на tolist возвращает список datetime объекты. Для одного datetime64 объект возвращает один datetime "объект".


Если вы хотите преобразовать всю серию pandas datetimes в обычные Python datetimes, вы также можете использовать .to_pydatetime().

pd.date_range('20110101','20110102',freq='H').to_pydatetime()

> [datetime.datetime(2011, 1, 1, 0, 0) datetime.datetime(2011, 1, 1, 1, 0)
   datetime.datetime(2011, 1, 1, 2, 0) datetime.datetime(2011, 1, 1, 3, 0)
   ....

Он также поддерживает часовые пояса:

pd.date_range('20110101','20110102',freq='H').tz_localize('UTC').tz_convert('Australia/Sydney').to_pydatetime()

[ datetime.datetime(2011, 1, 1, 11, 0, tzinfo=<DstTzInfo 'Australia/Sydney' EST+11:00:00 DST>)
 datetime.datetime(2011, 1, 1, 12, 0, tzinfo=<DstTzInfo 'Australia/Sydney' EST+11:00:00 DST>)
....

один из вариантов-использовать str, а потом to_datetime (или похожие):

In [11]: str(dt64)
Out[11]: '2012-05-01T01:00:00.000000+0100'

In [12]: pd.to_datetime(str(dt64))
Out[12]: datetime.datetime(2012, 5, 1, 1, 0, tzinfo=tzoffset(None, 3600))

Примечание: это не равно dt потому что это стало "offset-aware":

In [13]: pd.to_datetime(str(dt64)).replace(tzinfo=None)
Out[13]: datetime.datetime(2012, 5, 1, 1, 0)

это выглядит неэлегантно.

.

Update: это может иметь дело с "неприятный"пример:

In [21]: dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')

In [22]: pd.to_datetime(str(dt64)).replace(tzinfo=None)
Out[22]: datetime.datetime(2002, 6, 28, 1, 0)

этот пост был в течение 4 лет, и я все еще боролся с этой проблемой преобразования - поэтому проблема все еще активна в 2017 году в некотором смысле. Я был несколько шокирован тем, что документация numpy не предлагает простой алгоритм преобразования, но это другая история.

я столкнулся с другим способом сделать преобразование, которое включает только модули numpy и datetime, это не требует, чтобы панды импортировались, что мне кажется, много кода для импорта для таких простое преобразование. Я заметил это datetime64.astype(datetime.datetime) вернет datetime.datetime объект, если исходное datetime64 находится в микро-второго блоков в то время как другие единицы возвращают целочисленную метку времени. Я использую модуль xarray для ввода-вывода данных из файлов Netcdf, который использует datetime64 в наносекундных единицах, что делает преобразование не удастся, если вы сначала преобразовать в микро-вторых единиц. Вот пример кода преобразования,

import numpy as np
import datetime

def convert_datetime64_to_datetime( usert: np.datetime64 )->datetime.datetime:
    t = np.datetime64( usert, 'us').astype(datetime.datetime)
return t

его только протестировано на моей машине, которая является Python 3.6 с недавним 2017 Распределение анаконда. Я только посмотрел на скалярное преобразование и не проверил преобразования на основе массива, хотя я предполагаю, что это будет хорошо. Я также не смотрел на исходный код numpy datetime64, чтобы увидеть, имеет ли операция смысл или нет.


я возвращался к этому ответу больше раз, чем могу сосчитать, поэтому я решил собрать быстрый маленький класс, который преобразует Numpy datetime64 значение для Python datetime значение. Надеюсь, это поможет другим.

from datetime import datetime
import pandas as pd

class NumpyConverter(object):
    @classmethod
    def to_datetime(cls, dt64, tzinfo=None):
        """
        Converts a Numpy datetime64 to a Python datetime.
        :param dt64: A Numpy datetime64 variable
        :type dt64: numpy.datetime64
        :param tzinfo: The timezone the date / time value is in
        :type tzinfo: pytz.timezone
        :return: A Python datetime variable
        :rtype: datetime
        """
        ts = pd.to_datetime(dt64)
        if tzinfo is not None:
            return datetime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, tzinfo=tzinfo)
        return datetime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second)

Я буду держать это в моей сумке для инструментов, что-то говорит мне, что мне это снова понадобится.


действительно, все эти типы datetime могут быть сложными и потенциально проблематичными (необходимо тщательно отслеживать информацию о часовом поясе). вот что я сделал, хотя я признаю, что я обеспокоен тем, что по крайней мере часть его "не по проекту". кроме того, это может быть сделано немного более компактным по мере необходимости. начиная с numpy.datetime64 dt_a:

dt_a

и NumPy.datetime64('2015-04-24T23:11:26.270000-0700')

dt_a1 = dt_a.tolist () # дает объект datetime в формате UTC, но без tzinfo

dt_a1

datetime.datetime(2015, 4, 25, 6, 11, 26, 270000)

# now, make your "aware" datetime:

dt_a2=datetime.datetime (*list (dt_a1.timetuple () [: 6]) + [dt_a1.микросекунда], tzinfo=pytz.часовой пояс ('UTC'))

... и конечно, это можно сжать в одну строку по мере необходимости.


import numpy as np
import pandas as pd 

def np64toDate(np64):
    return pd.to_datetime(str(np64)).replace(tzinfo=None).to_datetime()

используйте эту функцию, чтобы получить pythons native datetime object


некоторые решения хорошо работают для меня, но numpy будет устаревать некоторые параметры. Решение, которое работает лучше для меня, - прочитать дату как дату-время pandas и явно вычеркнуть год, месяц и день объекта pandas. Следующий код работает для наиболее распространенных ситуаций.

def format_dates(dates):
    dt = pd.to_datetime(dates)
    try: return [datetime.date(x.year, x.month, x.day) for x in dt]    
    except TypeError: return datetime.date(dt.year, dt.month, dt.day)