Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between time addition using timestamp vs using timedelta?

Tags:

I'm working through Exercism.io gigasecond problem:

"Calculate the moment when someone has lived for 10^9 seconds."

My method was to convert the datetime input to a timestamp, add 10**9, then convert back. My answers are very close, but the test suite (provided by Exercism) fails because the hour arg is off by one. All other args are correct.

After a bit of searching, I found an answer that uses timedelta; the structure of the answer is almost identical to mine, but it generates the full correct answer.

My question is, why is there a difference in the output of these two methods? As you can see below, the problem only manifests when the input arg for hour is the default value of 0.

Code:

def add_gigasecond(birth_date):
    gigadate = birth_date.timestamp() + 10**9
    print(datetime.fromtimestamp(gigadate).__repr__())

    gigadate = birth_date + timedelta(seconds=10**9)
    print(gigadate.__repr__())

Inputs:

tests = [datetime(2011, 4, 25),
         datetime(1977, 6, 13),
         datetime(1959, 7, 19),
         datetime(2015, 1, 24, 22, 0, 0),
         datetime(2015, 1, 24, 23, 59, 59),]

Results:

test 1
datetime.datetime(2043, 1, 1, 0, 46, 40)
datetime.datetime(2043, 1, 1, 1, 46, 40)

test 2
datetime.datetime(2009, 2, 19, 0, 46, 40)
datetime.datetime(2009, 2, 19, 1, 46, 40)

test 3
datetime.datetime(1991, 3, 27, 0, 46, 40)
datetime.datetime(1991, 3, 27, 1, 46, 40)

test 4
datetime.datetime(2046, 10, 2, 23, 46, 40)
datetime.datetime(2046, 10, 2, 23, 46, 40)

test 5
datetime.datetime(2046, 10, 3, 1, 46, 39)
datetime.datetime(2046, 10, 3, 1, 46, 39)

As you can see, the top answer in each test (using timestamps) is off by 1, for all inputs where year, month, date are specified. The correct answer is achieved when the hour, minute, second, and microsecond args are included in the input.

like image 431
skytwosea Avatar asked May 13 '18 21:05

skytwosea


People also ask

How does Timedelta compare to datetime?

You can also find the difference between two datetime objects to get a timedelta object and perform the comparison based on the positive or negative value returned by the timedelta. total_seconds() function. if seconds < 0: print('First date is less than the second date.

What does datetime Timedelta do?

A timedelta object represents a duration, the difference between two dates or times. All arguments are optional and default to 0 . Arguments may be integers or floats, and may be positive or negative. Only days, seconds and microseconds are stored internally.

How can you find the difference in time between two datetime objects time_1 and time_2?

Subtracting the later time from the first time difference = later_time - first_time creates a datetime object that only holds the difference.

What does Timedelta mean?

Timedeltas are differences in times, expressed in difference units, e.g. days, hours, minutes, seconds. They can be both positive and negative. Timedelta is a subclass of datetime.


1 Answers

Daylight Savings

Some detective work can shed light on these problems. For this investigation, I pick the first date in your list, 25-Apr-2011.

from datetime import datetime, timedelta

def add_seconds(birth_date, n):
    x = datetime.fromtimestamp(birth_date.timestamp() + n)
    y = birth_date + timedelta(seconds=n)
    return (x, y)

for i in range(365):
    ts, td = add_seconds(datetime(2011, 4, 25), i*60**2*24)  # add i days via seconds
    if ts-td:  # test for difference in timestamp vs timedelta methods
        print(i, ts, td)
        break

Result:

189 2011-10-30 23:00:00 2011-10-31 00:00:00

As you can see, there is a discrepancy on exactly 30th October. This is, for many countries, the second date in the year where we see a daylight savings adjustment.

Update: A similar question is asked here: Difference between evaluating timestamp and total_seconds. The underlying reason for the difference is that datetime.timedelta does not take into account DST, while timestamp does take this into account.

like image 125
jpp Avatar answered Sep 28 '22 19:09

jpp