4. Timezones

4.1. Time zones in datetime library

  • Always keep dates and times only in UTC (important!)
  • Datetimes should be converted to localtime only when displaying to user
Code Listing 4.1. Make timezone aware object from naive datetime
from datetime import datetime, timezone


# timezone naive - nieświadome
datetime.now()
datetime.utcnow()
datetime(1957, 10, 4, 19, 28, 34)

# timezone aware - świadome
datetime.now(tz=timezone.utc)
datetime(1957, 10, 4, 19, 28, 34, tzinfo=timezone.utc)

4.2. pytz

4.2.1. List of Timezones

Code Listing 4.2. pytz brings the Olson tz database into Python.
from pytz import utc, timezone


utc = utc
eastern = timezone('US/Eastern')
warsaw = timezone('Europe/Warsaw')

4.2.2. From naive to local

Code Listing 4.3. From naive to local time
from datetime import datetime
from pytz import utc, timezone


gagarin = datetime(1961, 4, 12, 14, 7)  # timezone naive

gagarin = timezone('Asia/Almaty').localize(gagarin, is_dst=None)
# datetime.datetime(1961, 4, 12, 14, 7,
#                   tzinfo=<DstTzInfo 'Asia/Almaty' +06+6:00:00 STD>)

print(f'{gagarin:%Y-%m-%d %H:%M:%S %z}')
# 1961-04-12 14:07:00 +0600

4.2.3. From naive to UTC

Code Listing 4.4. From naive to local time
from datetime import datetime
from pytz import utc


gagarin = datetime(1961, 4, 12, 14, 7)      # timezone naive

in_utc = utc.localize(gagarin, is_dst=None)
# datetime.datetime(1961, 4, 12, 14, 7, tzinfo=<UTC>)

print(f'{in_utc:%Y-%m-%d %H:%M:%S %z}')
# 1961-04-12 14:07:00 +0000

4.2.4. From UTC to local time

Code Listing 4.5. From UTC to local time
from datetime import datetime
from pytz import timezone, utc


armstrong = datetime(1969, 7, 21, 14, 56, 15, tzinfo=utc)

waw_time = armstrong.astimezone(timezone('Europe/Warsaw'))
# datetime.datetime(1969, 7, 21, 15, 56, 15,
#                   tzinfo=<DstTzInfo 'Europe/Warsaw' CET+1:00:00 STD>)

print(f'{waw_time:%Y-%m-%d %H:%M:%S %Z%z}')
# 1969-07-21 15:56:15 CET+0100

4.2.5. Between timezones

Code Listing 4.6. Between timezones
from datetime import datetime
from pytz import utc, timezone


gagarin = datetime(1961, 4, 12, 14, 7, tzinfo=timezone('Asia/Almaty'))

in_utc = gagarin.astimezone(utc)                        # datetime.datetime(1961, 4, 12, 8, 59, tzinfo=<UTC>)
print(f'{in_utc:%Y-%m-%d %H:%M:%S %z}')               # 1961-04-12 08:59:00 +0000

in_waw = gagarin.astimezone(timezone('Europe/Warsaw'))  # datetime.datetime(1961, 4, 12, 9, 59, tzinfo=<DstTzInfo 'Europe/Warsaw' CET+1:00:00 STD>)
print(f'{in_waw:%Y-%m-%d %H:%M:%S %z}')               # 1961-04-12 09:59:00 +0100