Last modified: May 10, 2026 By Alexander Williams
Date & Time in Polars with dt Namespace
Working with dates and times is a core task in data analysis. Polars provides a powerful and intuitive pl.Expr.dt namespace for this. It makes date and time manipulation fast and clean.
This article will guide you through the essential methods. You will learn how to extract parts of dates, round timestamps, and compute time differences. The examples are practical and easy to follow.
Before diving in, ensure your date columns are of the correct data type. Polars uses Date, Datetime, and Duration types. You can cast a string column to datetime using pl.col("date").str.to_datetime(). For more on casting, see our guide on Polars Data Type Casting & Schema Management.
Extracting Date Components
The dt namespace lets you extract specific components easily. Common components include year, month, day, and weekday.
Let's start with a simple example. We will create a DataFrame with a datetime column and extract the year and month.
import polars as pl
# Create a sample DataFrame
df = pl.DataFrame({
"date": ["2024-01-15", "2024-06-20", "2024-12-25"]
}).with_columns(
pl.col("date").str.to_datetime("%Y-%m-%d")
)
# Extract year and month
result = df.with_columns([
pl.col("date").dt.year().alias("year"),
pl.col("date").dt.month().alias("month")
])
print(result)
shape: (3, 3)
┌─────────────────────┬──────┬───────┐
│ date ┆ year ┆ month │
│ --- ┆ --- ┆ --- │
│ datetime[μs] ┆ i32 ┆ i32 │
╞═════════════════════╪══════╪═══════╡
│ 2024-01-15 00:00:00 ┆ 2024 ┆ 1 │
│ 2024-06-20 00:00:00 ┆ 2024 ┆ 6 │
│ 2024-12-25 00:00:00 ┆ 2024 ┆ 12 │
└─────────────────────┴──────┴───────┘
Other useful extractors include .day(), .weekday(), and .hour(). The .weekday() method returns Monday as 1 and Sunday as 7. This is great for grouping data by day of the week.
Rounding and Truncating Dates
Sometimes you need to round timestamps to a specific frequency. For example, you might want to group data by month or quarter. The dt.truncate() method handles this perfectly.
It rounds down a datetime to the start of a given period. Common periods include "1mo" for month, "1w" for week, and "1d" for day.
# Truncate dates to the start of the month
df_truncated = df.with_columns(
pl.col("date").dt.truncate("1mo").alias("month_start")
)
print(df_truncated)
shape: (3, 2)
┌─────────────────────┬─────────────────────┐
│ date ┆ month_start │
│ --- ┆ --- │
│ datetime[μs] ┆ datetime[μs] │
╞═════════════════════╪═════════════════════╡
│ 2024-01-15 00:00:00 ┆ 2024-01-01 00:00:00 │
│ 2024-06-20 00:00:00 ┆ 2024-06-01 00:00:00 │
│ 2024-12-25 00:00:00 ┆ 2024-12-01 00:00:00 │
└─────────────────────┴─────────────────────┘
You can also use dt.round() for rounding to the nearest boundary. For instance, rounding to the nearest hour is useful for time series analysis. Handling null values in date columns is also important. Check our guide on Handling Null & Missing Values in Polars for best practices.
Computing Date Offsets
Adding or subtracting time from dates is a common task. Polars provides the dt.offset_by() method for this. It accepts a string like "1d" for one day or "-2w" for two weeks ago.
# Add 10 days to each date
df_offset = df.with_columns(
pl.col("date").dt.offset_by("10d").alias("date_plus_10d")
)
print(df_offset)
shape: (3, 2)
┌─────────────────────┬─────────────────────┐
│ date ┆ date_plus_10d │
│ --- ┆ --- │
│ datetime[μs] ┆ datetime[μs] │
╞═════════════════════╪═════════════════════╡
│ 2024-01-15 00:00:00 ┆ 2024-01-25 00:00:00 │
│ 2024-06-20 00:00:00 ┆ 2024-06-30 00:00:00 │
│ 2024-12-25 00:00:00 ┆ 2025-01-04 00:00:00 │
└─────────────────────┴─────────────────────┘
You can use complex offsets like "1y2mo3d". This adds one year, two months, and three days. The method handles month-end correctly, which is a big plus.
Calculating Date Differences
To find the difference between two dates, use the subtraction operator. This returns a Duration column. You can then extract components like days or hours using the dt namespace on the duration.
# Create a DataFrame with two date columns
df_diff = pl.DataFrame({
"start": ["2024-01-01", "2024-06-01"],
"end": ["2024-01-15", "2024-07-10"]
}).with_columns([
pl.col("start").str.to_datetime("%Y-%m-%d"),
pl.col("end").str.to_datetime("%Y-%m-%d")
])
# Compute the difference in days
df_diff = df_diff.with_columns(
(pl.col("end") - pl.col("start")).dt.total_days().alias("days_diff")
)
print(df_diff)
shape: (2, 3)
┌─────────────────────┬─────────────────────┬───────────┐
│ start ┆ end ┆ days_diff │
│ --- ┆ --- ┆ --- │
│ datetime[μs] ┆ datetime[μs] ┆ i64 │
╞═════════════════════╪═════════════════════╪═══════════╡
│ 2024-01-01 00:00:00 ┆ 2024-01-15 00:00:00 ┆ 14 │
│ 2024-06-01 00:00:00 ┆ 2024-07-10 00:00:00 ┆ 39 │
└─────────────────────┴─────────────────────┴───────────┘
You can also use total_hours(), total_minutes(), or total_seconds(). This is perfect for calculating lead times or durations.
Working with Time Zones
Polars supports time zone aware datetimes. You can localize a naive datetime or convert between time zones using dt.replace_time_zone() and dt.convert_time_zone().
# Convert to a specific time zone
df_tz = df.with_columns(
pl.col("date").dt.replace_time_zone("UTC").alias("utc_date")
)
print(df_tz)
shape: (3, 2)
┌─────────────────────┬─────────────────────────┐
│ date ┆ utc_date │
│ --- ┆ --- │
│ datetime[μs] ┆ datetime[μs, UTC] │
╞═════════════════════╪═════════════════════════╡
│ 2024-01-15 00:00:00 ┆ 2024-01-15 00:00:00 UTC │
│ 2024-06-20 00:00:00 ┆ 2024-06-20 00:00:00 UTC │
│ 2024-12-25 00:00:00 ┆ 2024-12-25 00:00:00 UTC │
└─────────────────────┴─────────────────────────┘
To convert to another time zone, use dt.convert_time_zone("America/New_York"). This is essential for global data analysis.
Practical Example: Sales Data Analysis
Let's combine these techniques. Imagine you have sales data with timestamps. You want to group sales by month and compute the total revenue.
# Sample sales data
sales = pl.DataFrame({
"timestamp": ["2024-01-05", "2024-01-20", "2024-02-15", "2024-02-28"],
"revenue": [100, 200, 150, 300]
}).with_columns(
pl.col("timestamp").str.to_datetime("%Y-%m-%d")
)
# Group by month and sum revenue
monthly_sales = sales.with_columns(
pl.col("timestamp").dt.truncate("1mo").alias("month")
).group_by("month").agg(
pl.col("revenue").sum().alias("total_revenue")
)
print(monthly_sales)
shape: (2, 2)
┌─────────────────────┬───────────────┐
│ month ┆ total_revenue │
│ --- ┆ --- │
│ datetime[μs] ┆ i64 │
╞═════════════════════╪═══════════════╡
│ 2024-01-01 00:00:00 ┆ 300 │
│ 2024-02-01 00:00:00 ┆ 450 │
└─────────────────────┴───────────────┘
This pattern is very powerful. You can adapt it for weekly, quarterly, or yearly aggregations. The dt namespace makes it all straightforward.
Conclusion
The pl.Expr.dt namespace is a robust tool for date and time manipulation in Polars. It simplifies extraction, rounding, offsets, and time zone handling.
By mastering these methods, you can clean and analyze temporal data efficiently. Start with the examples above and explore the full API. For more on the Polars expression system, see our Polars Expression System Core Concept.
Remember to always check your data types first. A little practice will make you comfortable with these operations. Happy coding!