390

如何将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)

但是我们如何从( )中提取datetimeor呢?Timestampnumpy.datetime64dt64

.

更新:我的数据集中的一个有点讨厌的例子(也许是激励例子)似乎是:

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

应该是datetime.datetime(2002, 6, 28, 1, 0),而不是长(!)(1025222400000000000L)...

4

14 回答 14

262

您可以只使用 pd.Timestamp 构造函数。下图可能对这个问题和相关问题有用。

时间表示之间的转换

于 2014-02-20T18:17:06.327 回答
175

欢迎来到地狱。

您可以将 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))
于 2012-12-06T22:40:22.060 回答
170

要转换numpy.datetime64datetime表示 UTC 时间的对象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'

上面的例子假设一个天真的datetime对象被解释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.

np.datetime64以与 , 等相同的方式思考np.int8np.int16并应用相同的方法在 Python 对象(例如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是因为 fornumpy.datetime64类型.astype(datetime)等同于.astype(object)返回 Python integer( long) on 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 文档说 datetime API 是实验性的,可能会在未来的 numpy 版本中发生变化。

于 2012-12-04T13:42:08.067 回答
133

我认为在答案中可能会有更综合的努力,以更好地解释 Python 的 datetime 模块、numpy 的 datetime64/timedelta64 和 pandas 的 Timestamp/Timedelta 对象之间的关系。

Python的日期时间标准库

datetime 标准库有四个主要对象

  • time - 只有时间,以小时、分钟、秒和微秒为单位
  • 日期 - 只有年、月和日
  • datetime - 时间和日期的所有组成部分
  • 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 和 timedelta64 对象

NumPy 没有单独的日期和时间对象,只有一个 datetime64 对象来表示单个时间点。datetime 模块的 datetime 对象具有微秒精度(百万分之一秒)。NumPy 的 datetime64 对象允许您将其精度设置为从小时一直到阿秒 (10 ^ -18)。它的构造函数更灵活,可以接受多种输入。

构造 NumPy 的 datetime64 和 timedelta64 对象

为单位传递一个带有字符串的整数。在这里查看所有单位。在 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')

时间增量有一个单位

>>> 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 Timestamp 和 Timedelta 在 NumPy 之上构建了更多功能

pandas Timestamp 是一个与日期时间非常相似但功能更多的时刻。您可以使用pd.Timestamp或构造它们pd.to_datetime

>>> pd.Timestamp(1239.1238934) #defaults 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)

将 Python 日期时间转换为 datetime64 和时间戳

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

将 numpy datetime64 转换为 datetime 和 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)

转换为时间戳

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

从 Timestamp 转换为 datetime 和 datetime64

这很容易,因为 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')
于 2017-10-24T23:36:25.420 回答
35
>>> dt64.tolist()
datetime.datetime(2012, 5, 1, 0, 0)

对于DatetimeIndextolist返回datetime对象列表。对于单个datetime64对象,它返回单个datetime对象。

于 2012-12-04T13:22:10.337 回答
15

如果要将整个 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()整个系列。您将需要.to_pydatetime()使用列表理解或类似的方法调用每个单独的 datetime64:

datetimes = [val.to_pydatetime() for val in df.problem_datetime_column]
于 2014-08-15T09:41:31.853 回答
13

一种选择是使用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因为它已成为“偏移感知”

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)
于 2012-12-04T13:08:29.863 回答
9

这篇文章已经发布了 4 年,我仍然在为这个转换问题而苦苦挣扎——所以从某种意义上说,这个问题在 2017 年仍然很活跃。numpy 文档并没有提供简单的转换算法,这让我感到有些震惊,但那是另一回事了。

我遇到了另一种只涉及模块的转换方法numpydatetime它不需要导入 pandas,在我看来,对于这样一个简单的转换,要导入很多代码。我注意到如果原始以微秒为单位,而其他单位返回整数时间戳,datetime64.astype(datetime.datetime)它将返回一个对象。我使用来自 Netcdf 文件的数据 I/O 模块,它使用以纳秒为单位的单位,除非您首先转换为微秒单位,否则转换失败。这是示例转换代码,datetime.datetimedatetime64xarraydatetime64

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 源代码来查看操作是否有意义。

于 2017-05-30T20:27:39.860 回答
1

我回到这个答案的次数比我能数的要多,所以我决定组合一个快速的小类,它将 Numpydatetime64值转换为 Pythondatetime值。我希望它可以帮助其他人。

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)

我要把这个放在我的工具包里,有东西告诉我我会再次需要它。

于 2017-08-02T06:59:32.067 回答
1

我确实喜欢这个

import pandas as pd

# Custom function to convert Pandas Datetime to Timestamp
def toTimestamp(data):
    return data.timestamp()

# Read a csv file
df = pd.read_csv("friends.csv")

# Replace the "birthdate" column by:
# 1. Transform to datetime
# 2. Apply the custom function to the column just converted
df["birthdate"] = pd.to_datetime(df["birthdate"]).apply(toTimestamp)
于 2021-12-13T11:31:04.320 回答
0
import numpy as np
import pandas as pd 

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

使用此函数获取 python 的本机日期时间对象

于 2016-06-05T16:04:56.750 回答
0

一些解决方案对我来说效果很好,但 numpy 会弃用一些参数。对我来说更好的解决方案是将日期读取为 pandas 日期时间,并明确提取 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)
于 2018-03-22T16:58:16.950 回答
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()])
于 2021-06-25T09:47:17.470 回答
-1

事实上,所有这些日期时间类型都可能很困难,并且可能存在问题(必须仔细跟踪时区信息)。这就是我所做的,尽管我承认我担心它至少有一部分是“不是设计使然”。此外,这可以根据需要变得更紧凑。从 numpy.datetime64 dt_a 开始:

dt_a

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

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

...当然,可以根据需要将其压缩为一行。

于 2015-08-04T18:37:14.723 回答