Python 使用timedelta向datetime64添加一个月
当我尝试这个:Python 使用timedelta向datetime64添加一个月,python,pandas,numpy,timedelta,Python,Pandas,Numpy,Timedelta,当我尝试这个: >>> a = numpy.datetime64('1995-12-31') >>> b = a + pandas.Timedelta(1, unit='M') >>> print(b) 我希望看到 1996-01-31 但是我得到了 1996-01-30 10:29:06. 知道为什么吗?非常感谢 一个月的时间差是一年的长度除以12 您需要检查日期并添加适当的天数。 或者,增加月数(如果需要,滚动到下一年),并保持日数
>>> a = numpy.datetime64('1995-12-31')
>>> b = a + pandas.Timedelta(1, unit='M')
>>> print(b)
我希望看到
1996-01-31
但是我得到了
1996-01-30 10:29:06.
知道为什么吗?非常感谢 一个月的时间差是一年的长度除以12 您需要检查日期并添加适当的天数。
或者,增加月数(如果需要,滚动到下一年),并保持日数不变。您可以替换
日
部分以模拟要求
import numpy as np
import pandas as pd
a = np.datetime64('1995-12-31')
b = a + pd.Timedelta(1, unit='M')
print(b.replace(day=pd.to_datetime(a).day))
如果您只对日期部分感兴趣,请使用
.date()
将“月”添加到时间中存在固有的模糊性,因为月的长度不同
确定日期:
In [247]: a = np.array('1995-12-31','datetime64[D]')
In [248]: a
Out[248]: array('1995-12-31', dtype='datetime64[D]')
再加上几天就行了:
In [249]: a + np.array(31, 'timedelta64[D]')
Out[249]: numpy.datetime64('1996-01-31')
添加月份会引发错误:
In [250]: a + np.array(1, 'timedelta64[M]')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-250-a331f724d7e7> in <module>
----> 1 a + np.array(1, 'timedelta64[M]')
TypeError: Cannot get a common metadata divisor for NumPy datetime metadata [D] and [M] because they have incompatible nonlinear base time units
在相应的datetime
对象中更改月份可能是处理此问题最干净的方法:
In [254]: b = a.item()
In [255]: b
Out[255]: datetime.date(1995, 12, 31)
我对
datetime
对象的处理不够,无法在不查看其文档的情况下进行更改。如果可能,添加一个月而不更改日期的简明方法是将月份截断,添加1,然后读取截断的内容:
>>> a = np.datetime64('1995-12-31')
>>> am = a.astype('M8[M]')
>>> b = (am + 1) + (a - am)
>>> b
numpy.datetime64('1996-01-31')
显然,如果下个月不存在原始日期,则这不起作用:
>>> a = np.datetime64('1995-01-31')
>>> am = a.astype('M8[M]')
>>> b = (am + 1) + (a - am)
>>> b
numpy.datetime64('1995-03-03')
但无论如何,在这种情况下,答案应该是什么还不清楚
一种可能是在该月的最后一天达到最大值:
>>> b = np.minimum((am + 1) + (a - am), (am + 2) - np.timedelta64(1, 'D'))
>>> b
numpy.datetime64('1995-02-28')
正如@hpaulj在他的回答中已经提到的:
在时间中添加“月”是一种固有的模糊性,因为月的长度不同 此外,在版本
0.25.0
,用于Timedelta
功能中的单位M
(月)和Y
(年)
但正如官方手册中所述,您应该使用时间增量表示绝对时间持续时间,使用日期偏移量表示日历算法方面的相对时间持续时间,这正是我们在您的情况下需要的:
基本的日期偏移量的作用类似于dateutil.relativedelta
(),它将日期时间移动指定的相应日历持续时间
因此,以你的例子:
In [7]: a = numpy.datetime64('1995-12-31')
: b = pandas.Timestamp(a) + pandas.DateOffset(months=1)
: b
Out[7]: Timestamp('1996-01-31 00:00:00')
注:如果您需要将熊猫时间戳转换为数,您可以使用转换为数的方法。datetime64
“一个月的时间增量是一年的长度除以12。”这似乎是熊猫的思维方式(但不是numpy
)。
In [7]: a = numpy.datetime64('1995-12-31')
: b = pandas.Timestamp(a) + pandas.DateOffset(months=1)
: b
Out[7]: Timestamp('1996-01-31 00:00:00')