Search code examples
pythondatetimepython-datetime

What is the best way to handle datetime value overflow


I am attempting to build a program to handle alerts. I want it to be able to handle specific dates like 8/23/2015 7:00 and relative dates like 5 days and 7 hours from now. specific dates are fine but for relative dates if I try and just add 5 days and 7 hours to the date time it can overflow the values intended for that spot

import datetime
dt = datetime.datetime.now()
dayslater = 5
hourslater = 7
minuteslater = 30
alarmTime = datetime.datetime(dt.year, dt.month, dt.day + dayslater,
                              dt.hour + hourslater,
                              dt.minute + minuteslater, 0,0)

this is fine sometimes but if dayslater was 40 days it would overflow the value. I did set up a simple

if hours >= 24: 
    hours -= 24
    days++

however this won't work for overflowing months whose length in days isn't consistent.


Solution

  • Use a datetime.timedelta() object and leave calculations to the datetime library:

    import datetime
    
    delta = datetime.timedelta(days=dayslater, hours=hourslater, minutes=minuteslater)
    alarmTime = datetime.datetime.now() + delta
    

    Demo:

    >>> import datetime
    >>> dt = datetime.datetime.now()
    >>> dayslater = 5
    >>> hourslater = 7
    >>> minuteslater = 30
    >>> delta = datetime.timedelta(days=dayslater, hours=hourslater, minutes=minuteslater)
    >>> delta
    datetime.timedelta(5, 27000)
    >>> dt
    datetime.datetime(2015, 7, 23, 21, 4, 59, 987926)
    >>> dt + delta
    datetime.datetime(2015, 7, 29, 4, 34, 59, 987926)
    

    Note how the hours carried over to the next day (from 21:04 to 04:34), and thus the date went from the 23rd to the 29th. I did not have to worry about 'overflow' here.

    This continues to work at month boundaries, at year boundaries, and in leap years, with February 29th:

    >>> datetime.datetime(2015, 7, 26, 22, 42) + delta
    datetime.datetime(2015, 8, 1, 6, 12)
    >>> datetime.datetime(2015, 12, 26, 22, 42) + delta
    datetime.datetime(2016, 1, 1, 6, 12)
    >>> datetime.datetime(2016, 2, 23, 22, 42) + delta
    datetime.datetime(2016, 2, 29, 6, 12)