pola-rs/polars · error
not implemented
Error message
not implemented
What it means
The date_like! macro backs year/month/day/weekday/iso_week in polars-arrow::compute::temporal. It only accepts Date32, Date64 and Timestamp (naive or zoned); every other dtype falls into _ => unimplemented!() (crates/polars-arrow/src/compute/temporal.rs:72) and panics, even though the public functions return PolarsResult. The doc comments advertise can_* predicates, but this file defines none, so callers must check dtypes themselves.
Source
Thrown at crates/polars-arrow/src/compute/temporal.rs:72
($extract:ident, $array:ident, $dtype:path) => {
match $array.dtype().to_storage() {
ArrowDataType::Date32 | ArrowDataType::Date64 | ArrowDataType::Timestamp(_, None) => {
date_variants($array, $dtype, |x| x.$extract().try_into().unwrap())
},
ArrowDataType::Timestamp(time_unit, Some(timezone_str)) => {
let array = $array.as_any().downcast_ref().unwrap();
if let Ok(timezone) = parse_offset(timezone_str.as_str()) {
Ok(extract_impl(array, *time_unit, timezone, |x| {
x.$extract().try_into().unwrap()
}))
} else {
chrono_tz(array, *time_unit, timezone_str.as_str(), |x| {
x.$extract().try_into().unwrap()
})
}
},
_ => unimplemented!(),
}
};
}
/// Extracts the years of a temporal array as [`PrimitiveArray<i32>`].
pub fn year(array: &dyn Array) -> PolarsResult<PrimitiveArray<i32>> {
date_like!(year, array, ArrowDataType::Int32)
}
/// Extracts the months of a temporal array as [`PrimitiveArray<i8>`].
///
/// Value ranges from 1 to 12.
pub fn month(array: &dyn Array) -> PolarsResult<PrimitiveArray<i8>> {
date_like!(month, array, ArrowDataType::Int8)
}
/// Extracts the days of a temporal array as [`PrimitiveArray<i8>`].
///View on GitHub (pinned to df599052da)
Solutions
- Cast to a true temporal dtype first, e.g. cast(&arr, &ArrowDataType::Timestamp(TimeUnit::Microsecond, None)) or Date32
- If values are epoch integers, convert via the epoch helpers instead of calling year() on primitives
- Guard with a matches! on array.dtype().to_storage() before calling
- For time-of-day dtypes use hour/minute/second (time_like) which accept Time32/Time64
Example fix
// before let years = temporal::year(&int64_array)?; // panics: _ => unimplemented!() // after let dates = cast(&int64_array, &ArrowDataType::Timestamp(TimeUnit::Microsecond, None))?; let years = temporal::year(dates.as_ref())?;
Defensive patterns
Strategy: type-guard
Validate before calling
if !can_extract_date(array.dtype()) {
polars_bail!(InvalidOperation: "date extraction requires Date32/Date64/Timestamp, got {:?}", array.dtype());
} Type guard
fn can_extract_date(dtype: &ArrowDataType) -> bool {
matches!(
dtype.to_storage(),
ArrowDataType::Date32 | ArrowDataType::Date64 | ArrowDataType::Timestamp(_, _)
)
} Try / catch
let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| temporal::year(array)));
let years = match res {
Ok(v) => v?,
Err(_) => polars_bail!(InvalidOperation: "year() panicked: cast {:?} to Date/Timestamp first", array.dtype()),
}; Prevention
- Always cast epoch columns to Timestamp/Date at ingestion; never rely on physical layout
- Centralize dtype validation before temporal kernels
- Unit-test temporal extraction against every dtype your pipeline can see
When it happens
Trigger: Calling year/month/day/weekday/iso_week on Time32/Time64/Duration arrays, or on plain Int32/Int64 arrays holding epoch values that were never cast to a date dtype.
Common situations: Parquet or CSV columns inferred as Int64 that the user assumes are dates; timestamps loaded through a path that drops the logical type; subtracting two dates into a Duration and then extracting year(); pl.time columns passed to date extractors.
Related errors
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/dffd3672a15787d9.
Report an issue: GitHub.