How can I fuzzy add a year to a date in numpy?
numpy, python
Solution
This simply will not work, at least not with numpy alone.
Days, hours, minutes, seconds can all be converted because they have compatible base units. There is always 60 seconds in a minute, always 60 minutes in an hour, always 24 hours in a day.
Years and Months are treated specially, because how much time they represent changes depending on when they are used. While a timedelta day unit is equivalent to 24 hours, there is no way to convert a month unit into days, because different months have different numbers of days. By extension, there is no way to convert years into days either.
In order to implement this appropriately, you will need to decide how to resolve conflicts such as leap years. This is not something that can be done with numpy alone. The way arithmetic works with `numpy.datetime64` objects is different from other libraries and, as mentioned in the documents, is not possible to convert between days and months.
Ordinary `datetime` and `relativedelta`s would work, because these libraries have codified the behavior on such conflicts.
from dateutil.relativedelta import relativedelta
from datetime import datetime
datetime(2016, 2, 29) + relativedelta(years=1)
#datetime.datetime(2017, 2, 28, 0, 0)
So, if you like how these datetime libraries sort it out... Something like this would get you the result...
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
Example:
fuzzy_add(np.datetime64("2016-02-29"), 1)
#numpy.datetime64('2017-02-28')
Problem
I understand why you can't add a year/month `timedelta64` to a day, since the month or years may have different number of days. But I expected adding a year to a date to work because all the information necessary is available. Alas I am saddened: ``` 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 ``` How do I make it work? Edit: The answer to the duplicate question is unsuitable. I'm looking to do it as best as I can, ignoring the corner cases. I'm trying to get nice date ticks, so being inexact is fine. Something like downcast datetime64[D] to datetime64[M] if I need to.