Python 如何在numpy中模糊地为日期添加一年?

Python 如何在numpy中模糊地为日期添加一年?,python,numpy,Python,Numpy,我理解为什么不能在一天中添加年/月timedelta64,因为一个月或几年可能有不同的天数。但我希望在工作日期的基础上再加上一年,因为所有必要的信息都是可用的。唉,我很难过: import numpy as np print(np.datetime64("2015-06-01") + np.timedelta64(1, "Y")) # TypeError: Cannot get a common metadata divisor for NumPy datetime metadata [D]

我理解为什么不能在一天中添加年/月
timedelta64
,因为一个月或几年可能有不同的天数。但我希望在工作日期的基础上再加上一年,因为所有必要的信息都是可用的。唉,我很难过:

import numpy as np

print(np.datetime64("2015-06-01") + np.timedelta64(1, "Y"))

# TypeError: Cannot get a common metadata divisor for NumPy datetime metadata [D] and [Y] because they have incompatible nonlinear base time units
我如何让它工作

编辑:

重复问题的答案不合适。我希望尽我所能做到最好,不去理会角落里的案子。我在试着得到好的日期标记,所以不精确是可以的


如果需要的话,可以将datetime64[D]向下转换为datetime64[M]。

这根本不起作用,至少单用numpy是不行的

天、小时、分钟、秒都可以转换,因为它们有兼容的基本单位。一分钟总有60秒,一小时总有60分钟,一天总有24小时

年和月是特殊处理的,因为它们代表的时间取决于它们的使用时间。虽然timedelta日单位相当于24小时,但无法将月份单位转换为天,因为不同的月份有不同的天数。推而广之,也没有办法将年转换为天

为了适当地实现这一点,您需要决定如何解决诸如闰年之类的冲突。这不是单凭numpy就能做到的。算术处理
numpy.datetime64
对象的方式与其他库不同,不可能在天和月之间进行转换

普通的
datetime
relativedelta
s可以工作,因为这些库已经对此类冲突的行为进行了编码

from dateutil.relativedelta import relativedelta
from datetime import datetime
datetime(2016, 2, 29) + relativedelta(years=1)
#datetime.datetime(2017, 2, 28, 0, 0)
所以,如果你喜欢这些datetime库的分类方式。。。像这样的事情会让你得到结果

from datetime import datetime
from dateutil.relativedelta import relativedelta
import numpy as np
def fuzzy_add(npdt, years):
    year, month, day = str(npdt).split("-")
    d = datetime(int(year), int(month), int(day))
    delta = relativedelta(years=years)
    the_date = d + delta
    new_npdt = np.datetime64(the_date.isoformat()[:10])
    return new_npdt
例如:

fuzzy_add(np.datetime64("2016-02-29"), 1)
#numpy.datetime64('2017-02-28')

也许最简单的解决方案是使用字符串操作

import numpy as np

def add_years(date, n_years):
    y, m, d = str(date).split("-")
    return np.datetime64("{}-{}-{}".format(int(y)+n_years, m, d))

my_date = np.datetime64("2015-06-01")
new_date = add_years(my_date, n_years=1)
print new_date

可能是重复的,为什么您希望它工作?年不是一个固定的时间量。如果你试图在2004年2月29日增加一年,会发生什么?可能是@user2357112的重复,我希望这会起作用,因为日期是人类的概念,我们可以连贯地谈论“从今天开始的一年”,即使是在2月29日。你认为29日出生的人年龄增长率和其他人不一样吗?时间的抽象概念可以用代码表示;我们必须非常小心边缘案例的处理方式。这就是日期时间图书馆的用途。是的,但我如何让它工作呢?我在文档中找不到一种方法来区分从几天到几个月的沮丧情绪。@csiz我的观点是,这是不可能的。如果你想使一年中的天数保持不变,你可以做
np.datetime64(“2015-06-01”)+np.timedelta64(366,“D”)
,但这可能不会给你带来任何令人满意或一致的结果,因为月份和年份中的天数问题。但这是可能的。如果我说从2015-06-01开始的一年,其他人通常会理解2016-06-01,即使这是闰年。我试图在一年后复制人们所理解的东西。(我接近一个解决方案)。如果一年中存在的日期在另一年中不存在,会发生什么?行为应该是什么?如果您定义了如何解决这些类型的冲突,您可能可以通过这种方式找到解决方案,但不能仅使用
datetime64
timedelta64
对象。从本质上讲,TimeDelta不能同时在月和日两个方面工作。
np.datetime64
对象对时间增量进行算术运算的方式是不可能的。如图所示,
(2016-2-29)
是有效的日期时间,但
(2017-2-29)
不是。这应该是
(2017-2-28)
还是
(2017-3-1)
?这就是造成这种情况的模糊性问题impossible@sytech你是说一个人不能接受像
2015-06-01
这样的日期,并将一年后的日期概念化为
2016-06-01
?这显然是错误的,日期-时间库的存在使这种操作成为可能。例如,Java的类使这个问题变得很简单:
LocalDate.of(2015,6,1)。plusYears(1)
。使用
d=np.datetime64(“2016-02-29”)
然后
nd=add_years(d,n_years=1)
会导致
ValueError:Day超出日期时间字符串“2017-02-29”的范围
如果使用字符串方法生成一个表示相同开始日期的普通
datetime
对象,然后将其添加到
relativedelta
对象,然后基于生成的
datetime
对象创建一个新的
numpy.datetime64
对象,则此方法可能有效。但是这样做的开销可能会破坏使用numpy的初衷。