2015-09-26 61 views
4

如果我想在我的程序中添加100年,为什么会显示错误的日期?在Python中添加年份

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() 
+3

因为几年并不都完全'365'天之久? – jonrsharpe

回答

6

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

要执行期(日历)算法,可以使用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 

要理解,为什么d.replace(year=d.year + 100)失败,考虑:

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

注意2100是不是闰年,而2000是一个闰年。

如果您要添加的唯一单位是一年,那么你可以只使用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 

例子:

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 
6

您不能只添加100 * 365天,因为在该时间段内有366天的闰年。在你的100年里,你失去了25天。

最好只用在这里datetime.replace() method

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

这仍然可能会因2月29日在一个闰年,因为根据的年数,添加你想最终的日期无效。在这种情况下,你可以回到2月28日,或者使用3月31日;处理抛出的异常,并切换到您选择的替换:

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) 

演示:

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

@@@ ##谢谢### –

+1

它打破了[“2000年2月29日”](http://stackoverflow.com/a/32812788/4279) – jfs

+0

@JFSebastian:对,请参阅[如何打印明年从Python中的当年开始](https://stackoverflow.com/a/11206511)来解决这个问题。可以说这是这个职位的一个骗局。 –