358 votes

Conversion entre datetime, Timestamp et datetime64

Comment convertir un numpy.datetime64 à un objet datetime.datetime (ou Timestamp ) ?

Dans le code suivant, je crée un objet datetime, timestamp et 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')

Remarque : il est facile d'obtenir la date à partir du timestamp :

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

Mais comment extraire le datetime o Timestamp d'un numpy.datetime64 ( dt64 ) ?

.

Mise à jour : un exemple quelque peu désagréable dans mon ensemble de données (peut-être l'exemple motivant) semble être :

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

qui devrait être datetime.datetime(2002, 6, 28, 1, 0) et pas un long ( !) ( 1025222400000000000L )...

3 votes

Vous devriez probablement accepter La réponse de @Wes McKinney qui est beaucoup plus court et qui devrait fonctionner sur des numpy , pandas versions.

0 votes

@J.F.Sebastian Hmmm, cela signifie-t-il que la réponse est "ne pas passer de np.datetime à datetime"... utiliser simplement pd.Timestamp (car c'est une sous-classe de datetime de toute façon), ou si vous devez vraiment utiliser pd.Timestamp(dt64).to_datetime() . Je suis toujours un peu insatisfait à ce sujet, mais il est certain que celle de Wes est moins spécifique à mon ancien problème (et donc meilleure pour le monde) ! Merci encore d'avoir pris le temps d'y répondre :)

0 votes

Votre question dit "ou Timestamp " y Timestamp est un datetime (une sous-classe de) de toute façon :)

239voto

Quant Points 343

Vous pouvez simplement utiliser le constructeur pd.Timestamp. Le diagramme suivant peut être utile pour cette question et d'autres questions connexes.

Conversions between time representations

176 votes

Le simple fait de regarder ce diagramme me dit qu'il y a quelque chose de fondamentalement faux avec tous ces trucs de temps.

5 votes

Il est très déroutant que pd.to_datetime produise un TimeStamp si on lui donne le nombre de ms ou ns, mais produise un datetime.datetime si on lui donne un datetime.datetime ou un np.datetime64 si on lui donne un np.datetime64... Pourquoi quelqu'un penserait-il que c'est raisonnable ?

0 votes

Pour ceux qui ne font que passer : pd.Timestamp() change np.datetime en pd.Timestamp

166voto

Wes McKinney Points 17545

Bienvenue en enfer.

Vous pouvez simplement passer un objet datetime64 à pandas.Timestamp :

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

J'ai remarqué que cela ne fonctionne pas correctement dans NumPy 1.6.1 :

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

Aussi, pandas.to_datetime peut être utilisé (ceci est tiré de la version dev, je n'ai pas vérifié la 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))

5 votes

Vous devriez mentionner que issubclass(pd.Timestamp, datetime) es True . Et Timestamp La classe elle-même a to_datetime() méthode.

9 votes

pd.to_datetime('2012-05-01T01:00:00.000000+0100') renvoie à Timestamp('2012-05-01 00:00:00') au moins chez les pandas 0.17.1 .

162voto

J.F. Sebastian Points 102961

Pour convertir numpy.datetime64 à datetime qui représente le temps en UTC sur 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'

L'exemple ci-dessus suppose qu'un naïf datetime est interprété par np.datetime64 comme temps en UTC.


Pour convertir datetime à np.datetime64 et retour ( numpy-1.6 ) :

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

Il fonctionne à la fois sur un seul np.datetime64 et un tableau numpy de np.datetime64 .

Pensez à np.datetime64 de la même manière que vous le feriez pour np.int8 , np.int16 etc. et appliquer les mêmes méthodes pour convertir les objets Python tels que int , datetime et les objets numpy correspondants.

Votre "méchant exemple" fonctionne correctement :

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

Je peux reproduire le long valeur sur numpy-1.8.0 installé comme :

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

Le même exemple :

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

Il retourne long car pour numpy.datetime64 type .astype(datetime) est équivalent à .astype(object) qui renvoie un entier Python ( long ) sur numpy-1.8 .

Pour obtenir datetime objet que vous pourriez :

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

Pour obtenir datetime64 qui utilise directement les secondes :

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

El documentation sur numpy dire que l'API datetime est expérimentale et peut changer dans les futures versions de numpy.

2 votes

J'ai bien peur que cela ne fonctionne pas toujours : par exemple. dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100') ce qui donne une longue ( 1025222400000000000L ) ( !)

0 votes

@hayden : essai type(dt64) . dt64.astype(datetime) == datetime.utcfromtimestamp(dt64.astype(int)*1e-6)

0 votes

@JFSebastian type(dt64) es numpy.datetime64 y dt64.astype(datetime) est le même long int... :s

34voto

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

Pour DatetimeIndex le tolist renvoie une liste de datetime objets. Pour un seul datetime64 il renvoie un seul datetime objet.

5 votes

@hayden si vous savez que c'est un tableau scalaire/0-d je préfère utiliser .item() qui est beaucoup plus explicite (et personne ne peut venir et commencer à argumenter qu'il devrait retourner une liste).

2 votes

J'ai bien peur que cela ne fonctionne pas toujours : par exemple. dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100') ce qui donne une longue ( 1025222400000000000L ) ( !)

5 votes

@hayden : le type qui est retourné par .item() (suggéré par @seberg), .tolist() dépend des unités utilisées par datetime64, par exemple, D produit datetime.date() , us (microsecondes) produisent datetime.datetime() , ns (nanosecondes) produisent long . Et les unités changent en fonction des valeurs d'entrée, par exemple, numpy.datetime64('2012-05-01') utilise 'D' , numpy.datetime64('2012-05-01T00:00:00.000') utilise ms , numpy.datetime64('2012-05-01T00:00:00.000000000') utilise ns . Vous pourriez ouvrir un dossier si vous le trouvez confus.

10voto

Andy Hayden Points 38010

Une option consiste à utiliser str y luego to_datetime (ou similaire) :

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

Remarque : elle n'est pas égale à dt parce que c'est devenu " offset-aware " :

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

Cela semble inélégant.

.

Mise à jour : cela permet de traiter le "méchant exemple" :

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)

0 votes

Merci Andy d'avoir partagé cette astuce. Pour une raison quelconque, je ne parviens pas à la faire fonctionner, comme je l'explique ici : stackoverflow.com/questions/22825349/

0 votes

@user815423426 cela n'a jamais été une solution très robuste, je suppose que vous pouvez passer un format au constructeur datetime pour travailler plus généralement. Pas très pandastique cependant !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X