it-swarm.com.de

Konvertieren zwischen datetime, Timestamp und datetime64

Wie konvertiere ich ein numpy.datetime64-Objekt in einen datetime.datetime (oder Timestamp)?

Im folgenden Code erstelle ich ein datetime-, timestamp- und datetime64-Objekt.

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

Hinweis: Die Datumszeit kann leicht vom Zeitstempel abgerufen werden:

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

Wie aber extrahieren wir die datetime oder Timestamp aus einem numpy.datetime64 (dt64)?

.

Update: Ein etwas unangenehmes Beispiel in meinem Datensatz (vielleicht das motivierende Beispiel) scheint zu sein:

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

was sollte datetime.datetime(2002, 6, 28, 1, 0) sein, und nicht ein langer (!) (1025222400000000000L) ...

216
Andy Hayden

So konvertieren Sie numpy.datetime64 in ein datetime-Objekt, das die Uhrzeit in UTC auf numpy-1.8 darstellt:

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

Im obigen Beispiel wird davon ausgegangen, dass ein naives datetime-Objekt von np.datetime64 als Uhrzeit in UTC interpretiert wird.


So konvertieren Sie datetime in np.datetime64 und zurück (numpy-1.6):

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

Es funktioniert sowohl für ein einzelnes np.datetime64-Objekt als auch für ein numpy-Array von np.datetime64.

Stellen Sie sich np.datetime64 genauso vor, wie Sie es mit np.int8, np.int16 usw. tun würden, und wenden Sie dieselben Methoden zum Konvertieren von Python-Objekten wie int, datetime und entsprechenden numpy-Objekten an.

Dein "böses Beispiel" funktioniert korrekt:

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

Ich kann den long-Wert auf numpy-1.8.0 wie folgt reproduzieren:

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

Das gleiche Beispiel:

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

Es gibt long zurück, da für numpy.datetime64 der Typ .astype(datetime) äquivalent ist mit .astype(object), das die Python-Ganzzahl (long) für numpy-1.8 zurückgibt. 

Um ein Zeitobjekt zu erhalten, können Sie:

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

So rufen Sie datetime64 ab, das Sekunden direkt verwendet:

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

Die numpy docs sagen aus, dass die datetime-API experimentell ist und sich in zukünftigen numpy-Versionen ändern kann.

102
jfs

Sie können einfach den Konstruktor pd.Timestamp verwenden. Das folgende Diagramm kann für diese und verwandte Fragen hilfreich sein. 

Conversions between time representations

157
Quant

Willkommen in der Hölle.

Sie können einfach ein datetime64-Objekt an pandas.Timestamp übergeben:

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

Ich habe festgestellt, dass dies in NumPy 1.6.1 nicht richtig funktioniert:

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

Auch pandas.to_datetime kann verwendet werden (dies ist nicht in der Dev-Version enthalten, v0.9.1 wurde nicht geprüft)

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))
108
Wes McKinney

Ich denke, es könnte eine konsolidiertere Anstrengung in einer Antwort geben, um die Beziehung zwischen Pythons datetime-Modul, datetime64/timedelta64 von numpy und Timestamp/Timedelta-Objekten von Pandas besser zu erklären.

Die datetime-Standardbibliothek von Python

Die Standardbibliothek datetime hat vier Hauptobjekte

  • zeit - nur Zeit, gemessen in Stunden, Minuten, Sekunden und Mikrosekunden
  • datum - nur Jahr, Monat und Tag
  • datetime - Alle Komponenten von Uhrzeit und Datum
  • timedelta - Zeitdauer mit maximaler Einheit von Tagen

Erstellen Sie diese vier Objekte

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

Die datetime64- und timedelta64-Objekte von NumPy

NumPy hat keine separaten Datums- und Uhrzeitobjekte, sondern nur ein einziges datetime64-Objekt, das einen einzelnen Zeitpunkt darstellt. Das datetime-Objekt des datetime-Moduls hat eine Genauigkeit im Mikrosekundenbereich (eine Millionstel Sekunde). Mit dem datetime64-Objekt von NumPy können Sie die Genauigkeit von Stunden bis zu Attosekunden (10 ^ -18) einstellen. Sein Konstruktor ist flexibler und kann eine Vielzahl von Eingaben aufnehmen.

Konstruieren Sie die datetime64- und timedelta64-Objekte von NumPy

Übergeben Sie eine Ganzzahl mit einer Zeichenfolge für die Einheiten. Siehe alle Einheiten hier . Es wird nach der UNIX-Epoche in so viele Einheiten konvertiert: 1. Januar 1970

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

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

Sie können auch Strings verwenden, solange sie im ISO 8601-Format vorliegen.

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

Zeitpläne haben eine einzige Einheit

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

Kann sie auch erstellen, indem zwei datetime64-Objekte subtrahiert werden

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

Pandas Timestamp und Timedelta bieten zusätzlich zu NumPy viel mehr Funktionalität

