14

This is really two questions: 1st, are Epoch (Unix) timestamps the same on all machines (assuming their system clocks are correct), regardless of timezones?

I ask because I have code deployed to AWS Lambda that generates Epoch timestamps using the datetime module. When we extract the data, I am trying to convert to a local time string (also using datetime) and I am getting a 2 hour difference to what was expected. I then started testing the following code:

import datetime
import time

print(time.time()) #1
print(datetime.datetime.utcnow().timestamp()) #2

print#1: 1554747526.775873
print#2: 1554783526.775873

Running on my local machine, they are different by two hours. I deployed the above code to AWS Lambda and they return the same values. How is it different on my machine? The screenshot below shows the same code running on AWS Lambda (left) and my local machine. My system clock is correct.

time.time() vs datetime.utcnow().timestamp()

dandev91
  • 1,691
  • 3
  • 22
  • 34
  • I've noted the same thing both on my ubuntu desktop and on my android phone. There is a 2h discrepancy in both machines. – sinekonata Sep 16 '20 at 10:51

5 Answers5

5

The reason has to do with the timezone of your computer. The library time uses the timezone set in your computer, but in the case of the datetime library you're using the UTC timezone. In order to obtain the timestamp in the same timezone use datetime.datetime.now().timestamp()

Alberto Bonsanto
  • 17,556
  • 10
  • 64
  • 93
  • On both my computer and phone, datetime.utcnow().timestamp() gives 2h less than time.time() whereas datetime.now().timestamp() gives the same as time.time(). But datetime.utcnow() does indeed give the correct utc hour. Note that therefore my actual displayed clock time on both my computer and phone is 4h more than datetime.utcnow().timestamp()... – sinekonata Sep 16 '20 at 11:05
2

Although datetime.datetime.utcnow() returns a datetime object with the current UTC time, the object returned is timezone naive, i.e. the object doesn't have any timezone info attached.

Example:

>>> datetime.datetime.utcnow()
datetime.datetime(2022, 12, 9, 11, 12, 33, 442103) # no timezone info

Without the timezone info, it is just a regular datetime object. By looking at the object, there is no way to tell whether this time is local time or UTC time.

When you call .timestamp() method on a datetime object, it assumes it to be in your local time and then returns the timestamp.


Better way to get UTC timestamps is like this:

>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2022, 12, 9, 11, 12, 33, 442103, tzinfo=timezone.utc)

As you can see, this time the object has a timezone attached. Now, if you call .timestamp() method on it, you'll get the timestamp in UTC.

xyres
  • 20,487
  • 3
  • 56
  • 85
1

The issue was the ".timestamp()" function.

If I run "datetime.datetime.utcnow()" on AWS, my local machine (and the various test machines I also have (EC2 AWS instances)) they return the same value. The ".timestamp()" function is causing the change.

Also, time.time() apparently only returns time since Epoch. "... this is platform-specific. A platform can return anything it wants for time, as long as it does so in a way that makes localtime and gmtime work properly. That being said, it's usually going to be GMT—or, rather, either UTC (Windows), or UTC-except-for-leap-seconds (most other platforms)." See: Does Python's time.time() return a timestamp in UTC?

dandev91
  • 1,691
  • 3
  • 22
  • 34
1

Let's compare calls at local PC and server at Digital Ocean.

datetime.now() - have difference at 3 hours on PC and server;

datetime.utcnow() - equal on both machine;

BUT

datetime.utcnow().timestamp() - have difference at 10800 seconds!!!

# local machine (Win64) UTC+0
>>> datetime.now(), datetime.utcnow(), datetime.utcnow().timestamp()
(datetime.datetime(2019, 8, 2, 22, 13, 39, 535678),   # datetime.now()
datetime.datetime(2019, 8, 2, 19, 13, 39, 535678),    # datetime.utcnow()
1564762419.535678)                                    # datetime.utcnow().timestamp()

# server(Ubuntu 18) UTC+2.0
>>> datetime.now(), datetime.utcnow(), datetime.utcnow().timestamp()
(datetime.datetime(2019, 8, 2, 19, 13, 39, 253675),   # datetime.now()
datetime.datetime(2019, 8, 2, 19, 13, 39, 253691),    # datetime.utcnow()
1564773219.253692)                                    # datetime.utcnow().timestamp()
1

According to the docu on timestamp(), it seems that utcnow() and now() return "naive" instead of "aware" datetimes. I imagine it means they're unaware of what the timezone is or something of the sort.

Their solution seems to be to call timestamp on a datetime with set timezone :

datetime.datetime.utcnow().replace(tzinfo= datetime.timezone.utc).timestamp()
datetime.datetime.now().replace(tzinfo= datetime.timezone.utc).timestamp()

The first is equivalent to time.time(). The second will return the timestamp equivalent to your timezone.

enter image description here

sinekonata
  • 364
  • 3
  • 11