如何将numpy.datetime64
对象转换为datetime.datetime
(或Timestamp
)?
在以下代码中,我创建了一个datetime,timestamp和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')
注意:从时间戳中获取日期时间很容易:
In [10]: ts.to_datetime()
Out[10]: datetime.datetime(2012, 5, 1, 0, 0)
但我们如何从datetime
(Timestamp
)中提取numpy.datetime64
或dt64
?
更新:我的数据集中的一个有点讨厌的例子(也许是激励性的例子)似乎是:
dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')
应为datetime.datetime(2002, 6, 28, 1, 0)
,而不是长(!)(1025222400000000000L
)......
答案 0 :(得分:168)
您可以使用pd.Timestamp构造函数。以下图表可能对此问题和相关问题有用。
答案 1 :(得分:111)
欢迎来到地狱。
您只需将datetime64对象传递给pandas.Timestamp
:
In [16]: Timestamp(numpy.datetime64('2012-05-01T01:00:00.000000'))
Out[16]: <Timestamp: 2012-05-01 01:00:00>
我注意到这在NumPy 1.6.1中不起作用:
numpy.datetime64('2012-05-01T01:00:00.000000+0100')
此外,pandas.to_datetime
可以使用(这是开发版本,未检查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))
答案 2 :(得分:108)
将numpy.datetime64
转换为表示numpy-1.8
上UTC时间的日期时间对象:
>>> 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'
上面的例子假设一个天真的日期时间对象被np.datetime64
解释为UTC时间。
要将datetime转换为np.datetime64并返回(numpy-1.6
):
>>> np.datetime64(datetime.utcnow()).astype(datetime)
datetime.datetime(2012, 12, 4, 13, 34, 52, 827542)
它适用于单个np.datetime64对象和np.datetime64的numpy数组。
考虑np.datetime64的方式与np.int8,np.int16等相同,并应用相同的方法来转换Python对象之间的beet,例如int,datetime和相应的numpy对象。
你的“讨厌的例子”正常工作:
>>> 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
我可以在long
上重现安装为numpy-1.8.0
的值:
pip install git+https://github.com/numpy/numpy.git#egg=numpy-dev
同样的例子:
>>> 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'
返回long
,因为numpy.datetime64
类型.astype(datetime)
等同于.astype(object)
,它返回long
上的Python整数(numpy-1.8
)。
要获取datetime对象,您可以:
>>> 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)
获取直接使用秒的datetime64:
>>> 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)
numpy docs表示日期时间API是实验性的,可能会在未来的numpy版本中发生变化。
答案 3 :(得分:64)
我认为,为了更好地解释Python的日期时间模块,numpy的datetime64 / timedelta64和pandas&#39;之间的关系,可能会有更多的综合努力。时间戳/ Timedelta对象。
日期时间标准库有四个主要对象
>>> 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没有单独的日期和时间对象,只有一个datetime64对象来表示单个时刻。 datetime模块的datetime对象具有微秒精度(百万分之一秒)。 NumPy的datetime64对象允许您将其精度从小时数一直设置为阿秒(10 ^ -18)。它的构造函数更灵活,可以进行各种输入。
传递一个带字符串的整数。 See all units here。它在UNIX时代之后被转换为许多单位:1970年1月1日
>>> np.datetime64(5, 'ns')
numpy.datetime64('1970-01-01T00:00:00.000000005')
>>> np.datetime64(1508887504, 's')
numpy.datetime64('2017-10-24T23:25:04')
您也可以使用字符串,只要它们是ISO 8601格式。
>>> np.datetime64('2017-10-24')
numpy.datetime64('2017-10-24')
Timedeltas只有一个单位
>>> np.timedelta64(5, 'D') # 5 days
>>> np.timedelta64(10, 'h') 10 hours
也可以通过减去两个datetime64对象来创建它们
>>> np.datetime64('2017-10-24T05:30:45.67') - np.datetime64('2017-10-22T12:35:40.123')
numpy.timedelta64(147305547,'ms')
pandas时间戳是一个非常类似于日期时间但具有更多功能的时刻。您可以使用pd.Timestamp
或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
的工作方式非常相似(还有一些选项),可以将字符串列表转换为时间戳。
>>> 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)
>>> 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')
>>> 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)
转换为时间戳
>>> pd.Timestamp(dt64)
Timestamp('2017-10-24 05:34:20.123456')
这很容易,因为pandas时间戳非常强大
>>> 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')
答案 4 :(得分:27)
>>> dt64.tolist()
datetime.datetime(2012, 5, 1, 0, 0)
对于DatetimeIndex
,tolist
会返回datetime
个对象的列表。对于单个datetime64
对象,它返回单个datetime
对象。
答案 5 :(得分:10)
如果您想将整个pandas系列日期时间转换为常规python日期时间,您还可以使用.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)
....
它还支持时区:
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>)
....
注意:如果您在Pandas系列上操作,则无法在整个系列中调用to_pydatetime()
。您需要使用列表推导或类似的东西在每个datetime64上调用.to_pydatetime()
:
datetimes = [val.to_pydatetime() for val in df.problem_datetime_column]
答案 6 :(得分:8)
一种选择是使用str
,然后使用to_datetime
(或类似):
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))
注意:它不等于dt
,因为它变为"offset-aware":
In [13]: pd.to_datetime(str(dt64)).replace(tzinfo=None)
Out[13]: datetime.datetime(2012, 5, 1, 1, 0)
这似乎不够优雅。
更新:这可以处理“讨厌的例子”:
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 :(得分:4)
此帖已经持续了4年,我仍然在努力解决这个转换问题 - 所以从某种意义上说,问题仍然存在于2017年。我有点震惊的是,numpy文档并不能轻易提供简单的转换算法,但这是另一个故事。
我遇到了另一种只涉及模块numpy
和datetime
的转换方式,它不需要导入pandas,这似乎是我要导入的大量代码这么简单的转换。我注意到,如果原始datetime64.astype(datetime.datetime)
处于微秒单位,datetime.datetime
将返回datetime64
个对象,而其他单位则返回整数时间戳。我使用模块xarray
来处理来自Netcdf文件的数据I / O,这些文件以纳秒为单位使用datetime64
,这使得转换失败,除非您首先转换为微秒单位。以下是示例转换代码
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
它仅在我的机器上进行了测试,这是Python 3.6,最近有2017款Anaconda发行版。我只看了标量转换,并没有检查基于数组的转换,虽然我猜它会很好。我也没有查看numpy datetime64源代码,看看操作是否有意义。
答案 8 :(得分:1)
我回到这个答案的次数比我可以计算的多,所以我决定将一个快速的小类放在一起,将Numpy datetime64
值转换为Python datetime
值。我希望它可以帮助其他人。
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)
我要把它放在我的工具包里,有些东西告诉我,我会再次需要它。
答案 9 :(得分:0)
dt_a
numpy.datetime64(&#39; 2015-04-24T23:11:26.270000-0700&#39)
dt_a1 = dt_a.tolist()#以UTC格式生成日期时间对象,但没有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(&#39; UTC&#39;))
......当然,可以根据需要将其压缩成一行。
答案 10 :(得分:0)
import numpy as np
import pandas as pd
def np64toDate(np64):
return pd.to_datetime(str(np64)).replace(tzinfo=None).to_datetime()
使用此函数获取pythons本地日期时间对象
答案 11 :(得分:0)
有些解决方案适合我,但numpy会弃用某些参数。
对我来说更好的解决方案是将日期作为熊猫日期时间读取,并明确地删除pandas对象的年,月和日。
以下代码适用于最常见的情况。
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)
答案 12 :(得分:0)
我设法将包含时间信息的 Pandas 数据框中的“日期”列转换为 numpy 数组的唯一方法如下:(数据框是从 csv 文件“csvIn.csv”中读取的)
import pandas as pd
import numpy as np
df = pd.read_csv("csvIn.csv")
df["date"] = pd.to_datetime(df["date"])
timestamps = np.array([np.datetime64(value) for dummy, value in df["date"].items()])