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
)...
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.
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ń.
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))
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')
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
.
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>)
....
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)
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 datetime64
znajduje 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.
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ł.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:
Numpy.datetime64 ("2015-04-24t23:11:26.270000-0700')Dt_a
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.
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
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)
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