pola-rs/polars · error · ValueError

`time_unit` must be one of {'ns', 'us', 'ms', 's', 'd'}, got

Error message

`time_unit` must be one of {'ns', 'us', 'ms', 's', 'd'}, got {time_unit!r}

What it means

Expr.dt.epoch extracts a timestamp as an integer and accepts only 'ns', 'us', 'ms', 's', and 'd'. 's' is computed as timestamp('ms') // 1000 and 'd' casts via Date to Int32; every other value raises ValueError. There is no case folding or plural handling.

Source

Thrown at py-polars/src/polars/expr/datetime.py:1853

        ┌────────────┬─────────────────┬───────────┐
        │ date       ┆ epoch_ns        ┆ epoch_s   │
        │ ---        ┆ ---             ┆ ---       │
        │ date       ┆ i64             ┆ i64       │
        ╞════════════╪═════════════════╪═══════════╡
        │ 2001-01-01 ┆ 978307200000000 ┆ 978307200 │
        │ 2001-01-02 ┆ 978393600000000 ┆ 978393600 │
        │ 2001-01-03 ┆ 978480000000000 ┆ 978480000 │
        └────────────┴─────────────────┴───────────┘
        """
        if time_unit in DTYPE_TEMPORAL_UNITS:
            return self.timestamp(time_unit)  # type: ignore[arg-type]
        elif time_unit == "s":
            return self.timestamp("ms") // F.lit(1000, Int64)
        elif time_unit == "d":
            return wrap_expr(self._pyexpr).cast(Date).cast(Int32)
        else:
            msg = f"`time_unit` must be one of {{'ns', 'us', 'ms', 's', 'd'}}, got {time_unit!r}"
            raise ValueError(msg)

    def timestamp(self, time_unit: TimeUnit = "us") -> Expr:
        """
        Return a timestamp in the given time unit.

        .. engine-support:: in-memory, streaming, distributed

        Parameters
        ----------
        time_unit : {'ns', 'us', 'ms'}
            Time unit.

        Examples
        --------
        >>> from datetime import date
        >>> df = (
        ...     pl.date_range(date(2001, 1, 1), date(2001, 1, 3), eager=True)
        ...     .alias("date")

View on GitHub (pinned to df599052da)

Solutions

  1. Use one of exactly 'ns', 'us', 'ms', 's', 'd'
  2. Normalise human unit names first: {'seconds':'s','secs':'s','milliseconds':'ms','microseconds':'us','nanoseconds':'ns','days':'d'}
  3. For unsupported units like minutes/hours, derive from a supported one: .dt.epoch('s') // 60

Example fix

# before
pl.col('ts').dt.epoch('seconds')  # ValueError

# after
pl.col('ts').dt.epoch('s')
# minutes, derived: pl.col('ts').dt.epoch('s') // 60
Defensive patterns

Strategy: validation

Validate before calling

VALID_EPOCH_UNITS = {'ns', 'us', 'ms', 's', 'd'}
ALIASES = {'seconds': 's', 'secs': 's', 'milliseconds': 'ms', 'microseconds': 'us', 'nanoseconds': 'ns', 'days': 'd'}

time_unit = ALIASES.get(time_unit, time_unit)
if time_unit not in VALID_EPOCH_UNITS:
    raise ValueError(f'time_unit must be one of {sorted(VALID_EPOCH_UNITS)}')
expr = pl.col('ts').dt.epoch(time_unit)

Type guard

from typing import Literal, TypeGuard

EpochUnit = Literal['ns', 'us', 'ms', 's', 'd']

def is_epoch_unit(v: str) -> TypeGuard[EpochUnit]:
    return v in ('ns', 'us', 'ms', 's', 'd')

Prevention

When it happens

Trigger: pl.col('ts').dt.epoch('sec'), .dt.epoch('seconds'), .dt.epoch('minutes'), or .dt.epoch('h') — anything outside {'ns','us','ms','s','d'}.

Common situations: Porting pandas/numpy unit conventions ('s' vs 'seconds'); unit strings sourced from user input or config and passed through unvalidated; assuming hours are supported.

Related errors


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