feat(material-temporal-adapter): add Temporal API date adapter #32668
+6,293
−16
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.Scope / what’s in this PR
TemporalDateAdapterwithmode:date→Temporal.PlainDatedatetime→Temporal.PlainDateTimezoned→Temporal.ZonedDateTimePlainTemporalAdapterwithmode: 'date' | 'datetime'(PlainDate + PlainDateTime)ZonedDateTimeAdapterwith configurabletimezoneIntl.DateTimeFormatOptionswith Temporal’s locale formatting.Configuration
Unified adapter (
TemporalDateAdapter/MatTemporalDateAdapterOptions)Defaults
calendar:iso8601outputCalendar: same ascalendarmode:dateoverflow:rejecttimezone: system timezone (only whenmode: 'zoned')disambiguation,offset,rounding: Temporal defaults (only whenmode: 'zoned')Options
calendar: calendar system to use for calculations.outputCalendar: calendar system to use for output/formatting when different from calculations (MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate/withCalendar, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/withCalendar).mode:date | datetime | zoned.timezone(zoned only): IANA ID likeEurope/WarsaworUTC.disambiguation(zoned only):'compatible' | 'earlier' | 'later' | 'reject'for DST gaps/overlaps (MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime/toZonedDateTime, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/from).offset(zoned only):'use' | 'ignore' | 'reject' | 'prefer'for offset ambiguity on parse (MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/from).rounding(zoned only):{smallestUnit, roundingIncrement?, roundingMode?}applied to zoned output (MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/round).firstDayOfWeek: overrides the locale-derived week start.overflow:rejectthrows on invalid dates,constrainclamps to the nearest valid date.Notes
outputCalendaruseswithCalendarfor display fields only; it does not re-resolve the instant, sodisambiguation/offsetare not applied during output conversion.disambiguation,offset, orroundingaren’t provided, the adapter relies on Temporal’s defaults.overflowdefaults torejectto avoid silent clamping and better match strict validation expectations.Split adapters
PlainTemporalAdapterOptions(forPlainTemporalAdapter)mode(default:datetime):date→PlainDate,datetime→PlainDateTime.calendar(default:iso8601): calendar system for calculations.outputCalendar(default: same ascalendar): calendar system for output/formatting.firstDayOfWeek(default: locale-derived): overrides the locale-derived week start.overflow(default:reject):rejectthrows on invalid dates,constrainclamps.ZonedDateTimeAdapterOptions(forZonedDateTimeAdapter)calendar(default:iso8601): calendar system for calculations.outputCalendar(default: same ascalendar): calendar system for output/formatting (MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/withCalendar).timezone(default: system timezone): IANA ID likeEurope/WarsaworUTC.disambiguation:'compatible' | 'earlier' | 'later' | 'reject'for DST gaps/overlaps (MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime/toZonedDateTime, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/from).offset:'use' | 'ignore' | 'reject' | 'prefer'for offset ambiguity on parse (MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/from).rounding:{smallestUnit, roundingIncrement?, roundingMode?}applied to zoned output (MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/round).firstDayOfWeek(default: locale-derived): overrides the locale-derived week start.overflow(default:reject):rejectthrows on invalid dates,constrainclamps.Examples
Unified adapter option examples
calendaroutputCalendarmodeTemporal.PlainDateTime.timezonedisambiguationoffsetroundingfirstDayOfWeekoverflowForm control example (overflow)
Effect: the value is clamped to the last valid day of the month (e.g. 2024-02-29) instead of throwing.
Split adapter option examples
Usage examples
Migration patterns
NativeDateAdapter(Date): switch tomode: 'date', replaceDatewithTemporal.PlainDate. If you rely on timezone/time-of-day behavior, usemode: 'zoned'with the system timezone instead.MomentDateAdapter/LuxonDateAdapter(date+time): usemode: 'datetime', replace values withTemporal.PlainDateTime.mode: 'zoned'+timezone, replace values withTemporal.ZonedDateTime.defaultOutputCalendar: keepcalendarfor calculations, setoutputCalendarfor display.disambiguation,offset, androundinginzonedmode.PlainTemporalAdapterorZonedDateTimeAdapter).MAT_DATE_FORMATS, ensure they areIntl.DateTimeFormatOptions(Temporal ignores parse formats and parses ISO strings only).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).Comparison and mapping
DateAdaptercontract asNativeDateAdapter,MomentDateAdapter,LuxonDateAdapter, andDateFnsAdapter.Intl.DateTimeFormatOptionsfor display formatting (likeNativeDateAdapter), but the backing values are Temporal types instead ofDate.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'firstDayOfWeekfirstDayOfWeekdefaultOutputCalendaroutputCalendarcalendar).MAT_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-adapter --no-watchon Chromium (local).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?overflowdefault toreject(strict) or align with Temporal’sconstraindefault?