Repository: denoland/deno
Pull request: BREAKING(temporal/unstable): Remove obsoleted Temporal APIs

<!--
Before submitting a PR, please read https://docs.deno.com/runtime/manual/references/contributing

1. Give the PR a descriptive title.

  Examples of good title:
    - fix(std/http): Fix race condition in server
    - docs(console): Update docstrings
    - feat(doc): Handle nested reexports

  Examples of bad title:
    - fix #7123
    - update docs
    - fix bugs

2. Ensure there is a related issue and it is referenced in the PR text.
3. Ensure there are tests that cover the changes.
4. Ensure `cargo test` passes.
5. Ensure `./tools/format.js` passes without changing files.
6. Ensure `./tools/lint.js` passes.
7. Open as a draft PR if your work is still in progress. The CI won't run
   all steps, but you can add '[ci]' to a commit message to force it to.
8. If you would like to run the benchmarks on the CI, add the 'ci-bench' label.
-->

At the TC39 meeting on 2024-06, [it was decided to obsolete several Temporal APIs](https://github.com/tc39/notes/blob/main/meetings/2024-06/june-12.md#temporal-stage-3-update-and-scope-reduction). I have disabled those APIs that had already been removed from the specification.
Ref https://github.com/tc39/proposal-temporal/pull/2895, https://github.com/tc39/proposal-temporal/pull/2914

`Temporal.TimeZone` and `Temporal.Calendar` are also obsoleted, so I will remove them as well when they are removed from the specification.
Ref https://github.com/tc39/proposal-temporal/pull/2925

Changed files:
filename: cli/tsc/dts/lib.deno.unstable.d.ts
patch: @@ -2606,7 +2606,7 @@ declare namespace Temporal {
   /**
    * When the name of a unit is provided to a Temporal API as a string, it is
    * usually singular, e.g. 'day' or 'hour'. But plural unit names like 'days'
-   * or 'hours' are aso accepted too.
+   * or 'hours' are also accepted.
    *
    * @category Temporal
    * @experimental
@@ -2925,8 +2925,8 @@ declare namespace Temporal {
          * This value must be either a `Temporal.PlainDateTime`, a
          * `Temporal.ZonedDateTime`, or a string or object value that can be
          * passed to `from()` of those types. Examples:
-         * - `'2020-01'01T00:00-08:00[America/Los_Angeles]'`
-         * - `'2020-01'01'`
+         * - `'2020-01-01T00:00-08:00[America/Los_Angeles]'`
+         * - `'2020-01-01'`
          * - `Temporal.PlainDate.from('2020-01-01')`
          *
          * `Temporal.ZonedDateTime` will be tried first because it's more
@@ -2971,8 +2971,8 @@ declare namespace Temporal {
        * This value must be either a `Temporal.PlainDateTime`, a
        * `Temporal.ZonedDateTime`, or a string or object value that can be passed
        * to `from()` of those types. Examples:
-       * - `'2020-01'01T00:00-08:00[America/Los_Angeles]'`
-       * - `'2020-01'01'`
+       * - `'2020-01-01T00:00-08:00[America/Los_Angeles]'`
+       * - `'2020-01-01'`
        * - `Temporal.PlainDate.from('2020-01-01')`
        *
        * `Temporal.ZonedDateTime` will be tried first because it's more
@@ -3007,8 +3007,8 @@ declare namespace Temporal {
      * This value must be either a `Temporal.PlainDateTime`, a
      * `Temporal.ZonedDateTime`, or a string or object value that can be passed
      * to `from()` of those types. Examples:
-     * - `'2020-01'01T00:00-08:00[America/Los_Angeles]'`
-     * - `'2020-01'01'`
+     * - `'2020-01-01T00:00-08:00[America/Los_Angeles]'`
+     * - `'2020-01-01'`
      * - `Temporal.PlainDate.from('2020-01-01')`
      *
      * `Temporal.ZonedDateTime` will be tried first because it's more
@@ -3027,6 +3027,16 @@ declare namespace Temporal {
       | string;
   }
 
+  /**
+   * Options to control behaviour of `ZonedDateTime.prototype.getTimeZoneTransition()`
+   *
+   * @category Temporal
+   * @experimental
+   */
+  export type TransitionDirection = "next" | "previous" | {
+    direction: "next" | "previous";
+  };
+
   /**
    * @category Temporal
    * @experimental
@@ -3127,19 +3137,15 @@ declare namespace Temporal {
    * @experimental
    */
   export class Instant {
-    static fromEpochSeconds(epochSeconds: number): Temporal.Instant;
     static fromEpochMilliseconds(epochMilliseconds: number): Temporal.Instant;
-    static fromEpochMicroseconds(epochMicroseconds: bigint): Temporal.Instant;
     static fromEpochNanoseconds(epochNanoseconds: bigint): Temporal.Instant;
     static from(item: Temporal.Instant | string): Temporal.Instant;
     static compare(
       one: Temporal.Instant | string,
       two: Temporal.Instant | string,
     ): ComparisonResult;
     constructor(epochNanoseconds: bigint);
-    readonly epochSeconds: number;
     readonly epochMilliseconds: number;
-    readonly epochMicroseconds: bigint;
     readonly epochNanoseconds: bigint;
     equals(other: Temporal.Instant | string): boolean;
     add(
@@ -3300,14 +3306,14 @@ declare namespace Temporal {
         | Temporal.PlainDateTime
         | PlainDateLike
         | string,
-    ): number;
+    ): number | undefined;
     yearOfWeek(
       date:
         | Temporal.PlainDate
         | Temporal.PlainDateTime
         | PlainDateLike
         | string,
-    ): number;
+    ): number | undefined;
     daysInWeek(
       date:
         | Temporal.PlainDate
@@ -3476,14 +3482,14 @@ declare namespace Temporal {
         | Temporal.PlainDateTime
         | PlainDateLike
         | string,
-    ): number;
+    ): number | undefined;
     yearOfWeek(
       date:
         | Temporal.PlainDate
         | Temporal.PlainDateTime
         | PlainDateLike
         | string,
-    ): number;
+    ): number | undefined;
     daysInWeek(
       date:
         | Temporal.PlainDate
@@ -3614,11 +3620,10 @@ declare namespace Temporal {
     readonly monthCode: string;
     readonly day: number;
     readonly calendarId: string;
-    getCalendar(): CalendarProtocol;
     readonly dayOfWeek: number;
     readonly dayOfYear: number;
-    readonly weekOfYear: number;
-    readonly yearOfWeek: number;
+    readonly weekOfYear: number | undefined;
+    readonly yearOfWeek: number | undefined;
     readonly daysInWeek: number;
     readonly daysInYear: number;
     readonly daysInMonth: number;
@@ -3755,11 +3760,10 @@ declare namespace Temporal {
     readonly microsecond: number;
     readonly nanosecond: number;
     readonly calendarId: string;
-    getCalendar(): CalendarProtocol;
     readonly dayOfWeek: number;
     readonly dayOfYear: number;
-    readonly weekOfYear: number;
-    readonly yearOfWeek: number;
+    readonly weekOfYear: number | undefined;
+    readonly yearOfWeek: number | undefined;
     readonly daysInWeek: number;
     readonly daysInYear: number;
     readonly daysInMonth: number;
@@ -3773,9 +3777,6 @@ declare namespace Temporal {
     withPlainTime(
       timeLike?: Temporal.PlainTime | PlainTimeLike | string,
     ): Temporal.PlainDateTime;
-    withPlainDate(
-      dateLike: Temporal.PlainDate | PlainDateLike | string,
-    ): Temporal.PlainDateTime;
     withCalendar(calendar: CalendarLike): Temporal.PlainDateTime;
     add(
       durationLike: Temporal.Duration | DurationLike | string,
@@ -3831,8 +3832,6 @@ declare namespace Temporal {
       options?: ToInstantOptions,
     ): Temporal.ZonedDateTime;
     toPlainDate(): Temporal.PlainDate;
-    toPlainYearMonth(): Temporal.PlainYearMonth;
-    toPlainMonthDay(): Temporal.PlainMonthDay;
     toPlainTime(): Temporal.PlainTime;
     getISOFields(): PlainDateTimeISOFields;
     toLocaleString(
@@ -3883,7 +3882,6 @@ declare namespace Temporal {
     readonly monthCode: string;
     readonly day: number;
     readonly calendarId: string;
-    getCalendar(): CalendarProtocol;
     equals(other: Temporal.PlainMonthDay | PlainMonthDayLike | string): boolean;
     with(
       monthDayLike: PlainMonthDayLike,
@@ -4013,13 +4011,6 @@ declare namespace Temporal {
         | "nanosecond"
       >,
     ): Temporal.PlainTime;
-    toPlainDateTime(
-      temporalDate: Temporal.PlainDate | PlainDateLike | string,
-    ): Temporal.PlainDateTime;
-    toZonedDateTime(timeZoneAndDate: {
-      timeZone: TimeZoneLike;
-      plainDate: Temporal.PlainDate | PlainDateLike | string;
-    }): Temporal.ZonedDateTime;
     getISOFields(): PlainTimeISOFields;
     toLocaleString(
       locales?: string | string[],
@@ -4049,12 +4040,6 @@ declare namespace Temporal {
       dateTime: Temporal.PlainDateTime | PlainDateTimeLike | string,
       options?: ToInstantOptions,
     ): Temporal.Instant;
-    getNextTransition?(
-      startingPoint: Temporal.Instant | string,
-    ): Temporal.Instant | null;
-    getPreviousTransition?(
-      startingPoint: Temporal.Instant | string,
-    ): Temporal.Instant | null;
     getPossibleInstantsFor(
       dateTime: Temporal.PlainDateTime | PlainDateTimeLike | string,
     ): Temporal.Instant[];
@@ -4091,7 +4076,6 @@ declare namespace Temporal {
     static from(timeZone: TimeZoneLike): Temporal.TimeZone | TimeZoneProtocol;
     constructor(timeZoneIdentifier: string);
     readonly id: string;
-    equals(timeZone: TimeZoneLike): boolean;
     getOffsetNanosecondsFor(instant: Temporal.Instant | string): number;
     getOffsetStringFor(instant: Temporal.Instant | string): string;
     getPlainDateTimeFor(
@@ -4102,12 +4086,6 @@ declare namespace Temporal {
       dateTime: Temporal.PlainDateTime | PlainDateTimeLike | string,
       options?: ToInstantOptions,
     ): Temporal.Instant;
-    getNextTransition(
-      startingPoint: Temporal.Instant | string,
-    ): Temporal.Instant | null;
-    getPreviousTransition(
-      startingPoint: Temporal.Instant | string,
-    ): Temporal.Instant | null;
     getPossibleInstantsFor(
       dateTime: Temporal.PlainDateTime | PlainDateTimeLike | string,
     ): Temporal.Instant[];
@@ -4160,7 +4138,6 @@ declare namespace Temporal {
     readonly month: number;
     readonly monthCode: string;
     readonly calendarId: string;
-    getCalendar(): CalendarProtocol;
     readonly daysInMonth: number;
     readonly daysInYear: number;
     readonly monthsInYear: number;
@@ -4272,13 +4249,11 @@ declare namespace Temporal {
     readonly microsecond: number;
     readonly nanosecond: number;
     readonly timeZoneId: string;
-    getTimeZone(): TimeZoneProtocol;
     readonly calendarId: string;
-    getCalendar(): CalendarProtocol;
     readonly dayOfWeek: number;
     readonly dayOfYear: number;
-    readonly weekOfYear: number;
-    readonly yearOfWeek: number;
+    readonly weekOfYear: number | undefined;
+    readonly yearOfWeek: number | undefined;
     readonly hoursInDay: number;
     readonly daysInWeek: number;
     readonly daysInMonth: number;
@@ -4299,9 +4274,6 @@ declare namespace Temporal {
     withPlainTime(
       timeLike?: Temporal.PlainTime | PlainTimeLike | string,
     ): Temporal.ZonedDateTime;
-    withPlainDate(
-      dateLike: Temporal.PlainDate | PlainDateLike | string,
-    ): Temporal.ZonedDateTime;
     withCalendar(calendar: CalendarLike): Temporal.ZonedDateTime;
     withTimeZone(timeZone: TimeZoneLike): Temporal.ZonedDateTime;
     add(
@@ -4354,11 +4326,12 @@ declare namespace Temporal {
       >,
     ): Temporal.ZonedDateTime;
     startOfDay(): Temporal.ZonedDateTime;
+    getTimeZoneTransition(
+      direction: TransitionDirection,
+    ): Temporal.ZonedDateTime | null;
     toInstant(): Temporal.Instant;
     toPlainDateTime(): Temporal.PlainDateTime;
     toPlainDate(): Temporal.PlainDate;
-    toPlainYearMonth(): Temporal.PlainYearMonth;
-    toPlainMonthDay(): Temporal.PlainMonthDay;
     toPlainTime(): Temporal.PlainTime;
     getISOFields(): ZonedDateTimeISOFields;
     toLocaleString(
@@ -4395,29 +4368,6 @@ declare namespace Temporal {
      */
     instant: () => Temporal.Instant;
 
-    /**
-     * Get the current calendar date and clock time in a specific calendar and
-     * time zone.
-     *
-     * The `calendar` parameter is required. When using the ISO 8601 calendar or
-     * if you don't understand the need for or implications of a calendar, then
-     * a more ergonomic alternative to this method is
-     * `Temporal.Now.zonedDateTimeISO()`.
-     *
-     * @param {CalendarLike} [calendar] - calendar identifier, or
-     * a `Temporal.Calendar` instance, or an object implementing the calendar
-     * protocol.
-     * @param {TimeZoneLike} [tzLike] -
-     * {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones|IANA time zone identifier}
-     * string (e.g. `'Europe/London'`), `Temporal.TimeZone` instance, or an
-     * object implementing the time zone protocol. If omitted, the environment's
-     * current time zone will be used.
-     */
-    zonedDateTime: (
-      calendar: CalendarLike,
-      tzLike?: TimeZoneLike,
-    ) => Temporal.ZonedDateTime;
-
     /**
      * Get the current calendar date and clock time in a specific time zone,
      * using the ISO 8601 calendar.
@@ -4430,34 +4380,6 @@ declare namespace Temporal {
      */
     zonedDateTimeISO: (tzLike?: TimeZoneLike) => Temporal.ZonedDateTime;
 
-    /**
-     * Get the current calendar date and clock time in a specific calendar and
-     * time zone.
-     *
-     * The calendar is required. When using the ISO 8601 calendar or if you
-     * don't understand the need for or implications of a calendar, then a more
-     * ergonomic alternative to this method is `Temporal.Now.plainDateTimeISO`.
-     *
-     * Note that the `Temporal.PlainDateTime` type does not persist the time zone,
-     * but retaining the time zone is required for most time-zone-related use
-     * cases. Therefore, it's usually recommended to use
-     * `Temporal.Now.zonedDateTimeISO` or `Temporal.Now.zonedDateTime` instead
-     * of this function.
-     *
-     * @param {CalendarLike} [calendar] - calendar identifier, or
-     * a `Temporal.Calendar` instance, or an object implementing the calendar
-     * protocol.
-     * @param {TimeZoneLike} [tzLike] -
-     * {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones|IANA time zone identifier}
-     * string (e.g. `'Europe/London'`), `Temporal.TimeZone` instance, or an
-     * object implementing the time zone protocol. If omitted,
-     * the environment's current time zone will be used.
-     */
-    plainDateTime: (
-      calendar: CalendarLike,
-      tzLike?: TimeZoneLike,
-    ) => Temporal.PlainDateTime;
-
     /**
      * Get the current date and clock time in a specific time zone, using the
      * ISO 8601 calendar.
@@ -4475,27 +4397,6 @@ declare namespace Temporal {
      */
     plainDateTimeISO: (tzLike?: TimeZoneLike) => Temporal.PlainDateTime;
 
-    /**
-     * Get the current calendar date in a specific calendar and time zone.
-     *
-     * The calendar is required. When using the ISO 8601 calendar or if you
-     * don't understand the need for or implications of a calendar, then a more
-     * ergonomic alternative to this method is `Temporal.Now.plainDateISO`.
-     *
-     * @param {CalendarLike} [calendar] - calendar identifier, or
-     * a `Temporal.Calendar` instance, or an object implementing the calendar
-     * protocol.
-     * @param {TimeZoneLike} [tzLike] -
-     * {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones|IANA time zone identifier}
-     * string (e.g. `'Europe/London'`), `Temporal.TimeZone` instance, or an
-     * object implementing the time zone protocol. If omitted,
-     * the environment's current time zone will be used.
-     */
-    plainDate: (
-      calendar: CalendarLike,
-      tzLike?: TimeZoneLike,
-    ) => Temporal.PlainDate;
-
     /**
      * Get the current date in a specific time zone, using the ISO 8601
      * calendar.

filename: runtime/js/99_main.js
patch: @@ -849,6 +849,30 @@ function bootstrapMainRuntime(runtimeOptions, warmup = false) {
       // Removes the `Temporal` API.
       delete globalThis.Temporal;
       delete globalThis.Date.prototype.toTemporalInstant;
+    } else {
+      // Removes the obsoleted `Temporal` API.
+      // https://github.com/tc39/proposal-temporal/pull/2895
+      // https://github.com/tc39/proposal-temporal/pull/2914
+      if (typeof Temporal.Instant.fromEpochSeconds === "undefined") {
+        throw "V8 removes obsoleted Temporal API now, no need to delete them!";
+      }
+      delete Temporal.Instant.fromEpochSeconds;
+      delete Temporal.Instant.fromEpochMicroseconds;
+      delete Temporal.Instant.prototype.epochSeconds;
+      delete Temporal.Instant.prototype.epochMicroseconds;
+      delete Temporal.PlainDateTime.prototype.withPlainDate;
+      delete Temporal.PlainDateTime.prototype.toPlainYearMonth;
+      delete Temporal.PlainDateTime.prototype.toPlainMonthDay;
+      delete Temporal.PlainTime.prototype.toPlainDateTime;
+      delete Temporal.PlainTime.prototype.toZonedDateTime;
+      delete Temporal.TimeZone.prototype.getNextTransition;
+      delete Temporal.TimeZone.prototype.getPreviousTransition;
+      delete Temporal.ZonedDateTime.prototype.withPlainDate;
+      delete Temporal.ZonedDateTime.prototype.toPlainYearMonth;
+      delete Temporal.ZonedDateTime.prototype.toPlainMonthDay;
+      delete Temporal.Now.zonedDateTime;
+      delete Temporal.Now.plainDateTime;
+      delete Temporal.Now.plainDate;
     }
 
     // Setup `Deno` global - we're actually overriding already existing global
@@ -1008,6 +1032,30 @@ function bootstrapWorkerRuntime(
       // Removes the `Temporal` API.
       delete globalThis.Temporal;
       delete globalThis.Date.prototype.toTemporalInstant;
+    } else {
+      // Removes the obsoleted `Temporal` API.
+      // https://github.com/tc39/proposal-temporal/pull/2895
+      // https://github.com/tc39/proposal-temporal/pull/2914
+      if (typeof Temporal.Instant.fromEpochSeconds === "undefined") {
+        throw "V8 removes obsoleted Temporal API now, no need to delete them!";
+      }
+      delete Temporal.Instant.fromEpochSeconds;
+      delete Temporal.Instant.fromEpochMicroseconds;
+      delete Temporal.Instant.prototype.epochSeconds;
+      delete Temporal.Instant.prototype.epochMicroseconds;
+      delete Temporal.PlainDateTime.prototype.withPlainDate;
+      delete Temporal.PlainDateTime.prototype.toPlainYearMonth;
+      delete Temporal.PlainDateTime.prototype.toPlainMonthDay;
+      delete Temporal.PlainTime.prototype.toPlainDateTime;
+      delete Temporal.PlainTime.prototype.toZonedDateTime;
+      delete Temporal.TimeZone.prototype.getNextTransition;
+      delete Temporal.TimeZone.prototype.getPreviousTransition;
+      delete Temporal.ZonedDateTime.prototype.withPlainDate;
+      delete Temporal.ZonedDateTime.prototype.toPlainYearMonth;
+      delete Temporal.ZonedDateTime.prototype.toPlainMonthDay;
+      delete Temporal.Now.zonedDateTime;
+      delete Temporal.Now.plainDateTime;
+      delete Temporal.Now.plainDate;
     }
 
     // Setup `Deno` global - we're actually overriding already existing global