Ein Pandas-Zeitstempel ist ein Zeitpunkt, der einer Datumszeit sehr ähnlich ist, jedoch mit viel mehr Funktionalität. Sie können sie mit pd.Timestamp oder pd.to_datetime erstellen.

>>> 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 arbeitet sehr ähnlich (mit ein paar weiteren Optionen) und kann eine Liste von Strings in Timestamps konvertieren.

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

Konvertieren von Python-Datetime in datetime64 und 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')

Konvertieren von numpy datetime64 in datetime und 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)

Konvertieren in Zeitstempel

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

Konvertieren Sie den Zeitstempel in Datums- und Datumsangaben64

Dies ist ziemlich einfach, da Pandas Zeitstempel sehr mächtig sind

>>> 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')
59
Ted Petrou
>>> dt64.tolist()
datetime.datetime(2012, 5, 1, 0, 0)

Für DatetimeIndex gibt die tolist eine Liste von datetime-Objekten zurück. Für ein einzelnes datetime64-Objekt wird ein einzelnes datetime-Objekt zurückgegeben.

25
eumiro

Wenn Sie eine ganze Pandaserie von Datumszeiten in reguläre Python-Datumszeiten konvertieren möchten, können Sie auch .to_pydatetime() verwenden.

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

Es unterstützt auch Zeitzonen:

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
fantabolous

Eine Möglichkeit ist, str und dann to_datetime (oder ähnliches) zu verwenden:

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

Hinweis: es ist nicht gleich dt, weil es zu "offset-aware" :

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

Dies scheint unwichtig zu sein.

.

Update: Dies kann mit dem "bösen Beispiel" umgehen:

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)
8
Andy Hayden

Dieser Beitrag ist seit 4 Jahren auf dem Markt und ich habe immer noch Probleme mit diesem Konvertierungsproblem - also ist das Thema 2017 noch in gewissem Sinne aktiv. Ich war etwas geschockt, dass die numpy-Dokumentation keinen einfachen Konvertierungsalgorithmus bietet, aber das ist eine andere Geschichte.

Ich bin auf einen anderen Weg gekommen, die Konvertierung durchzuführen, die nur die Module numpy und datetime umfasst. Es ist nicht erforderlich, dass Pandas importiert werden, was für mich eine Menge Code für eine solche einfache Konvertierung zu sein scheint. Mir ist aufgefallen, dass datetime64.astype(datetime.datetime) ein datetime.datetime-Objekt zurückgibt, wenn sich der ursprüngliche datetime64 in micro-second units befindet, während andere Units einen ganzzahligen Zeitstempel zurückgeben. Ich verwende das Modul xarray für Daten-E/A aus Netcdf-Dateien, das den datetime64 in Nanosekunden-Einheiten verwendet, wodurch die Konvertierung fehlschlägt, sofern Sie nicht zuerst in Mikro-Sekunden-Einheiten konvertieren. Hier ist der Beispiel-Konvertierungscode.

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

Es wurde nur auf meinem Rechner getestet, nämlich Python 3.6 mit einer Anaconda-Distribution von 2017. Ich habe mir nur die skalare Konvertierung angesehen und Array-basierte Konvertierungen nicht überprüft, obwohl ich denke, dass dies gut sein wird. Ich habe mir auch den numpy-Quellcode datetime64 nicht angesehen, um zu sehen, ob die Operation sinnvoll ist oder nicht.

4
ndl303

Ich bin mehrmals auf diese Antwort zurückgekommen, als ich zählen kann, also habe ich beschlossen, eine schnelle kleine Klasse zusammen zu werfen, die einen Numpy datetime64-Wert in einen Python datetime-Wert konvertiert. Ich hoffe es hilft anderen da draußen. 

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)

Ich werde das in meiner Werkzeugtasche aufbewahren. Etwas sagt mir, dass ich es wieder brauchen werde.

1
MikeyE

in der Tat können alle diese Datetime-Typen schwierig und möglicherweise problematisch sein (sie müssen die Zeitzoneninformationen sorgfältig verfolgen). Hier ist, was ich getan habe, obwohl ich zugeben muss, dass zumindest ein Teil davon "nicht beabsichtigt" ist. Dies kann auch etwas kompakter gemacht werden, wenn dies erforderlich ist beginnend mit einer numpy.datetime64 dt_a:

dt_a

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

dt_a1 = dt_a.tolist () # ergibt ein Datumszeitobjekt in UTC, jedoch ohne 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.microsecond], tzinfo = pytz.timezone ('UTC'))

... und das kann natürlich nach Bedarf in eine Zeile komprimiert werden.

0
yoder
import numpy as np
import pandas as pd 

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

verwenden Sie diese Funktion, um das native datetime-Objekt von Pythons abzurufen

0
Crystal

Einige Lösungen funktionieren für mich gut, aber einige Parameter werden von Numpy nicht mehr unterstützt. Die für mich bessere Lösung besteht darin, das Datum als pandas datetime zu lesen und explizit das Jahr, den Monat und den Tag eines pandas object zu extrahieren Code funktioniert für die am häufigsten vorkommende Situation.

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