Skip to content

Commit 9ec5c81

Browse files
committed
refactor(material-temporal-adapter): use native Temporal types
- Replace custom TemporalDateType interface with union type of native Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime - Update temporal.d.ts to match TC39 spec and TypeScript PR #62628 (microsoft/TypeScript#62628) - Types match MDN documentation and Chrome 144/Firefox 139 implementations - Add _invalid marker to sentinel object for explicit invalid detection - Adapter uses global Temporal namespace without polyfill dependency - Polyfill (@js-temporal/polyfill) is only used in tests
1 parent a46964b commit 9ec5c81

2 files changed

Lines changed: 352 additions & 233 deletions

File tree

src/material-temporal-adapter/adapter/temporal-date-adapter.ts

Lines changed: 14 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -33,77 +33,13 @@ export type TemporalCalendarId = string;
3333

3434
/**
3535
* Represents a date in the Temporal API format.
36-
* This interface is compatible with `Temporal.PlainDate`, `Temporal.PlainDateTime`,
37-
* and `Temporal.ZonedDateTime`.
38-
*
39-
* The interface provides read-only access to date components and includes methods
40-
* for date manipulation. When used with the TemporalDateAdapter, instances will be
41-
* actual `Temporal.PlainDate`, `Temporal.PlainDateTime`, or `Temporal.ZonedDateTime` objects.
36+
* Can be a PlainDate, PlainDateTime, or ZonedDateTime depending on the adapter mode.
4237
*
4338
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate
4439
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime
4540
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime
4641
*/
47-
export interface TemporalDateType {
48-
/** The year component (may be negative for BCE dates). */
49-
readonly year: number;
50-
/** The month component (1-12). */
51-
readonly month: number;
52-
/** The day of month component (1-31). */
53-
readonly day: number;
54-
/**
55-
* The calendar system identifier used by this date.
56-
* This is the standard property in the current Temporal spec.
57-
*/
58-
readonly calendarId?: string;
59-
/** The day of the week (1-7, where 1 is Monday). */
60-
readonly dayOfWeek: number;
61-
/** The number of days in the month. */
62-
readonly daysInMonth: number;
63-
/** The number of months in the year. */
64-
readonly monthsInYear: number;
65-
66-
// Optional time components (present in PlainDateTime and ZonedDateTime)
67-
/** The hour component (0-23). Only present in PlainDateTime/ZonedDateTime. */
68-
readonly hour?: number;
69-
/** The minute component (0-59). Only present in PlainDateTime/ZonedDateTime. */
70-
readonly minute?: number;
71-
/** The second component (0-59). Only present in PlainDateTime/ZonedDateTime. */
72-
readonly second?: number;
73-
/** The millisecond component (0-999). Only present in PlainDateTime/ZonedDateTime. */
74-
readonly millisecond?: number;
75-
76-
// Optional timezone components (present in ZonedDateTime)
77-
/** The timezone identifier. Only present in ZonedDateTime. */
78-
readonly timeZoneId?: string;
79-
80-
/**
81-
* Returns a new date with the specified duration added.
82-
* @param duration The duration to add (e.g., `{years: 1}`, `{months: 2}`, `{days: 7}`).
83-
*/
84-
add(duration: {years?: number; months?: number; days?: number}): TemporalDateType;
85-
86-
/**
87-
* Returns a new PlainDateTime from this date with the specified time.
88-
* @param time The time components to use.
89-
*/
90-
toPlainDateTime?(time: {
91-
hour?: number;
92-
minute?: number;
93-
second?: number;
94-
millisecond?: number;
95-
}): TemporalDateType;
96-
97-
/**
98-
* Returns a string representation of this date.
99-
*/
100-
toString(): string;
101-
102-
/**
103-
* Returns true if this date equals the other date.
104-
*/
105-
equals(other: TemporalDateType): boolean;
106-
}
42+
export type TemporalDateType = Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime;
10743

10844
/**
10945
* Mode for the Temporal adapter - determines which type is used internally.
@@ -405,12 +341,13 @@ export class TemporalDateAdapter extends DateAdapter<TemporalDateType> {
405341
/** Clones the given date. */
406342
clone(date: TemporalDateType): TemporalDateType {
407343
if (this._isZonedDateTime(date)) {
408-
return Temporal.ZonedDateTime.from(this._toZonedDateTime(date));
344+
// Use toString() to clone - from() accepts string
345+
return Temporal.ZonedDateTime.from(date.toString());
409346
}
410347
if (this._isPlainDateTime(date)) {
411-
return Temporal.PlainDateTime.from(this._toPlainDateTime(date));
348+
return Temporal.PlainDateTime.from(date.toString());
412349
}
413-
return Temporal.PlainDate.from(this._toPlainDate(date));
350+
return Temporal.PlainDate.from(date.toString());
414351
}
415352

416353
/**
@@ -728,7 +665,10 @@ export class TemporalDateAdapter extends DateAdapter<TemporalDateType> {
728665
/** Checks whether the given date is valid. */
729666
isValid(date: TemporalDateType): boolean {
730667
// Temporal doesn't create invalid dates - it throws instead.
731-
// Our invalid() returns a sentinel object with NaN values.
668+
// Our invalid() returns a sentinel object with NaN values and _invalid marker.
669+
if ((date as {_invalid?: boolean})._invalid === true) {
670+
return false;
671+
}
732672
return date != null && typeof date.year === 'number' && !isNaN(date.year);
733673
}
734674

@@ -744,8 +684,9 @@ export class TemporalDateAdapter extends DateAdapter<TemporalDateType> {
744684
*/
745685
invalid(): TemporalDateType {
746686
// Temporal doesn't support invalid dates like Date(NaN).
747-
// Return minimal sentinel with NaN year - isValid() checks this.
687+
// Return sentinel with _invalid marker and NaN values.
748688
const baseInvalid = {
689+
_invalid: true as const,
749690
year: NaN,
750691
month: NaN,
751692
day: NaN,
@@ -1090,15 +1031,15 @@ export class TemporalDateAdapter extends DateAdapter<TemporalDateType> {
10901031
if (this._isZonedDateTime(date)) {
10911032
return this._toZonedDateTime(date).toPlainDateTime();
10921033
}
1093-
return date as Temporal.PlainDateTime;
1034+
return date as unknown as Temporal.PlainDateTime;
10941035
}
10951036

10961037
/**
10971038
* Converts a TemporalDateType to Temporal.ZonedDateTime for internal use.
10981039
* This is needed because our public interface doesn't expose Temporal types directly.
10991040
*/
11001041
private _toZonedDateTime(date: TemporalDateType): Temporal.ZonedDateTime {
1101-
return date as Temporal.ZonedDateTime;
1042+
return date as unknown as Temporal.ZonedDateTime;
11021043
}
11031044

11041045
/**

0 commit comments

Comments
 (0)