Konwersja pomiędzy datetime, Timestamp i datetime64

Jak przekonwertować obiekt numpy.datetime64 na datetime.datetime (lub Timestamp)?

W poniższym kodzie tworzę obiekty datetime, timestamp oraz 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')

Uwaga: łatwo jest pobrać datetime ze znacznika czasu:

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

Ale jak wyodrębnić datetime lub Timestamp z numpy.datetime64 (dt64)?

.

Aktualizacja: nieco paskudny przykład w moim zbiorze danych (być może przykład motywujący) wydaje się być:

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

Które powinno być datetime.datetime(2002, 6, 28, 1, 0), oraz nie długo (!) (1025222400000000000L)...

Author: Andy Hayden, 2012-12-04

12 answers

Aby przekonwertować numpy.datetime64 na obiekt datetime, który reprezentuje czas w UTC na 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'

Powyższy przykład zakłada, że naiwny obiekt datetime jest interpretowany przez np.datetime64 jako czas w UTC.


Aby przekonwertować datetime na np.datetime64 i z powrotem (numpy-1.6):

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

Działa zarówno na pojedynczym np.obiekt datetime64 i tablica numpy np.datetime64

Pomyśl o np.datetime64 tak samo jak o np. int8, np. int16, itd. i zastosować te same metody do konwertuje obiekty Pythona takie jak int, datetime i odpowiadające im obiekty numpy.

Twój "paskudny przykład" działa poprawnie:

>>> 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

Mogę odtworzyć long wartość na numpy-1.8.0 zainstalowaną jako:

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

Ten sam przykład:

>>> 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'

Zwraca long, ponieważ dla numpy.datetime64 typ {[15] } jest odpowiednikiem .astype(object), który zwraca Python integer (long) na numpy-1.8.

Aby uzyskać obiekt datetime można:

>>> 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)

Aby uzyskać datetime64, który używa sekund bezpośrednio:

>>> 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)

Dokumenty numpy mówią, że API datetime jest eksperymentalne i może ulec zmianie w przyszłych wersjach numpy.

 95
Author: jfs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-04 20:30:33

Możesz po prostu skorzystać z pd.Konstruktor znaczników czasu. Poniższy diagram może być przydatny dla tego i powiązanych pytań.

Konwersje pomiędzy reprezentacjami czasu

 147
Author: Quant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-20 18:17:06

Witaj w piekle.

Możesz po prostu przekazać obiekt datetime64 do pandas.Timestamp:

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

Zauważyłem, że to nie działa dobrze chociaż w NumPy 1.6.1:

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

Można również użyć pandas.to_datetime (jest to wyłączone z wersji dev, nie sprawdzałem 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))
 100
Author: Wes McKinney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-06 22:40:22

Myślę, że istnieje bardziej skonsolidowany wysiłek w odpowiedzi, aby lepiej wyjaśnić związek między modułem DateTime Pythona, datetime64/timedelta64 numpy i obiektami timestamp/Timedelta pandy.

Standardowa biblioteka DateTime w Pythonie

Biblioteka standardowa datetime ma cztery główne obiekty

  • czas-tylko czas, mierzony w godzinach, minutach, sekundach i mikrosekundach
  • Data-tylko rok, miesiąc i dzień
  • datetime-All składniki czasu i daty
  • timedelta-ilość czasu z maksymalną jednostką dni

Utwórz te cztery obiekty

>>> 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)

NumPy ' s datetime64 and timedelta64 objects

NumPy nie ma oddzielnych obiektów daty i czasu, tylko pojedynczy obiekt datetime64 reprezentujący pojedynczy moment w czasie. Obiekt datetime modułu DateTime ma mikrosekundową precyzję (jedną milionową sekundy). Obiekt datetime64 NumPy pozwala ustawić jego dokładność z godzin wszystkich sposób na attosekundy (10 ^ -18). Jego konstruktor jest bardziej elastyczny i może przyjmować różne dane wejściowe.

Konstruuj Obiekty Datetime64 i timedelta64 NumPy

Podaj liczbę całkowitą z ciągiem znaków dla jednostek. Zobacz wszystkie jednostki tutaj . Jest on konwertowany do wielu jednostek po epoce Uniksa: Jan 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')

Można również używać ciągów, o ile są one w formacie ISO 8601.

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

Timedeltas mają jedną jednostkę

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

Może również utwórz je, odejmując dwa obiekty datetime64

>>> np.datetime64('2017-10-24T05:30:45.67') - np.datetime64('2017-10-22T12:35:40.123')
numpy.timedelta64(147305547,'ms')
Pandy Timestamp i Timedelta budują znacznie więcej funkcjonalności na NumPy]}

