Search code examples
pythondatetimetimezonedstpytz

How to get the epoch value for any given Local Time with Time Zone & Daylight Saving Time in Python?


I'm new to Python and I have a use case which deals with datetime. Unfortunately, the data is not in UTC, so I have to rely on Local Time, Time Zones & Daylight Savings. I tried with datetime & pytz to get the epoch value from datetime, but its not working out.

Approach 1 : If I try creating datetime object, localize it to Brussels time and use strftime to convert to epoch, I'm getting valid response for the window outside Daylight Saving Time (DST). But for time within DST, I'm getting a response of -1.

Approach 2 : If I give the time zone details while creating the datetime object, and try to convert that to epoch, its giving value same as that for IST.

from datetime import datetime
import pytz

print('localize')
print(pytz.timezone("Asia/Kolkata").localize(datetime(2024, 10, 27, 0,0,0)).strftime('%s'))
print(pytz.timezone("Europe/Brussels").localize(datetime(2024, 10, 27, 0,0,0)).strftime('%s'))
print(pytz.timezone("Europe/Brussels").localize(datetime(2024, 10, 27, 6,0,0)).strftime('%s'))

print('tzinfo')
print(datetime(2024, 10, 27, 0,0,0, tzinfo=pytz.timezone("Asia/Kolkata")).strftime('%s'))
print(datetime(2024, 10, 27, 0,0,0,tzinfo=pytz.timezone("Europe/Brussels")).strftime('%s'))
print(datetime(2024, 10, 27, 6,0,0, tzinfo=pytz.timezone("Europe/Brussels")).strftime('%s'))

Output:

localize
1729967400
-1
1729989000
tzinfo
1729967400
1729967400
1729989000

What's even more confusing is, if I print the datetime values without formatting, Approach 1 shows valid info, while Approach 2 shows non-rounded offset values as shown below.

print('datetime values showing appropriate offset')
print(pytz.timezone("Asia/Kolkata").localize(datetime(2024, 10, 27, 0, 0, 0)))
print(pytz.timezone("Europe/Brussels").localize(datetime(2024, 10, 27, 0, 0, 0)))
print(pytz.timezone("Europe/Brussels").localize(datetime(2024, 10, 27, 6, 0, 0)))

print('datetime values showing different offset')
print(datetime(2024, 10, 27, 0,0,0, tzinfo=pytz.timezone("Asia/Kolkata")))
print(datetime(2024, 10, 27, 0,0,0,tzinfo=pytz.timezone("Europe/Brussels")))
print(datetime(2024, 10, 27, 6,0,0, tzinfo=pytz.timezone("Europe/Brussels")))

Output:

datetime values showing appropriate offset
2024-10-27 00:00:00+05:30
2024-10-27 00:00:00+02:00
2024-10-27 06:00:00+01:00
datetime values showing different offset
2024-10-27 00:00:00+05:53
2024-10-27 00:00:00+00:18
2024-10-27 06:00:00+00:18

Which is better and why so? Not sure if I'm missing anything. Can anyone help on this?


Solution

  • Use the built-in zoneinfo (available since Python 3.9) and .timestamp() instead of the non-standard .strftime('%s') (not supported on Windows). This produces correct results:

    # `zoneinfo` requires "pip install -U tzdata" for the latest time zone info
    # on some OSes, e.g. Windows.
    import datetime as dt
    import zoneinfo as zi
    
    print(dt.datetime(2024, 10, 27, tzinfo=zi.ZoneInfo('Asia/Kolkata')).timestamp())
    print(dt.datetime(2024, 10, 27, tzinfo=zi.ZoneInfo('Europe/Brussels')).timestamp())
    print(dt.datetime(2024, 10, 27, 6, tzinfo=zi.ZoneInfo('Europe/Brussels')).timestamp())
    
    print(dt.datetime(2024, 10, 27, tzinfo=zi.ZoneInfo('Asia/Kolkata')))
    print(dt.datetime(2024, 10, 27, tzinfo=zi.ZoneInfo('Europe/Brussels')))
    print(dt.datetime(2024, 10, 27, 6, tzinfo=zi.ZoneInfo('Europe/Brussels')))
    

    Output:

    1729967400.0
    1729980000.0
    1730005200.0
    2024-10-27 00:00:00+05:30
    2024-10-27 00:00:00+02:00
    2024-10-27 06:00:00+01:00