Conversion entre datetime, Timestamp et datetime64
comment convertir un objet numpy.datetime64
en un objet datetime.datetime
(ou Timestamp
)?
dans le code suivant, je crée des objets 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')
Note: il est facile d'obtenir le datetime à partir de L'horodatage:
In [10]: ts.to_datetime()
Out[10]: datetime.datetime(2012, 5, 1, 0, 0)
mais comment extraire le datetime
ou Timestamp
d'un numpy.datetime64
( dt64
)?
.
mise à Jour: un peu méchant exemple dans ma base de données (peut-être la motivation exemple) 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
)...
12 réponses
pour convertir numpy.datetime64
en objet datetime qui représente le temps en TUC 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 objet datetime naïf est interprété par np.datetime64
comme du temps en TUC.
pour convertir datetime en 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.objet datetime64 et un tableau numpy de np.datetime64.
pensez à np.datetime64 de la même façon que vous le feriez pour np.int8, np.int16, etc. et appliquent les mêmes méthodes pour convertir des objets Python comme int, datetime et les objets numpy correspondants.
votre "mauvais 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 la valeur long
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'
retourne long
parce que pour numpy.datetime64
type .astype(datetime)
est équivalent à .astype(object)
qui renvoie Python entier ( long
) sur numpy-1.8
.
pour obtenir l'objet datetime vous pouvez:
>>> 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 les secondes directement:
>>> 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)
le num PY docs disent que l'API datetime est expérimentale et peut changer en futures versions de numpy.
vous pouvez utiliser la police.Constructeur de Timestamp. Le diagramme ci-dessous peut être utile pour répondre à cette question et à d'autres questions connexes.
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 bien même dans NumPy 1.6.1:
numpy.datetime64('2012-05-01T01:00:00.000000+0100')
aussi, pandas.to_datetime
peut être utilisé (ceci est hors de la version dev, n'ont pas coché 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))
je pense qu'il pourrait y avoir un effort plus consolidé dans une réponse pour mieux expliquer la relation entre le module datetime de Python, les objets datetime64/timedelta64 de num Python et les objets Timestamp/Timedelta de pandas.
datetime bibliothèque standard de Python
datetime de la bibliothèque standard a quatre principaux objets
- temps - seul le temps, mesuré en heures, minutes, secondes et microsecondes
- date-only année, mois et jour
- datetime - Tous les composants de l'heure et de la date
- timedelta - Un montant de temps le maximum de l'unité de jours
la création de ces quatre objets
>>> 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 est datetime64 et timedelta64 objets
NumPy n'a pas d'objets date et time séparés, juste un seul objet datetime64 pour représenter un seul moment dans le temps. L'objet datetime du module datetime a une précision de microseconde (un millionième de seconde). L'objet datetime64 de num PY vous permet de régler sa précision des heures jusqu'aux attosecondes (10 ^ -18). Son constructeur est plus flexible et peut prendre une variété d'entrées.
Construire NumPy est datetime64 et timedelta64 objets
passe un entier avec une chaîne pour les unités. voir toutes les unités ici . Il est converti que de nombreuses unités après L'époque UNIX: 1er janvier 1970
>>> np.datetime64(5, 'ns')
numpy.datetime64('1970-01-01T00:00:00.000000005')
>>> np.datetime64(1508887504, 's')
numpy.datetime64('2017-10-24T23:25:04')
vous pouvez également utiliser des chaînes aussi longtemps qu'elles sont au format ISO 8601.
>>> np.datetime64('2017-10-24')
numpy.datetime64('2017-10-24')
Timedeltas ont une seule unité
>>> np.timedelta64(5, 'D') # 5 days
>>> np.timedelta64(10, 'h') 10 hours
peut aussi les créer en soustrayant deux objets datetime64
>>> np.datetime64('2017-10-24T05:30:45.67') - np.datetime64('2017-10-22T12:35:40.123')
numpy.timedelta64(147305547,'ms')
Pandas Timestamp et Timedelta construire beaucoup plus de fonctionnalités sur le dessus de NumPy
Une pandas Timestamp est un moment très similaire à un datetime, mais avec beaucoup plus de fonctionnalités. Vous pouvez les construire avec pd.Timestamp
ou 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
fonctionne de manière très similaire (avec quelques options supplémentaires) et peut convertir une liste de chaînes en horodateurs.
>>> 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)
conversion de Python datetime en datetime64 et 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')
la Conversion de numpy datetime64 à DateTime et horodatage
>>> 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)
Convertir un Timestamp
>>> pd.Timestamp(dt64)
Timestamp('2017-10-24 05:34:20.123456')
Convertir à partir d'Horodatage date / heure et datetime64
c'est assez facile car les pointeurs de pandas sont très puissants
>>> 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)
Pour DatetimeIndex
, le tolist
renvoie une liste de datetime
des objets. Pour un seul objet datetime64
, il renvoie un seul objet datetime
.
si vous voulez convertir une série entière de pandas en Python, vous pouvez aussi utiliser .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)
....
il supporte aussi timezones:
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>)
....
une option est d'utiliser str
, puis 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: il n'est pas égal à dt
parce qu'il est devenu "le décalage de courant" :
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 peut traiter du "mauvais 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)
ce poste est en place depuis 4 ans et j'ai encore lutté avec ce problème de conversion - donc la question est toujours active en 2017 dans un certain sens. J'ai été quelque peu choqué que la documentation de numpy n'offre pas facilement un algorithme de conversion simple, mais c'est une autre histoire.
j'ai rencontré une autre façon de faire la conversion qui ne concerne que les modules numpy
et datetime
, il ne nécessite pas pandas à importer qui me semble être beaucoup de code à importer pour une conversion aussi simple. J'ai remarqué que datetime64.astype(datetime.datetime)
retournera un datetime.datetime
objet si l'original datetime64
est dans micro-unités de seconde tandis que d'autres unités renvoient un timestamp entier. J'utilise le module xarray
pour les données e/s des fichiers Netcdf qui utilise le datetime64
en unités nanosecondes faisant échouer la conversion sauf si vous convertissez d'abord en unités micro-secondes. Voici l'exemple de code de conversion,
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
est le seul testé sur ma machine, qui est Python 3.6 avec une récente distribution anaconda 2017. J'ai seulement regardé la conversion scalaire et n'ai pas vérifié les conversions basées sur les tableaux bien que je devine qu'il sera bon. Je n'ai pas non plus regardé le code source de numpy datetime64 pour voir si l'opération avait un sens ou non.
je suis revenu à cette réponse plus de fois que je ne peux compter, donc j'ai décidé de jeter ensemble une petite classe rapide, qui convertit une valeur" Numpy datetime64
à la valeur "Python datetime
. J'espère que cela aidera d'autres.
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)
je vais garder ça dans mon sac à outils, quelque chose me dit que j'en aurai encore besoin.
en effet, tous ces types de datetime peuvent être difficiles, et potentiellement problématiques (doit garder une trace attentive des informations de fuseau horaire). voici ce que j'ai fait, même si je reconnais que je suis préoccupé qu'au moins une partie de celui-ci est "pas par la conception". en outre, cela peut être fait un peu plus compact que nécessaire. en commençant par un numpy.datetime64 dt_a:
dt_a
numpy.datetime64 ('2015-04-24T23:11:26.270000-0700')
dt_a1 = dt_a.tolist () # fournit un objet datetime dans UTC, mais sans tzinfo
dt_a1
datetime.datetime(2015, 4, 25, 6, 11, 26, 270000)
# now, make your "aware" datetime:
dt_a2=datetime.datetime(*liste(dt_a1.timetuple()[:6]) + [dt_a1.microseconde], tzinfo=pytz.le fuseau horaire('UTC'))
... et bien sûr, cela peut être compressé en un seul ligne si nécessaire.
import numpy as np
import pandas as pd
def np64toDate(np64):
return pd.to_datetime(str(np64)).replace(tzinfo=None).to_datetime()
utilisez cette fonction pour obtenir l'objet datetime natif de pythons
Certaines solutions fonctionnent bien pour moi, mais numpy va déprécier certains paramètres.
La solution qui fonctionne mieux pour moi est de lire la date comme une datetime pandas et d'exclure explicitement l'année, le mois et le jour d'un objet pandas.
Le code suivant fonctionne pour la situation la plus courante.
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)