4

I think I'm misunderstanding something regarding datetime timestamps. The descriptions I've read seem to say that a timestamp represents the Unix time (the number of seconds since 1970)

But when I run the following

import datetime
date = datetime.datetime(2020, 1 , 1, 0, 0, 0)

time1 = datetime.datetime.timestamp(date)
time2 = (date - datetime.datetime(1970,1,1,0,0,0)).total_seconds()

print(time1)
print(time2)

It prints:

1577862000.0
1577836800.0

Shouldn't these be the same? What am I misunderstanding?

FObersteiner
  • 22,500
  • 8
  • 42
  • 72
trazz
  • 43
  • 3
  • I bet you're based in Mountain Time zone :-) – user1717828 Sep 16 '21 at 22:59
  • 1
    There appears to be exactly 7 hours difference. Is your time zone UTC-7? – Henry Sep 16 '21 at 23:00
  • Does https://stackoverflow.com/questions/18812638/get-timezone-used-by-datetime-datetime-fromtimestamp help? – Karl Knechtel Sep 16 '21 at 23:07
  • 1
    actually, `time2` is correct since both input datetime objects are naive. The problem is `datetime.datetime.timestamp(date)` does more than you think - it converts given date/time from local time to UTC, *then* calculates seconds since 1970-01-01. That's where the offset comes from. As @wim points out, set tzinfo to UTC and you will be happy. – FObersteiner Sep 17 '21 at 06:08
  • 2
    Note: AFAIK the total_seconds() is also not the total number of seconds (it ignores, AFAIK, leap seconds). (such note is not useful on most cases, but when there are leap seconds, you may see strange things) – Giacomo Catenazzi Sep 17 '21 at 07:00
  • @GiacomoCatenazzi yes, see [technical detail, #4](https://docs.python.org/3/library/datetime.html#technical-detail): "*Unlike the time module, the datetime module does not support leap seconds.*" – FObersteiner Sep 17 '21 at 08:36

1 Answers1

4

Timezones. The unix epoch is Jan 1st 1970 in UTC, but your local zone is not UTC, so when you create a "naive" datetime instance using datetime.datetime(1970,1,1,0,0,0) it's offset from the real unix epoch by several hours.

Attach tzinfo=datetime.timezone.utc to both of the created datetime instances, and you'll see equality.

Alternatively, use datetime.datetime.fromtimestamp(0) instead of datetime.datetime(1970,1,1,0,0,0) to get a "naive" datetime instance coincident with the epoch.

wim
  • 338,267
  • 99
  • 616
  • 750
  • I think the problem in the OPs example is not `time2` that uses the naive `datetime(1970,1,1,0,0,0)` - time2 is correct since *both* datetime objects are naive (= both local time). The problem is how Unix time is derived from `date`, see also my comment under the question. – FObersteiner Sep 17 '21 at 06:10
  • @MrFuppes You're quite right, time2 is "correct" in that it equals `((50 * 365) + 12) * 24 * 60 * 60` exactly. But the question doesn't ask for this result specifically, it asks why they are not the same. I try to explain why the numbers are not the same, and propose two different approaches which will make the results the same (even though in each approach the actual result is different!). – wim Sep 17 '21 at 17:06
  • 1
    If there is any problem here, it's probably that OP was expecting `time1 = datetime.datetime.timestamp(dt)` to _not_ account for the local zone but to assume that the naive datetime is UTC (i.e. to get the result of `time1 = datetime.datetime.timestamp(dt.replace(tzinfo=datetime.timezone.utc))` instead). – wim Sep 17 '21 at 17:08