pola-rs/polars · error · NotImplementedError

unsupported temporal data type: {dtype!r}

Error message

unsupported temporal data type: {dtype!r}

What it means

Temporal protocol dtypes are recognized purely by their format string: 'ts<m|u|n>:<tz>' for datetimes, 'tdD' for dates, 'ttu' for times, and 'tD<m|u|n>' for durations. Any other format string falls through all branches and raises NotImplementedError with the offending dtype shown. The producer emitted a temporal encoding polars cannot parse.

Source

Thrown at py-polars/src/polars/interchange/utils.py:148

def _temporal_dtype_to_polars_dtype(format_str: str, dtype: Dtype) -> PolarsDataType:
    if (match := re.fullmatch(r"ts([mun]):(.*)", format_str)) is not None:
        time_unit = match.group(1) + "s"
        time_zone = match.group(2) or None
        return Datetime(
            time_unit=time_unit,  # type: ignore[arg-type]
            time_zone=time_zone,
        )
    elif format_str == "tdD":
        return Date
    elif format_str == "ttu":
        return Time
    elif (match := re.fullmatch(r"tD([mun])", format_str)) is not None:
        time_unit = match.group(1) + "s"
        return Duration(time_unit=time_unit)  # type: ignore[arg-type]

    msg = f"unsupported temporal data type: {dtype!r}"
    raise NotImplementedError(msg)


def get_buffer_length_in_elements(buffer_size: int, dtype: Dtype) -> int:
    """Get the length of a buffer in elements."""
    bits_per_element = dtype[1]
    bytes_per_element, rest = divmod(bits_per_element, 8)
    if rest > 0:
        msg = f"cannot get buffer length for buffer with dtype {dtype!r}"
        raise ValueError(msg)
    return buffer_size // bytes_per_element


def polars_dtype_to_data_buffer_dtype(dtype: PolarsDataType) -> PolarsDataType:
    """Get the data type of the data buffer."""
    if dtype.is_integer() or dtype.is_float() or dtype == Boolean:
        return dtype
    elif dtype.is_temporal():
        return Int32 if dtype == Date else Int64

View on GitHub (pinned to df599052da)

Solutions

  1. Fix the producer to emit one of the supported format strings (ts[mun]:tz, tdD, ttu, tD[mun])
  2. Expose the column as plain integers upstream and build the Datetime/Duration in Polars afterwards with cast
  3. Upgrade polars if the format string was added in a newer release

Example fix

// producer-side fix: emit 'tsu:UTC' instead of 'tsa:UTC'
// consumer-side workaround: import as Int64 and cast
df = pl.from_dataframe(raw_df).with_columns(pl.col('ts').cast(pl.Datetime('us', 'UTC')))
Defensive patterns

Strategy: try-catch

Validate before calling

import re

SUPPORTED_TEMPORAL = re.compile(r'^(ts[mun]:.*|tdD|ttu|tD[mun])$')

def temporal_format_supported(format_str: str) -> bool:
    return SUPPORTED_TEMPORAL.fullmatch(format_str) is not None

Try / catch

try:
    out = pl.from_dataframe(df)
except NotImplementedError as e:
    if 'unsupported temporal data type' in str(e):
        raise ValueError(
            'producer emits a temporal format string polars cannot parse; '
            'use ts[mun]:tz / tdD / ttu / tD[mun] or export raw integers'
        ) from e
    raise

Prevention

When it happens

Trigger: A producer emitting a non-standard or malformed temporal format string, e.g. 'tsa:...' (attoseconds), 'tdW' (weeks), or a misspelled variant.

Common situations: Hand-rolled producers with typo'd format strings; draft or extended spec encodings; unit mismatches after a producer changes its temporal representation.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/b3979176a8371a06. Report an issue: GitHub.