Adding years in python

匆匆过客 提交于 2019-12-06 23:32:08

问题


If I want to add 100 years in my program, why is it showing the wrong date?

import datetime
stringDate= "January 10, 1920"
dateObject= datetime.datetime.strptime(stringDate, "%B %d, %Y")
endDate= dateObject+datetime.timedelta(days=100*365)
print dateObject.date()
print endDate.date()

回答1:


The number of seconds in a year is not fixed. Think you know how many days are in a year? Think again.

To perform period (calendar) arithmetic, you could use dateutil.relativedelta:

#!/usr/bin/env python
from datetime import date
from dateutil.relativedelta import relativedelta # $ pip install python-dateutil

print(date(1920, 1, 10) + relativedelta(years=+100))
# -> 2020-01-10

To understand, why d.replace(year=d.year + 100) fails, consider:

print(date(2000, 2, 29) + relativedelta(years=+100))
2100-02-28

Notice that 2100 is not a leap year while 2000 is a leap year.

If the only units you want to add is year then you could implement it using only stdlib:

from calendar import isleap

def add_years(d, years):
    new_year = d.year + years
    try:
        return d.replace(year=new_year)
    except ValueError:
        if (d.month == 2 and d.day == 29 and # leap day
            isleap(d.year) and not isleap(new_year)):
            return d.replace(year=new_year, day=28)
        raise

Example:

from datetime import date

print(add_years(date(1920, 1, 10), 100))
# -> 2020-01-10
print(add_years(date(2000, 2, 29), 100))
# -> 2100-02-28
print(add_years(date(2000, 2, 29), 4))
# -> 2004-02-29



回答2:


You can't just add 100 * 365 days, because there are leap years with 366 days in that timespan. Over your 100 year span you are missing 25 days.

Better to just use the datetime.replace() method here:

endDate = dateObject.replace(year=dateObject.year + 100)

This can still fail for February 29th in a leap year, as depending on the number of years you add you'd end up with an invalid date. You could move back to February 28th in that case, or use March 31st; handle the exception thrown and switch to your chosen replacement:

years = 100
try:
    endDate = dateObject.replace(year=dateObject.year + years)
except ValueError::
    # Leap day in a leap year, move date to February 28th
    endDate = dateObject.replace(year=dateObject.year + years, day=28)

Demo:

>>> import datetime
>>> dateObject = datetime.datetime(1920, 1, 10, 0, 0)
>>> dateObject.replace(year=dateObject.year + 100)
datetime.datetime(2020, 1, 10, 0, 0)



回答3:


man 3 mktime

Anyone who ever did C knows the answer.

mktime automatically adds overflowing values to the next bigger unit. You just need to convert it back to a datetime.

For example you can feed it with 2019-07-40, which converts to 2019-08-09.

>>> datetime.fromtimestamp(mktime((2019, 7, 40, 0, 0, 0, 0, 0, 0)))
datetime.datetime(2019, 8, 9, 0, 0)

Or 2019-03-(-1) is converted to 2019-02-27:

>>> datetime.fromtimestamp(mktime((2019, 3, -1, 0, 0, 0, 0, 0, 0)))
datetime.datetime(2019, 2, 27, 0, 0)

So you just take your old date and add whatever you like:

now = datetime.datetime.now()
hundred_days_later = datetime.datetime.fromtimestamp(mktime((now.year, now.month, now.day + 100, now.hour, now.minute, now.second, 0, 0, 0)))


来源:https://stackoverflow.com/questions/32799428/adding-years-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!