Skip to content

Instantly share code, notes, and snippets.

@troolee
Created August 10, 2010 07:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save troolee/516873 to your computer and use it in GitHub Desktop.
Save troolee/516873 to your computer and use it in GitHub Desktop.
Python datetime utils
import calendar
from datetime import datetime, date
def inc_months(d, value, specifying_date=None):
'''
Adds `value` of months to the date `d`. If `specifying_date` is passed, the day of resulting month
will be taken from the `specifying_date` instead of `d`.
>>> inc_months(datetime(2010, 3, 31), 0)
datetime.datetime(2010, 3, 31, 0, 0)
>>> inc_months(datetime(2010, 3, 31), 23)
datetime.datetime(2012, 2, 29, 0, 0)
>>> inc_months(datetime(2010, 2, 28), 1, datetime(2010, 1, 31))
datetime.datetime(2010, 3, 31, 0, 0)
>>> inc_months(datetime(2010, 3, 31), -3)
datetime.datetime(2009, 12, 31, 0, 0)
'''
assert(isinstance(d, (date, datetime)))
assert(isinstance(value, int))
if specifying_date:
assert(isinstance(specifying_date, (date, datetime)))
d0 = d.replace(day=1)
years, months = value / 12, value % 12
if d0.month + months > 12:
years += 1
months = months - 12
d0 = d0.replace(year=d0.year + years, month=d0.month + months)
max_day = calendar.monthrange(d0.year, d0.month)[1]
day = min(max_day, (specifying_date or d).day)
return d0.replace(day=day)
import unittest
import datetime_utils
from datetime import datetime
class Tests(unittest.TestCase):
def test_inc_months(self):
def _(d1, v, d2):
self.assertEqual(datetime_utils.inc_months(datetime(*d1), v), datetime(*d2))
_((2010, 3, 31), 0, (2010, 3, 31))
_((2010, 3, 31), 1, (2010, 4, 30))
_((2010, 3, 31), 2, (2010, 5, 31))
_((2010, 3, 31), 12, (2011, 3, 31))
_((2010, 3, 31), -12, (2009, 3, 31))
_((2010, 2, 28), 12, (2011, 2, 28))
_((2010, 2, 28), -12, (2009, 2, 28))
_((2010, 3, 31), 23, (2012, 2, 29))
_((2010, 3, 31), 35, (2013, 2, 28))
_((2010, 2, 28), 1, (2010, 3, 28))
_((2010, 3, 31), -1, (2010, 2, 28))
_((2010, 3, 31), -2, (2010, 1, 31))
_((2010, 3, 31), -3, (2009, 12, 31))
_((2010, 3, 31), -13, (2009, 2, 28))
_((2010, 3, 31), -25, (2008, 2, 29))
_((2010, 1, 1), -1, (2009, 12, 1))
_((2010, 11, 30), -2, (2010, 9, 30))
_((2010, 12, 31), -3, (2010, 9, 30))
_((2010, 6, 10), -6, (2009, 12, 10))
if __name__ == '__main__':
import doctest
doctest.testmod(datetime_utils)
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment