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

  1. Cast to a true temporal dtype first, e.g. cast(&arr, &ArrowDataType::Timestamp(TimeUnit::Microsecond, None)) or Date32
  2. If values are epoch integers, convert via the epoch helpers instead of calling year() on primitives
  3. Guard with a matches! on array.dtype().to_storage() before calling
  4. 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

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.