Since Python 3.9, the zoneinfo module in the standard library is recommended for timezone processing.
This allows accurate handling of regional timezones like Japan Standard Time (Asia/Tokyo) and Coordinated Universal Time (UTC). This article explains how to generate timezone-aware datetime objects and how to add timezone information to objects that lack it (Naive objects).
Prerequisite: Installing tzdata
On environments like Windows that do not include the IANA timezone database by default, you need to install the following package:
pip install tzdata
1. Specifying Timezone During Creation
When creating a datetime object, you can generate an “Aware” datetime (one holding timezone information) from the start by passing a ZoneInfo object to the tzinfo argument.
Implementation Example: Setting Meeting Time
from datetime import datetime
from zoneinfo import ZoneInfo
# 1. Create with specific timezone (JST)
# September 1, 2024 10:30 (Japan Time)
meeting_schedule = datetime(
2024, 9, 1, 10, 30,
tzinfo=ZoneInfo("Asia/Tokyo")
)
print(f"Specified (JST): {meeting_schedule}")
# 2. Get current time with timezone (JST)
# Specify in the tz argument of datetime.now()
current_time_jst = datetime.now(tz=ZoneInfo("Asia/Tokyo"))
print(f"Current (JST) : {current_time_jst}")
Execution Result
Specified (JST): 2024-09-01 10:30:00+09:00
Current (JST) : 2025-12-15 19:30:00.123456+09:00
Note: The +09:00 clearly indicates this is Japan Standard Time.
2. Adding Timezone to Existing Datetimes (replace)
If you have a date object without timezone information (Naive datetime) and want to assign a timezone to it later, use the replace() method.
Implementation Example: Setting Timezone for Log Data
from datetime import datetime
from zoneinfo import ZoneInfo
# Date without timezone info (Naive)
# Example: Date read from a log file
naive_dt = datetime(2024, 9, 1, 10, 30)
print(f"Original (Naive): {naive_dt}")
# 1. Assign Japan Standard Time (Asia/Tokyo)
# Rewrite only the tzinfo attribute using replace
dt_jst = naive_dt.replace(tzinfo=ZoneInfo("Asia/Tokyo"))
print(f"Assigned JST : {dt_jst}")
# 2. Assign Coordinated Universal Time (UTC)
dt_utc = naive_dt.replace(tzinfo=ZoneInfo("UTC"))
print(f"Assigned UTC : {dt_utc}")
Execution Result
Original (Naive): 2024-09-01 10:30:00
Assigned JST : 2024-09-01 10:30:00+09:00
Assigned UTC : 2024-09-01 10:30:00+00:00
Explanation
ZoneInfo("Region/City"): Specify the IANA timezone database identifier as a string (e.g.,"Asia/Tokyo","America/New_York","UTC").- Naive vs. Aware:
- Naive: Datetime without timezone information. Easy to use for local processing but unsuitable for international comparisons or conversions.
- Aware: Datetime with timezone information. It holds offset data like
+09:00, enabling calculations between different timezones.
- Note on
replace(): Thereplace(tzinfo=...)method does not convert the time value itself; it simply “labels” the time as belonging to a specific timezone. If you want to convert the time difference (e.g., convert JST to UTC), you must use theastimezone()method instead.
