Coders' Halloween: Tests That Fail One Day Every Four Years
Join the DZone community and get the full member experience.
Join For FreeSome of our tests were constructing expected dates, one year from today, with the following code:
from datetime import datetime now = datetime.utcnow() then = datetime(now.year + 1, now.month, now.day)
Of course if you run this code today, then it tries to construct a datetime for February 29th 2013, which fails because that date doesn't exist.
When I posted this on twitter a few people suggested that instead we should have used timedelta(days=365) instead. Again, this works most of the time - but if you want a date exactly one year from now it will fail in leap years when used before February 29th:
>>> from datetime import datetime, timedelta >>> datetime(2012, 2, 27) + timedelta(days=365) datetime.datetime(2013, 2, 26, 0, 0)
The correct fix is to use the wonderful dateutil module, in particular the dateutil.relativedelta.relativedelta:
>>> from datetime import datetime >>> from dateutil.relativedelta import relativedelta >>> datetime.utcnow() + relativedelta(years=1) datetime.datetime(2013, 2, 28, 15, 20, 21, 546755) >>> datetime(2012, 2, 27) + relativedelta(years=1) datetime.datetime(2013, 2, 27, 0, 0)
And as another hint, always use datetime.utcnow() instead of datetime.now() to avoid horrible timezone nightmares (exactly which timezone are your servers in?).
Source: http://www.voidspace.org.uk/python/weblog/arch_d7_2012_02_25.shtml
Opinions expressed by DZone contributors are their own.
Comments