Implementation:Pola rs Polars Datetime Timezone Ops
| Knowledge Sources | |
|---|---|
| Domains | Data Engineering, Time Series |
| Last Updated | 2026-02-09 10:00 GMT |
Overview
Concrete APIs for attaching, converting, and removing timezone information on Polars Datetime columns and Series using IANA timezone identifiers.
Description
Polars provides two primary timezone operations accessible through the dt accessor namespace. Expr.dt.replace_time_zone(time_zone) attaches or replaces a timezone label on a datetime column without shifting the underlying instant (the wall-clock time stays the same). Expr.dt.convert_time_zone(time_zone) converts an already timezone-aware datetime to display in a different timezone, preserving the underlying instant while changing the wall-clock display.
Both operations are also available on Series objects via Series.dt.replace_time_zone() and Series.dt.convert_time_zone(). Passing None to replace_time_zone removes timezone information, producing a naive datetime.
Usage
Use these APIs whenever you need to:
- Label a naive datetime column with a timezone after parsing.
- Convert timezone-aware datetimes to a different timezone for display or alignment.
- Remove timezone information to produce naive datetimes.
Code Reference
Source Location
- Repository: Polars
- File:
docs/source/src/python/user-guide/transformations/time-series/timezones.py(lines 1-27)
Signature
# Expression-level timezone operations
Expr.dt.replace_time_zone(
time_zone: str | None,
*,
ambiguous: str | Expr = "raise",
non_existent: str = "raise",
) -> Expr
Expr.dt.convert_time_zone(
time_zone: str,
) -> Expr
# Series-level timezone operations
Series.dt.replace_time_zone(
time_zone: str | None,
*,
ambiguous: str | Expr = "raise",
non_existent: str = "raise",
) -> Series
Series.dt.convert_time_zone(
time_zone: str,
) -> Series
Import
import polars as pl
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| time_zone | None | Yes | IANA timezone identifier (e.g., "UTC", "Europe/Brussels", "Asia/Kathmandu"); None removes timezone (for replace_time_zone only)
|
| ambiguous | Expr | No | How to handle ambiguous datetimes during DST transitions: "raise" (default), "earliest", "latest", or "null"
|
| non_existent | str |
No | How to handle non-existent datetimes during DST spring-forward: "raise" (default) or "null"
|
Outputs
| Name | Type | Description |
|---|---|---|
| result (Expr) | pl.Expr |
Expression yielding a Datetime column with the specified timezone applied or converted
|
| result (Series) | pl.Series |
Series with timezone-aware or timezone-naive datetimes |
Usage Examples
Replace Time Zone on Naive Series
import polars as pl
ts = ["2021-03-27 03:00", "2021-03-28 03:00"]
tz_naive = pl.Series("tz_naive", ts).str.to_datetime()
# Attach UTC timezone (wall-clock time unchanged)
tz_aware = tz_naive.dt.replace_time_zone("UTC")
print(tz_aware)
Replace, Convert, and Unset Timezones
import polars as pl
ts = ["2021-03-27 03:00", "2021-03-28 03:00"]
tz_naive = pl.Series("tz_naive", ts).str.to_datetime()
tz_aware = tz_naive.dt.replace_time_zone("UTC")
df = pl.DataFrame([tz_naive, tz_aware.rename("tz_aware")])
result = df.select(
# Replace: re-label as Brussels (wall-clock stays the same)
pl.col("tz_aware").dt.replace_time_zone("Europe/Brussels").alias("replace tz"),
# Convert: shift display to Kathmandu (instant stays the same)
pl.col("tz_aware").dt.convert_time_zone("Asia/Kathmandu").alias("convert tz"),
# Unset: remove timezone information
pl.col("tz_aware").dt.replace_time_zone(None).alias("unset tz"),
)
print(result)
Handle DST Ambiguity
import polars as pl
# During fall-back, 02:30 occurs twice in US Eastern
ambiguous_ts = pl.Series("ts", ["2023-11-05 01:30"]).str.to_datetime()
# Use "earliest" to pick the first occurrence (EDT)
result = ambiguous_ts.dt.replace_time_zone(
"America/New_York", ambiguous="earliest"
)
print(result)