feat(is_dst): real per-backend implementation (item 65) - #291
Merged
Conversation
- require timezone at build time (InvalidOptionValueError when omitted) - protocol/backend signatures tightened to timezone: str (no default) - polars: native dt.convert_time_zone + dt.dst_offset() != 0 - narwhals: hand-rolled two-reference-offset algorithm (no native dst_offset equivalent); avoids the narwhals 2.24.0 + pandas 3.0.5 chained-convert_time_zone bug for America/New_York and America/Los_Angeles by never deriving utc_naive by converting back from local_naive - ibis: declared_unsupported (no DST/timezone-offset primitive at all); new is_dst.timezone UNSUPPORTED capability fact on ibis family-default + ibis-duckdb - new cross-backend test file, 11 cases, all passing (7 temporal backends x hemisphere pairs + 3 ibis capability-gate cases) - fixed two pre-existing tests written for the old permissive no-arg/placeholder behavior (test_is_dst_builder_validation, test_remaining_ops_results docstring)
…zone (item 65)
- add IS_DST smoke override (America/New_York UTC pair) to _smoke_helpers.py
so the generic introspection-driven smoke/reachability/signature-conformance
suites synthesize a valid IANA timezone instead of the generic 'x' placeholder
- register is_dst.timezone in the disposition-matrix open-value domains
(option_disposition.py OPTION_DTYPES + _MA_OPTION_VALUE_DOMAINS), mirroring
to_timezone exactly (same value class, same ibis-unsupported shape)
- add a full is_dst OptionCell/OptionProbeRegistration/InvalidOptionRejection
registration section to test_arg_types_datetime.py so the new ibis capability
fact is backed by a declared disposition cell, and every (backend, timezone)
combination gets a runtime probe assertion
- fix test_is_dst AST test and test_is_dst_builder_validation (cross_backend)
to pass the now-required timezone argument
- regenerate docs/reference/expression-coverage.{md,json} + scoped variant
for the new is_dst.timezone ibis capability fact
- ruff --fix: drop unused Optional imports in the four is_dst signature files
Full suite: 22543 passed, 0 failed. ruff clean. mypy: 97 pre-existing
import-untyped/found-twice baseline errors only, no errors in touched code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the
is_dstplaceholder (return Falseon every backend) with a real per-backend implementation, gated by a capability fact.timezoneis now required —is_dst()with no timezone raisesInvalidOptionValueError.dt.convert_time_zone(tz).dt.dst_offset() != 0.dst_offsetequivalent); verified againstzoneinfoacross 7 zones, both hemispheres, on narwhals-polars and narwhals-pandas. Constructed to avoid a narwhals 2.24.0 + pandas 3.0.5 bug where a secondconvert_time_zonechained onto aAmerica/New_York/America/Los_Angeles-targeted expression raisesAttributeError.declared_unsupported— no DST/timezone-offset primitive exists at all. Enforced via a newis_dst.timezoneCapabilityFact(family default +ibis-duckdb).Spec / Plan
mountainash-central/.../specs/2026-08-15-is-dst-real-implementation-design.md(rev 2, adversarially reviewed + empirically verified against pinned library versions)mountainash-central/.../plans/2026-08-15-is-dst-real-implementation.md(rev 2, 6 tasks)Verification
tests/expressions/cross_backend/test_datetime_is_dst.py: 11 cases (7 temporal backends × hemisphere pairs + 3 ibis capability-gate cases), all passing.ruff check: clean.mypy: only pre-existing baselineimport-untyped/found-twicenoise, no errors in touched code.docs/reference/expression-coverage.{md,json}for the new capability fact.🤖 Generated with SDD (spec → plan → execute)