How do you get the UTC time offset in Python now that utcnow() is deprecated?

1.5k Views Asked by At

I need the time difference in sec between my current location and UTC. It worked so well with (example timezone Berlin, UTC+1h) :

import datetime
datetime.datetime.utcnow().timestamp(): 1699017779.016835
datetime.datetime.now().timestamp():    1699021379.017343 # 3600 sec larger, correct!

But now utcnow() is marked as deprecated, and I need now() and load it with a timezone object:

datetime.datetime.now(datetime.timezone.utc): 2023-11-03 14:22:59.018573+00:00
datetime.datetime.now():                      2023-11-03 15:22:59.018941    # 1 h later, correct!

Also giving correct result. But as I want the timestamp, I do as before, but get the wrong result:

datetime.datetime.now(datetime.timezone.utc).timestamp()) 1699021379.019286 # UTC  : is actually local timestamp
datetime.datetime.now().timestamp())                      1699021379.019619 # Local: why no difference ???

Local is correct, but UTC is now giving the exact same timestamp as Local, and this wrong! Am I missing anything or is this simply a bug?

EDIT:

After reviewing all the comments I disagree with some commenters - I see nothing wrong with utcnow(). It does give the UTC timestamp for the moment of calling. Of course there is no timezone involved when you ask for UTC time! What does seem wrong is to use timestamps for other places which include the time difference to UTC and view this as a UTC/UNIX timestamp?

But perhaps I should make my needs clearer: I want the time difference between my timezone and UTC in seconds. Is there a simpler way to get this in Python?

None of the answers and comments provide an answer to this question.

EDIT2

I found 2 possible workarounds:

import datetime as dt
# workaround #1
ts = time.time()
utc   = dt.datetime.fromtimestamp(ts, tz=datetime.timezone.utc)                     # 2023-11-06 11:49:30.154083+00:00
local = dt.datetime.fromtimestamp(ts, tz=None)                                      # 2023-11-06 12:49:30.154083
ts_utc   = dt.datetime.strptime(str(utc)  [0:19], "%Y-%m-%d %H:%M:%S").timestamp()  # 1699267770.0
ts_local = dt.datetime.strptime(str(local)[0:19], "%Y-%m-%d %H:%M:%S").timestamp()  # 1699271370.0  # more by 3600 sec
TimeZoneOffset = ts_local - ts_utc                                                  # +3600 (sec)

# workaround #2
TimeZoneOffset = dt.datetime.now().astimezone().utcoffset().total_seconds()         # +3600 (sec)
1

There are 1 best solutions below

2
Malcolm On

The unix time stamp is the number of seconds since 00:00:00 on January 1, 1970 UTC. It is a global value not local, which is what makes it useful.

The issues is actually with utcnow. Either you have your original example code answers inverted or you are located east of Greenwich where your timezone is ahead of the UTC and you should have actually been expecting a smaller timestamp from utcnow. For me, where I am 4 hours behind UTC time (i.e. west of Greewich).

>>> datetime.datetime.utcnow().timestamp()
1699038850.622385
>>> datetime.datetime.now().timestamp()
1699024453.862131
>>> 

So, for me it is the utcnow timestamp that is larger. The problem is that datetime.datetime.utcnow() generates a datetime.datetime object that doesn't have timezone information embedded. So, when you call timestamp on it you get the timestamp for when your local time is what the UTC time is now.

I expect this is part of why utcnow is deprecated.