Datetimes with Timezones in Python

First, let’s show how the commonly-used plain datetime.datetime.now() gets the local time but does not have a timezone:

>>> import datetime
>>> now = datetime.datetime.now()
>>> type(now)
<class 'datetime.datetime'>
>>> now
datetime.datetime(2024, 2, 17, 12, 47, 40, 34210)
>>> print(now)
2024-02-17 12:47:40.034210
>>> now.tzinfo is None
True
>>>

Let’s add timezone to it, using the zoneinfo module that is in the Python standard library since version 3.9:

>>> import zoneinfo
>>> now = now.replace(tzinfo=zoneinfo.ZoneInfo("localtime"))
>>> now
datetime.datetime(2024, 2, 17, 12, 47, 40, 34210, tzinfo=zoneinfo.ZoneInfo(key='localtime'))
>>> print(now)
2024-02-17 12:47:40.034210+02:00
>>> 

I’m in Europe/Helsinki timezone, or +02:00 UTC.

Instead of replacing the timezone of the datetime.datetime object separately, we can also call datetime.datetime.now() with the timezone argument to get the timezone-aware object right away:

>>> now = datetime.datetime.now(zoneinfo.ZoneInfo("localtime"))
>>> now
datetime.datetime(2024, 2, 17, 12, 53, 12, 528517, tzinfo=zoneinfo.ZoneInfo(key='localtime'))
>>> print(now)
2024-02-17 12:53:12.528517+02:00
>>>

Now, let’s take another timestamp that’s in UTC, like any timestamp data that you usually get from API calls:

>>> some_timestamp = datetime.datetime.fromisoformat("2024-02-17 11:00:00").replace(tzinfo=datetime.timezone.utc)
>>> some_timestamp
datetime.datetime(2024, 2, 17, 11, 0, tzinfo=datetime.timezone.utc)
>>>

We can then compare the timestamps:

>>> print(now)
2024-02-17 12:53:12.528517+02:00
>>> print(some_timestamp)
2024-02-17 11:00:00+00:00
>>> now > some_timestamp
False
>>>

That’s correct, because:

>>> print(some_timestamp.astimezone(zoneinfo.ZoneInfo("localtime")))
2024-02-17 13:00:00+02:00
>>>

We can also use whatever IANA timezone names are available:

>>> len(zoneinfo.available_timezones())
596
>>> sorted([tz for tz in zoneinfo.available_timezones() if "US/" in tz])
['US/Alaska', 'US/Aleutian', 'US/Arizona', 'US/Central', 'US/East-Indiana', 'US/Eastern', 'US/Hawaii', 'US/Indiana-Starke', 'US/Michigan', 'US/Mountain', 'US/Pacific', 'US/Samoa']
>>> print(now.astimezone(zoneinfo.ZoneInfo("US/Pacific")))
2024-02-17 02:53:12.528517-08:00
>>>

If you need to get the current UTC offset for some reason, you can get it via the datetime.utcoffset() method:

>>> now.utcoffset()
datetime.timedelta(seconds=7200)
>>> now.utcoffset().total_seconds()
7200.0
>>> datetime.datetime.now(zoneinfo.ZoneInfo("US/Pacific")).utcoffset().total_seconds()
-28800.0
>>>
Updated: February 17, 2024 — 15:21

Leave a Reply