feat(material-temporal-adapter): add Temporal API date adapter #32668
+5,450
−0
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.
AI assistance disclosure
This work was implemented by AI tools (Claude Opus 4.5 and GPT-5.2-Codex) under my orchestration.
Summary
Add a Temporal-based
DateAdapterfor Angular Material datepicker, supporting date-only, date+time, and timezone-aware date+time use cases.Fixes #25753
Background
Temporal is a Stage 3 TC39 proposal providing immutable date/time primitives with explicit calendar and timezone semantics. This adapter enables Material datepicker to work with Temporal (native or polyfilled) without relying on JS
Dateas the internal model. The implementation follows patterns from existing adapters in this repo, especiallyNativeDateAdapter.What’s in this PR
Adapter(s)
Unified adapter:
TemporalDateAdapterwithmode:date→Temporal.PlainDatedatetime→Temporal.PlainDateTimezoned→Temporal.ZonedDateTimeSplit adapters (API ergonomics; supports common “plain vs zoned” consumption patterns). Both unified and split versions are included so the team can choose the preferred public API shape:
PlainTemporalAdapterwithmode: 'date' | 'datetime'(PlainDate + PlainDateTime)ZonedDateTimeAdapterwith configurabletimezoneConfiguration
Unified adapter (
TemporalDateAdapter/MatTemporalDateAdapterOptions)calendar(default:iso8601): calendar system to use for calculations/formatting.mode(default:date): selectsPlainDate,PlainDateTime, orZonedDateTime.timezone(zoned mode only; default: system timezone): IANA ID likeEurope/WarsaworUTC.firstDayOfWeek(default: locale-derived): overrides the locale-derived week start.overflow(default:reject): strict vs constrained date creation.Split adapters
PlainTemporalAdapterOptions(forPlainTemporalAdapter)mode(default:datetime):date(PlainDate) ordatetime(PlainDateTime).calendar(default:iso8601): calendar system for calculations/formatting.firstDayOfWeek(default: locale-derived): overrides the locale-derived week start.overflow(default:reject): strict vs constrained date creation.ZonedDateTimeAdapterOptions(forZonedDateTimeAdapter)calendar(default:iso8601): calendar system for calculations/formatting.timezone(default: system timezone): IANA ID likeEurope/WarsaworUTC.firstDayOfWeek(default: locale-derived): overrides the locale-derived week start.overflow(default:reject): strict vs constrained date creation.Usage examples
Comparison to other adapters
DateAdaptercontract asNativeDateAdapter,MomentDateAdapter,LuxonDateAdapter, andDateFnsAdapter.Intl.DateTimeFormatOptionsfor display formatting, likeNativeDateAdapter, but the backing values are Temporal types instead ofDate.Migration patterns
NativeDateAdapter(Date): switch toprovideTemporalDateAdapter({mode: 'date'})and replaceDatevalues withTemporal.PlainDate(e.g.Temporal.PlainDate.from('2024-01-15')).MomentDateAdapter/LuxonDateAdapter(date+time): usemode: 'datetime'and replace values withTemporal.PlainDateTime(e.g.Temporal.PlainDateTime.from('2024-01-15T12:30')).mode: 'zoned'and providetimezone(e.g.{mode: 'zoned', timezone: 'UTC'}), replacing values withTemporal.ZonedDateTime(e.g.Temporal.ZonedDateTime.from('2024-01-15T12:30[UTC]')).PlainTemporalAdapterorZonedDateTimeAdapter) to keep the date type explicit in APIs and templates.MAT_DATE_FORMATS, ensure they areIntl.DateTimeFormatOptions(Temporal ignores parse formats and parses ISO strings only). Supporting custom parse formats would require a custom parsing implementation in the adapter.Example (custom display formats):
MAT token notes
MAT_DATE_LOCALE: locale string used for formatting and week info.MAT_DATE_FORMATS: must beIntl.DateTimeFormatOptions(parse formats ignored).Option mapping (approximate)
mode: 'date'PlainDateis the closest analogue toDatefor date-only use.useUtc: truemode: 'zoned', timezone: 'UTC'strict: trueoverflow: 'reject'overflowcontrols invalid date creation.useUtc: truemode: 'zoned', timezone: 'UTC'firstDayOfWeekfirstDayOfWeekdefaultOutputCalendarcalendarMAT_DATE_LOCALE+MAT_DATE_FORMATSNotable design choices / dilemmas (with resolution)
1) Temporal typings source (TypeScript not shipping them yet)
TypeScript does not currently ship
lib.esnext.temporalin the version used here, so this PR includes local declarations to type the adapter until the repo upgrades to a TS version that includes Temporal libs.Reference: microsoft/TypeScript#62628
2) API Extractor goldens
API Extractor had trouble resolving the global
Temporalnamespace in this setup. Additionally, existing adapter packages (moment/luxon/date-fns) don’t have API goldens. For consistency and to avoid introducing a blocked/flaky step, this PR does not add API golden coverage for this adapter package.3) Formatting implementation note
Intl.DateTimeFormatis used for localization (same overall approach as other adapters). Zoned values are formatted using the configured timezone.Tests
modevariants and timezone behavior, plus creation/parsing/formatting/time operations.pnpm test src/material-temporal-adapteron Chrome/Chromium 144.islamiccalendar is not supported by the current Temporal implementation).PlainTemporalAdapter,ZonedDateTimeAdapter) are not explicitly covered by a dedicated spec yet.Open questions (feedback requested)
calendarasstring(max flexibility) vs trying to constrain it (risk of being incomplete/locale-dependent).modebe required for the unified adapter (no implicit default), or keep the defaultdatemode?