Skip to content

Rebase up to December 2024 #317

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
97f28b7
Polyfill: Fix IsOffsetTimeZoneIdentifier to not accept sub-minute off…
ptomato Oct 3, 2024
fd5f5bc
Tighten validation of offset string and month code in property bags
ptomato Oct 3, 2024
88e70d1
Polyfill: Fix definitions of hasDateOptions and hasTimeOptions
ptomato Oct 3, 2024
faae66b
Throw TypeError if no overlap between options and Temporal object
ptomato Oct 3, 2024
084aec7
Avoid formatting irrelevant parts of dateStyle/timeStyle for Temporal…
ptomato Oct 4, 2024
e14225b
Update test262
ptomato Oct 7, 2024
526e5c4
Editorial: Add ISODateWithinLimits check to CalendarMonthDayFromFields
ptomato Oct 8, 2024
3b7f3a9
Editorial: Second argument to CalendarExtraFields is only a List
ptomato Oct 8, 2024
86103a9
Editorial: Give field names lists to PrepareCalendarFields in table o…
ptomato Oct 8, 2024
fdaf227
Editorial: Abstract days range check into CheckISODaysRange
ptomato Oct 8, 2024
796be68
Polyfill: Refactor GetUTCEpochMilliseconds to use ISO Date-Time Record
ptomato Oct 8, 2024
5ed4c32
Polyfill: Use object spreading for readability
ptomato Oct 8, 2024
5907fd6
Editorial: Rename "normalized duration" to "internal duration"
ptomato Oct 8, 2024
8a19d02
Editorial: Rename UnnormalizeDuration to TemporalDurationFromInternal
ptomato Oct 8, 2024
6a0682a
Editorial: Rename UnbalanceDateDurationRelative to DateDurationDays
ptomato Oct 8, 2024
b426058
Editorial: Rename Normalized Time Duration to time duration
ptomato Oct 8, 2024
f4bf0cd
Editorial: Merge SubtractTimeDuration into AddTimeDuration
ptomato Oct 8, 2024
8e6d920
Use `Intl.LocalesArgument` in signature of `toLocaleString` methods
fabon-f Oct 23, 2024
51496f9
Polyfill: Implement previous commit in reference code
ptomato Nov 1, 2024
202aeaa
Polyfill: Make Date.prototype.toTemporalInstant not a constructor
ptomato Nov 8, 2024
1798441
Update test262
ptomato Nov 7, 2024
e02de94
Polyfill: Implement ISODateTimeWithinLimits assertions
ptomato Oct 26, 2024
7f5494b
Editorial: Rename roundedNorm/diffNorm to roundedTime/diffTime
ptomato Oct 26, 2024
ef8cd3a
Editorial: Merge DivideTimeDuration into TotalTimeDuration
ptomato Oct 26, 2024
ba8fb6c
Editorial: Remove use of nonexistent [[TotalNanoseconds]] field
ptomato Oct 26, 2024
7f62b59
Update test262
ptomato Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,9 @@ export namespace Temporal {
*/
export type TransitionDirection = 'next' | 'previous' | { direction: 'next' | 'previous' };

// Handle Intl.LocalesArgument regardless of whether the TS version has it yet
type LocalesArgument = ConstructorParameters<typeof Intl.DateTimeFormat>[0];

export type DurationLike = {
years?: number;
months?: number;
Expand Down Expand Up @@ -552,7 +555,7 @@ export namespace Temporal {
subtract(other: Temporal.Duration | DurationLike | string): Temporal.Duration;
round(roundTo: DurationRoundTo): Temporal.Duration;
total(totalOf: DurationTotalOf): number;
toLocaleString(locales?: string | string[], options?: globalThis.Intl.DateTimeFormatOptions): string;
toLocaleString(locales?: LocalesArgument, options?: globalThis.Intl.DateTimeFormatOptions): string;
toJSON(): string;
toString(options?: ToStringPrecisionOptions): string;
valueOf(): never;
Expand Down Expand Up @@ -600,7 +603,7 @@ export namespace Temporal {
roundTo: RoundTo<'hour' | 'minute' | 'second' | 'millisecond' | 'microsecond' | 'nanosecond'>
): Temporal.Instant;
toZonedDateTimeISO(tzLike: TimeZoneLike): Temporal.ZonedDateTime;
toLocaleString(locales?: string | string[], options?: globalThis.Intl.DateTimeFormatOptions): string;
toLocaleString(locales?: LocalesArgument, options?: globalThis.Intl.DateTimeFormatOptions): string;
toJSON(): string;
toString(options?: InstantToStringOptions): string;
valueOf(): never;
Expand Down Expand Up @@ -678,7 +681,7 @@ export namespace Temporal {
): Temporal.ZonedDateTime;
toPlainYearMonth(): Temporal.PlainYearMonth;
toPlainMonthDay(): Temporal.PlainMonthDay;
toLocaleString(locales?: string | string[], options?: globalThis.Intl.DateTimeFormatOptions): string;
toLocaleString(locales?: LocalesArgument, options?: globalThis.Intl.DateTimeFormatOptions): string;
toJSON(): string;
toString(options?: ShowCalendarOption): string;
valueOf(): never;
Expand Down Expand Up @@ -781,7 +784,7 @@ export namespace Temporal {
toZonedDateTime(tzLike: TimeZoneLike, options?: ToInstantOptions): Temporal.ZonedDateTime;
toPlainDate(): Temporal.PlainDate;
toPlainTime(): Temporal.PlainTime;
toLocaleString(locales?: string | string[], options?: globalThis.Intl.DateTimeFormatOptions): string;
toLocaleString(locales?: LocalesArgument, options?: globalThis.Intl.DateTimeFormatOptions): string;
toJSON(): string;
toString(options?: CalendarTypeToStringOptions): string;
valueOf(): never;
Expand Down Expand Up @@ -817,7 +820,7 @@ export namespace Temporal {
equals(other: Temporal.PlainMonthDay | PlainMonthDayLike | string): boolean;
with(monthDayLike: PlainMonthDayLike, options?: AssignmentOptions): Temporal.PlainMonthDay;
toPlainDate(year: { year: number }): Temporal.PlainDate;
toLocaleString(locales?: string | string[], options?: globalThis.Intl.DateTimeFormatOptions): string;
toLocaleString(locales?: LocalesArgument, options?: globalThis.Intl.DateTimeFormatOptions): string;
toJSON(): string;
toString(options?: ShowCalendarOption): string;
valueOf(): never;
Expand Down Expand Up @@ -883,7 +886,7 @@ export namespace Temporal {
round(
roundTo: RoundTo<'hour' | 'minute' | 'second' | 'millisecond' | 'microsecond' | 'nanosecond'>
): Temporal.PlainTime;
toLocaleString(locales?: string | string[], options?: globalThis.Intl.DateTimeFormatOptions): string;
toLocaleString(locales?: LocalesArgument, options?: globalThis.Intl.DateTimeFormatOptions): string;
toJSON(): string;
toString(options?: ToStringPrecisionOptions): string;
valueOf(): never;
Expand Down Expand Up @@ -952,7 +955,7 @@ export namespace Temporal {
options?: DifferenceOptions<'year' | 'month'>
): Temporal.Duration;
toPlainDate(day: { day: number }): Temporal.PlainDate;
toLocaleString(locales?: string | string[], options?: globalThis.Intl.DateTimeFormatOptions): string;
toLocaleString(locales?: LocalesArgument, options?: globalThis.Intl.DateTimeFormatOptions): string;
toJSON(): string;
toString(options?: ShowCalendarOption): string;
valueOf(): never;
Expand Down Expand Up @@ -1046,7 +1049,7 @@ export namespace Temporal {
toPlainDateTime(): Temporal.PlainDateTime;
toPlainDate(): Temporal.PlainDate;
toPlainTime(): Temporal.PlainTime;
toLocaleString(locales?: string | string[], options?: globalThis.Intl.DateTimeFormatOptions): string;
toLocaleString(locales?: LocalesArgument, options?: globalThis.Intl.DateTimeFormatOptions): string;
toJSON(): string;
toString(options?: ZonedDateTimeToStringOptions): string;
valueOf(): never;
Expand Down
10 changes: 6 additions & 4 deletions lib/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export interface CalendarImpl {
monthDayToISOReferenceDate(fields: ResolveFieldsReturn<'month-day'>, overflow: Overflow): ISODate;
dateAdd(date: ISODate, duration: Partial<DateDuration>, overflow: Overflow): ISODate;
dateUntil(one: ISODate, two: ISODate, largestUnit: 'year' | 'month' | 'week' | 'day'): DateDuration;
extraFields(): FieldKey[];
extraFields(fields: FieldKey[]): FieldKey[];
fieldKeysToIgnore(keys: FieldKey[]): FieldKey[];
}

Expand Down Expand Up @@ -2267,9 +2267,11 @@ class DangiHelper extends ChineseBaseHelper {
*/
class NonIsoCalendar implements CalendarImpl {
constructor(private readonly helper: HelperBase) {}
extraFields(type: ISODateToFieldsType = 'date'): FieldKey[] {
if (type === 'month-day') return [];
return ['era', 'eraYear'];
extraFields(fields: FieldKey[]): FieldKey[] {
if (this.helper.hasEra && Call(ArrayPrototypeIncludes, fields, ['year'])) {
return ['era', 'eraYear'];
}
return [];
}
resolveFields(fields: CalendarFieldsRecord /* , type */) {
if (this.helper.calendarType !== 'lunisolar') {
Expand Down
61 changes: 38 additions & 23 deletions lib/duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
SetSlot,
TIME_ZONE
} from './slots';
import { TimeDuration } from './timeduration';
import type { Temporal } from '..';
import type { DurationParams as Params, DurationReturn as Return } from './internaltypes';
import JSBI from 'jsbi';
Expand Down Expand Up @@ -230,7 +231,7 @@ export class Duration implements Temporal.Duration {
}

if (zonedRelativeTo) {
let duration = ES.NormalizeDuration(this);
let duration = ES.ToInternalDurationRecord(this);
const timeZone = GetSlot(zonedRelativeTo, TIME_ZONE);
const calendar = GetSlot(zonedRelativeTo, CALENDAR);
const relativeEpochNs = GetSlot(zonedRelativeTo, EPOCHNANOSECONDS);
Expand All @@ -246,12 +247,12 @@ export class Duration implements Temporal.Duration {
roundingMode
);
if (ES.TemporalUnitCategory(largestUnit) === 'date') largestUnit = 'hour';
return ES.UnnormalizeDuration(duration, largestUnit);
return ES.TemporalDurationFromInternal(duration, largestUnit);
}

if (plainRelativeTo) {
let duration = ES.NormalizeDurationWith24HourDays(this);
const targetTime = ES.AddTime(ES.MidnightTimeRecord(), duration.norm);
let duration = ES.ToInternalDurationRecordWith24HourDays(this);
const targetTime = ES.AddTime(ES.MidnightTimeRecord(), duration.time);

// Delegate the date part addition to the calendar
const isoRelativeToDate = GetSlot(plainRelativeTo, ISO_DATE);
Expand All @@ -270,7 +271,7 @@ export class Duration implements Temporal.Duration {
smallestUnit,
roundingMode
);
return ES.UnnormalizeDuration(duration, largestUnit);
return ES.TemporalDurationFromInternal(duration, largestUnit);
}

// No reference date to calculate difference relative to
Expand All @@ -281,9 +282,19 @@ export class Duration implements Temporal.Duration {
throw new RangeErrorCtor(`a starting point is required for ${largestUnit}s balancing`);
}
assert(!ES.IsCalendarUnit(smallestUnit), 'smallestUnit was larger than largestUnit');
let duration = ES.NormalizeDurationWith24HourDays(this);
duration = ES.RoundTimeDuration(duration, roundingIncrement, smallestUnit, roundingMode);
return ES.UnnormalizeDuration(duration, largestUnit);
let internalDuration = ES.ToInternalDurationRecordWith24HourDays(this);
if (smallestUnit === 'day') {
// First convert time units up to days
const { quotient, remainder } = internalDuration.time.divmod(ES.DAY_NANOS);
let days = internalDuration.date.days + quotient + ES.TotalTimeDuration(remainder, 'day');
days = ES.RoundNumberToIncrement(days, roundingIncrement, roundingMode);
const dateDuration = { years: 0, months: 0, weeks: 0, days };
internalDuration = ES.CombineDateAndTimeDuration(dateDuration, TimeDuration.ZERO);
} else {
const timeDuration = ES.RoundTimeDuration(internalDuration.time, roundingIncrement, smallestUnit, roundingMode);
internalDuration = ES.CombineDateAndTimeDuration(ES.ZeroDateDuration(), timeDuration);
}
return ES.TemporalDurationFromInternal(internalDuration, largestUnit);
}
total(optionsParam: Params['total'][0]): Return['total'] {
if (!ES.IsTemporalDuration(this)) throw new TypeErrorCtor('invalid receiver');
Expand All @@ -297,7 +308,7 @@ export class Duration implements Temporal.Duration {
const unit = ES.GetTemporalUnitValuedOption(options, 'unit', 'datetime', ES.REQUIRED);

if (zonedRelativeTo) {
const duration = ES.NormalizeDuration(this);
const duration = ES.ToInternalDurationRecord(this);
const timeZone = GetSlot(zonedRelativeTo, TIME_ZONE);
const calendar = GetSlot(zonedRelativeTo, CALENDAR);
const relativeEpochNs = GetSlot(zonedRelativeTo, EPOCHNANOSECONDS);
Expand All @@ -306,8 +317,8 @@ export class Duration implements Temporal.Duration {
}

if (plainRelativeTo) {
const duration = ES.NormalizeDurationWith24HourDays(this);
let targetTime = ES.AddTime(ES.MidnightTimeRecord(), duration.norm);
const duration = ES.ToInternalDurationRecordWith24HourDays(this);
let targetTime = ES.AddTime(ES.MidnightTimeRecord(), duration.time);

// Delegate the date part addition to the calendar
const isoRelativeToDate = GetSlot(plainRelativeTo, ISO_DATE);
Expand All @@ -328,8 +339,8 @@ export class Duration implements Temporal.Duration {
if (ES.IsCalendarUnit(unit)) {
throw new RangeErrorCtor(`a starting point is required for ${unit}s total`);
}
const duration = ES.NormalizeDurationWith24HourDays(this);
return ES.TotalTimeDuration(duration.norm, unit);
const duration = ES.ToInternalDurationRecordWith24HourDays(this);
return ES.TotalTimeDuration(duration.time, unit);
}
toString(options: Params['toString'][0] = undefined): string {
if (!ES.IsTemporalDuration(this)) throw new TypeErrorCtor('invalid receiver');
Expand All @@ -349,9 +360,13 @@ export class Duration implements Temporal.Duration {
if (unit === 'nanosecond' && increment === 1) return ES.TemporalDurationToString(this, precision);

const largestUnit = ES.DefaultTemporalLargestUnit(this);
let duration = ES.NormalizeDuration(this);
duration = ES.RoundTimeDuration(duration, increment, unit, roundingMode);
const roundedDuration = ES.UnnormalizeDuration(duration, ES.LargerOfTwoTemporalUnits(largestUnit, 'second'));
let internalDuration = ES.ToInternalDurationRecord(this);
const timeDuration = ES.RoundTimeDuration(internalDuration.time, increment, unit, roundingMode);
internalDuration = ES.CombineDateAndTimeDuration(internalDuration.date, timeDuration);
const roundedDuration = ES.TemporalDurationFromInternal(
internalDuration,
ES.LargerOfTwoTemporalUnits(largestUnit, 'second')
);
return ES.TemporalDurationToString(roundedDuration, precision);
}
toJSON(): Return['toJSON'] {
Expand Down Expand Up @@ -402,8 +417,8 @@ export class Duration implements Temporal.Duration {

const largestUnit1 = ES.DefaultTemporalLargestUnit(one);
const largestUnit2 = ES.DefaultTemporalLargestUnit(two);
const duration1 = ES.NormalizeDuration(one);
const duration2 = ES.NormalizeDuration(two);
const duration1 = ES.ToInternalDurationRecord(one);
const duration2 = ES.ToInternalDurationRecord(two);

if (
zonedRelativeTo &&
Expand All @@ -424,12 +439,12 @@ export class Duration implements Temporal.Duration {
if (!plainRelativeTo) {
throw new RangeErrorCtor('A starting point is required for years, months, or weeks comparison');
}
d1 = ES.UnbalanceDateDurationRelative(duration1.date, plainRelativeTo);
d2 = ES.UnbalanceDateDurationRelative(duration2.date, plainRelativeTo);
d1 = ES.DateDurationDays(duration1.date, plainRelativeTo);
d2 = ES.DateDurationDays(duration2.date, plainRelativeTo);
}
const norm1 = duration1.norm.add24HourDays(d1);
const norm2 = duration2.norm.add24HourDays(d2);
return norm1.cmp(norm2);
const timeDuration1 = duration1.time.add24HourDays(d1);
const timeDuration2 = duration2.time.add24HourDays(d2);
return timeDuration1.cmp(timeDuration2);
}
[Symbol.toStringTag]!: 'Temporal.Duration';
}
Expand Down
Loading