Explain Codes LogoExplain Codes Logo

Iso time (ISO 8601) in Python

python
datetime
pytz
isoformat
Anton ShumikhinbyAnton Shumikhin·Sep 30, 2024
TLDR

To work with ISO 8601 times in Python, use the datetime module. In particular, datetime.isoformat() is used to convert to ISO format, and datetime.fromisoformat() is for parsing from ISO format. Here's the gist of it:

from datetime import datetime # Convert to ISO 8601 iso_formatted = datetime.now().isoformat() print(iso_formatted) # e.g., '2023-04-02T12:34:56.789123' - shakes the magic 8-ball # Parse from ISO 8601 parsed_datetime = datetime.fromisoformat('2023-04-02T12:34:56.789123') print(parsed_datetime) # 2023-04-02 12:34:56.789123 - it's not magic, it's Python!

When dealing with time zones, tzinfo comes to your rescue:

from datetime import datetime, timezone # UTC time with TimeZone info iso_formatted_utc = datetime.now(timezone.utc).isoformat() print(iso_formatted_utc) # e.g., '2023-04-02T12:34:56.789123+00:00' - UTC, the time zone of kings

Tackling time zones and DST

Time zones and Daylight Saving Time (DST) differ across regions and need careful handling. Here are some pragmatic examples using the datetime and pytz libraries.

Casting UTC and local time into ISO 8601 format

For UTC time with time zone info:

from datetime import datetime, timezone # Express UTC time in ISO 8601 with TimeZone info utc_time_with_tz = datetime.utcnow().replace(tzinfo=timezone.utc).isoformat() print(utc_time_with_tz) # e.g., '2023-04-02T12:34:56.789123+00:00' - Universal Time, convert it!

For expressing local time with time zone info:

# Craft local time in ISO 8601 with TimeZone info local_time_with_tz = datetime.now().astimezone().isoformat() print(local_time_with_tz) # e.g., '2023-04-02T12:34:56.789123-04:00' - I live here. Period.

Beware the Ides of astimezone()

Be cautious—astimezone() can invite trouble if applied unwisely on UTC times. Always crosscheck time zone and DST rules for the region in focus.

Pruning microseconds

Oftentimes, microsecond precision is an overkill. Prune them if not needed.

# Castles made of time, without the sand (microseconds) formatted_without_microseconds= datetime.now().replace(microsecond=0).isoformat() print(formatted_without_microseconds) # e.g., '2023-04-02T12:34:56' - Bingo, no microseconds

Special formatting touches

strftime — a string time master

strftime() empowers you to format the time to comply with ISO 8601:

iso_formatted_strftime = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') print(iso_formatted_strftime) # e.g., '2023-04-02T12:34:56Z' - The Z stands for "zero offset", not "Zorro was here"

ISO 8601 strings — compact and crisp

A compact form of ISO 8601 string can come handy at times:

compact_iso_string = datetime.utcnow().strftime('%Y%m%dT%H%M%SZ') print(compact_iso_string) # e.g., '20230402T123456Z' - Compact, like my first car

Converting ISO 8601 strings back to datetime

The ability to convert back ISO time strings to datetime object is as handy as a Swiss knife:

from datetime import datetime dt = datetime.strptime("2023-04-02T12:34:56Z", '%Y-%m-%dT%H:%M:%SZ') print(dt) # 2023-04-02 12:34:56 - It's like turning back time!

Working with sub-second precision and time zone conversions

Sub-second time precision

There are times when sub-second precision holds importance:

# Showcasing sub-second precision from datetime import datetime print(datetime.now().isoformat(timespec='microseconds')) # 'It's getting sub-atomic here!'

Time zone conversion

The conversion of time zones using isoformat() demands tzinfo:

from datetime import datetime, timezone, timedelta # Convert to a different time zone dt = datetime.now() target_tz = timezone(timedelta(hours=9)) # e.g., JST dt_with_tz = dt.astimezone(target_tz).isoformat() print(dt_with_tz) # e.g., '2023-04-02T21:34:56.789123+09:00' - Tokyo Drift, anyone?

Dealing with challenges and portability

Managing DST and time zone fluctuations

Keeping grip on DST and time zone changes is crucial for accurate time representation.

from datetime import datetime import pytz # Correctly account for DST ny_tz = pytz.timezone('America/New_York') ny_time_with_dst = datetime.now(ny_tz).isoformat() print(ny_time_with_dst) # 'If you could turn back time... you'd manage DST better'

Portability across systems

ISO 8601 time format ensures smooth portability across different systems and locales.

# For system-to-system handshakes, use ISO 8601 reliable_iso_format = datetime.now().isoformat() # 'I'm portable. Like a barbecue.'

RFC 3339 compliance

ISO 8601 forms the cornerstone of RFC 3339, which stipulates time stamps in internet protocols:

# For system-to-web interactions, RFC 3339 plays the referee. rfc_3339_format = datetime.now().replace(microsecond=0).isoformat('T') + 'Z' print(rfc_3339_format) # '2023-04-02T12:34:56Z - It's web time!'