Znacznik czasu pandy jest momentem bardzo podobnym do datetime, ale o wiele bardziej funkcjonalnym. Można je konstruować za pomocą pd.Timestamp lub 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 Działa bardzo podobnie (z kilkoma opcjami) i może konwertować listę ciągów znaków na znaczniki czasu.

>>> 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)

Konwersja Pythona datetime do datetime64 i Timestamp

>>> 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')

Konwersja numpy datetime64 na datetime i Timestamp

>>> 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)

Konwertuj na znacznik czasu

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

Konwertuj ze znacznika czasu na datetime i datetime64

Jest to dość proste, ponieważ znaczniki czasu pand są bardzo potężne.]}
>>> 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')
 41
Author: Ted Petrou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-19 14:48:53
>>> dt64.tolist()
datetime.datetime(2012, 5, 1, 0, 0)

Dla DatetimeIndex, tolist zwraca listę obiektów datetime. Dla pojedynczego obiektu datetime64 zwraca on pojedynczy obiekt datetime.

 24
Author: eumiro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-04 13:22:10

Jeśli chcesz przekonwertować całą serię pand datetimes do zwykłych datetimes Pythona, możesz również użyć .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)
   ....

Obsługuje również strefy czasowe:

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>)
....
 8
Author: fantabolous,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-15 09:41:31

Jedną z opcji jest użycie str, a następnie to_datetime (lub podobnych):

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))

uwaga: nie jest równa dt, ponieważ stała się "offset-aware":

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

.

Update: to może poradzić sobie z "przykrym przykładem":

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)
 7
Author: Andy Hayden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:48

Ten post działa od 4 lat i nadal zmagałem się z tym problemem konwersji - więc problem jest nadal aktywny w 2017 w pewnym sensie. Byłem nieco zszokowany, że dokumentacja numpy nie oferuje prostego algorytmu konwersji, ale to już inna historia.

Natknąłem się na inny sposób konwersji, który obejmuje tylko moduły numpy i datetime, nie wymaga importowania pand co wydaje mi się być dużo kodu do importowania dla tak prostego nawrócenie. Zauważyłem, że datetime64.astype(datetime.datetime) zwróci obiekt datetime.datetime, Jeśli Oryginalny datetime64znajduje się w mikro-sekundowych jednostkach, podczas gdy inne jednostki zwracają liczbę całkowitą znacznika czasu. Używam modułu xarray do danych I / o z plików Netcdf, który używa datetime64 w jednostkach nanosekund, co powoduje, że konwersja nie powiedzie się, chyba że najpierw przekonwertujesz na jednostki mikro-sekundowe. Oto przykładowy kod konwersji,

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

Jest testowany tylko na mojej maszynie, czyli Pythonie 3.6 z niedawną dystrybucją Anaconda 2017. Mam tylko spojrzałem na konwersję skalarną i nie sprawdziłem konwersji opartych na tablicach, chociaż zgaduję, że będzie dobrze. Nie spojrzałem też na kod źródłowy numpy datetime64, aby sprawdzić, czy operacja ma sens, czy nie.

 3
Author: ndl303,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-13 11:01:25

Wróciłem do tej odpowiedzi więcej razy, niż mogę zliczyć, więc postanowiłem stworzyć szybką małą klasę, która zamienia wartość Numpy datetime64 na wartość Pythona datetime. Mam nadzieję, że to pomoże innym.

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)
Będę trzymał to w torbie z narzędziami, coś mi mówi, że będę go potrzebował.
 1
Author: MikeyE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-02 06:59:32

Rzeczywiście, wszystkie te typy datetime mogą być trudne i potencjalnie problematyczne (należy uważnie śledzić informacje o strefie czasowej). oto, co zrobiłem, choć przyznaję, że martwię się, że przynajmniej część z nich jest "nie z założenia". w razie potrzeby można to zrobić nieco bardziej kompaktowo. zaczynając od numpy.datetime64 dt_a:

Dt_a

Numpy.datetime64 ("2015-04-24t23:11:26.270000-0700')

Dt_a1 = dt_a. tolist () # daje datetime obiekt w UTC, ale bez 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.mikrosekunda], tzinfo=pytz.timezone ('UTC'))

... i oczywiście, że można skompresować w jednej linii w razie potrzeby.

 0
Author: yoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-04 18:37:14
import numpy as np
import pandas as pd 

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

Użyj tej funkcji, aby uzyskać natywny obiekt datetime pythons

 0
Author: Crystal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-05 16:04:56

Niektóre rozwiązania działają dobrze dla mnie, ale numpy będzie deprecjonować niektóre parametry. Rozwiązaniem, które działa lepiej dla mnie jest odczytanie daty jako datetime pandy i excract jawnie Rok, Miesiąc i dzień obiektu pandy. Poniższy kod działa dla najczęstszej sytuacji.

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)
 0
Author: João Gabriel John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-22 16:58:16