From 5143b9e7d3f72e6cc23f8381295df17ff1235f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 15 Jan 2024 01:26:57 +0100 Subject: [PATCH] feat(unstable): add Temporal API support (#21738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds support for [Stage 3 Temporal API proposal](https://tc39.es/proposal-temporal/docs/). The API is available when `--unstable-temporal` flag is passed. --------- Signed-off-by: Bartek Iwańczuk Co-authored-by: David Sherret Co-authored-by: Kenta Moriuchi --- cli/main.rs | 24 +- cli/tests/integration/lsp_tests.rs | 510 ++++- cli/tests/integration/run_tests.rs | 14 + .../run/unstable_temporal_api/main.out | 12 + .../run/unstable_temporal_api/main.ts | 71 + .../run/unstable_temporal_api/missing_flag.js | 1 + .../unstable_temporal_api/missing_flag.out | 4 + cli/tsc/dts/lib.deno.unstable.d.ts | 1994 +++++++++++++++++ cli/tsc/dts/lib.es2020.intl.d.ts | 2 +- cli/tsc/dts/lib.es5.d.ts | 2 +- ext/console/01_console.js | 50 + runtime/js/90_deno_ns.js | 7 +- 12 files changed, 2621 insertions(+), 70 deletions(-) create mode 100644 cli/tests/testdata/run/unstable_temporal_api/main.out create mode 100644 cli/tests/testdata/run/unstable_temporal_api/main.ts create mode 100644 cli/tests/testdata/run/unstable_temporal_api/missing_flag.js create mode 100644 cli/tests/testdata/run/unstable_temporal_api/missing_flag.out diff --git a/cli/main.rs b/cli/main.rs index 6a9ac33273..53c7bdf5a7 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -315,22 +315,28 @@ pub(crate) static UNSTABLE_GRANULAR_FLAGS: &[( "Enable unstable net APIs", 7, ), + ( + "temporal", + "Enable unstable Temporal API", + // Not used in JS + 8, + ), ( "unsafe-proto", "Enable unsafe __proto__ support. This is a security risk.", // This number is used directly in the JS code. Search - // for "unstableFeatures" to see where it's used. - 8, + // for "unstableIds" to see where it's used. + 9, ), ( deno_runtime::deno_webgpu::UNSTABLE_FEATURE_NAME, "Enable unstable `WebGPU` API", - 9, + 10, ), ( deno_runtime::ops::worker_host::UNSTABLE_FEATURE_NAME, "Enable unstable Web Worker APIs", - 10, + 11, ), ]; @@ -394,7 +400,15 @@ pub fn main() { // Using same default as VSCode: // https://github.com/microsoft/vscode/blob/48d4ba271686e8072fc6674137415bc80d936bc7/extensions/typescript-language-features/src/configuration/configuration.ts#L213-L214 DenoSubcommand::Lsp => vec!["--max-old-space-size=3072".to_string()], - _ => vec![], + _ => { + if flags.unstable + || flags.unstable_features.contains(&"temporal".to_string()) + { + vec!["--harmony-temporal".to_string()] + } else { + vec![] + } + } }; init_v8_flags(&default_v8_flags, &flags.v8_flags, get_v8_flags_from_env()); deno_core::JsRuntime::init_platform(None); diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index 94982c0a7f..018dc93304 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -9012,68 +9012,458 @@ fn lsp_workspace_symbol() { ); assert_eq!( res, - json!([{ - "name": "fieldA", - "kind": 8, - "location": { - "uri": "file:///a/file.ts", - "range": { - "start": { "line": 1, "character": 2 }, - "end": { "line": 1, "character": 17 } - } - }, - "containerName": "A" - }, { - "name": "fieldB", - "kind": 8, - "location": { - "uri": "file:///a/file.ts", - "range": { - "start": { "line": 2, "character": 2 }, - "end": { "line": 2, "character": 17 } - } - }, - "containerName": "A" - }, { - "name": "fieldC", - "kind": 8, - "location": { - "uri": "file:///a/file_01.ts", - "range": { - "start": { "line": 1, "character": 2 }, - "end": { "line": 1, "character": 17 } - } - }, - "containerName": "B" - }, { - "name": "fieldD", - "kind": 8, - "location": { - "uri": "file:///a/file_01.ts", - "range": { - "start": { "line": 2, "character": 2 }, - "end": { "line": 2, "character": 17 } - } - }, - "containerName": "B" - }, { - "name": "ClassFieldDecoratorContext", - "kind": 11, - "location": { - "uri": "deno:/asset/lib.decorators.d.ts", - "range": { - "start": { - "line": 343, - "character": 0, - }, - "end": { - "line": 385, - "character": 1, - }, + json!([ + { + "name": "fieldA", + "kind": 8, + "location": { + "uri": "file:///a/file.ts", + "range": { + "start": { + "line": 1, + "character": 2 + }, + "end": { + "line": 1, + "character": 17 + } + } }, + "containerName": "A" }, - "containerName": "", - }]) + { + "name": "fieldB", + "kind": 8, + "location": { + "uri": "file:///a/file.ts", + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 17 + } + } + }, + "containerName": "A" + }, + { + "name": "fieldC", + "kind": 8, + "location": { + "uri": "file:///a/file_01.ts", + "range": { + "start": { + "line": 1, + "character": 2 + }, + "end": { + "line": 1, + "character": 17 + } + } + }, + "containerName": "B" + }, + { + "name": "fieldD", + "kind": 8, + "location": { + "uri": "file:///a/file_01.ts", + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 17 + } + } + }, + "containerName": "B" + }, + { + "name": "fields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3139, + "character": 4 + }, + "end": { + "line": 3139, + "character": 55 + } + } + }, + "containerName": "CalendarProtocol" + }, + { + "name": "fields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3309, + "character": 4 + }, + "end": { + "line": 3309, + "character": 47 + } + } + }, + "containerName": "Calendar" + }, + { + "name": "ClassFieldDecoratorContext", + "kind": 11, + "location": { + "uri": "deno:/asset/lib.decorators.d.ts", + "range": { + "start": { + "line": 343, + "character": 0 + }, + "end": { + "line": 385, + "character": 1 + } + } + }, + "containerName": "" + }, + { + "name": "dateFromFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3117, + "character": 4 + }, + "end": { + "line": 3120, + "character": 26 + } + } + }, + "containerName": "CalendarProtocol" + }, + { + "name": "dateFromFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3287, + "character": 4 + }, + "end": { + "line": 3290, + "character": 26 + } + } + }, + "containerName": "Calendar" + }, + { + "name": "getISOFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3413, + "character": 4 + }, + "end": { + "line": 3413, + "character": 39 + } + } + }, + "containerName": "PlainDate" + }, + { + "name": "getISOFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3576, + "character": 4 + }, + "end": { + "line": 3576, + "character": 43 + } + } + }, + "containerName": "PlainDateTime" + }, + { + "name": "getISOFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3625, + "character": 4 + }, + "end": { + "line": 3625, + "character": 39 + } + } + }, + "containerName": "PlainMonthDay" + }, + { + "name": "getISOFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3744, + "character": 4 + }, + "end": { + "line": 3744, + "character": 39 + } + } + }, + "containerName": "PlainTime" + }, + { + "name": "getISOFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3897, + "character": 4 + }, + "end": { + "line": 3897, + "character": 39 + } + } + }, + "containerName": "PlainYearMonth" + }, + { + "name": "getISOFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 4056, + "character": 4 + }, + "end": { + "line": 4056, + "character": 43 + } + } + }, + "containerName": "ZonedDateTime" + }, + { + "name": "mergeFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3140, + "character": 4 + }, + "end": { + "line": 3143, + "character": 31 + } + } + }, + "containerName": "CalendarProtocol" + }, + { + "name": "mergeFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3310, + "character": 4 + }, + "end": { + "line": 3313, + "character": 31 + } + } + }, + "containerName": "Calendar" + }, + { + "name": "monthDayFromFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3125, + "character": 4 + }, + "end": { + "line": 3128, + "character": 30 + } + } + }, + "containerName": "CalendarProtocol" + }, + { + "name": "monthDayFromFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3295, + "character": 4 + }, + "end": { + "line": 3298, + "character": 30 + } + } + }, + "containerName": "Calendar" + }, + { + "name": "PlainDateISOFields", + "kind": 5, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3329, + "character": 2 + }, + "end": { + "line": 3334, + "character": 4 + } + } + }, + "containerName": "Temporal" + }, + { + "name": "PlainDateTimeISOFields", + "kind": 5, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3440, + "character": 2 + }, + "end": { + "line": 3451, + "character": 4 + } + } + }, + "containerName": "Temporal" + }, + { + "name": "PlainTimeISOFields", + "kind": 5, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3645, + "character": 2 + }, + "end": { + "line": 3652, + "character": 4 + } + } + }, + "containerName": "Temporal" + }, + { + "name": "yearMonthFromFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3121, + "character": 4 + }, + "end": { + "line": 3124, + "character": 31 + } + } + }, + "containerName": "CalendarProtocol" + }, + { + "name": "yearMonthFromFields", + "kind": 6, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3291, + "character": 4 + }, + "end": { + "line": 3294, + "character": 31 + } + } + }, + "containerName": "Calendar" + }, + { + "name": "ZonedDateTimeISOFields", + "kind": 5, + "location": { + "uri": "deno:/asset/lib.deno.unstable.d.ts", + "range": { + "start": { + "line": 3926, + "character": 2 + }, + "end": { + "line": 3939, + "character": 4 + } + } + }, + "containerName": "Temporal" + } + ]) ); client.shutdown(); } diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 38408c0f94..8db06470d1 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -4925,3 +4925,17 @@ Warning Sloppy module resolution (hint: specify path to index.tsx file in direct ", ); } + +itest!(unstable_temporal_api { + args: "run --unstable-temporal --check run/unstable_temporal_api/main.ts", + output: "run/unstable_temporal_api/main.out", + http_server: false, + exit_code: 0, +}); + +itest!(unstable_temporal_api_missing_flag { + args: "run run/unstable_temporal_api/missing_flag.js", + output: "run/unstable_temporal_api/missing_flag.out", + http_server: false, + exit_code: 1, +}); diff --git a/cli/tests/testdata/run/unstable_temporal_api/main.out b/cli/tests/testdata/run/unstable_temporal_api/main.out new file mode 100644 index 0000000000..46d25c3ea7 --- /dev/null +++ b/cli/tests/testdata/run/unstable_temporal_api/main.out @@ -0,0 +1,12 @@ +Check [WILDCARD] +Temporal.Now [WILDCARD] +Temporal.Instant 1969-07-20T20:17:00Z +Temporal.ZonedDateTime 1995-12-07T03:24:30.0000035-08:00[America/Los_Angeles] +Temporal.PlainDate 2006-08-24 +Temporal.PlainTime 19:39:09.068346205 +Temporal.PlainDateTime 1995-12-07T15:00:00 +Temporal.PlainYearMonth 2020-10 +Temporal.PlainMonthDay 07-14 +Temporal.Duration PT130H20M +Temporal.TimeZone Africa/Cairo +Temporal.Calendar 1999-12-31 diff --git a/cli/tests/testdata/run/unstable_temporal_api/main.ts b/cli/tests/testdata/run/unstable_temporal_api/main.ts new file mode 100644 index 0000000000..1641b90bf8 --- /dev/null +++ b/cli/tests/testdata/run/unstable_temporal_api/main.ts @@ -0,0 +1,71 @@ +console.log("Temporal.Now", Temporal.Now.instant()); +console.log( + "Temporal.Instant", + Temporal.Instant.from("1969-07-20T20:17Z"), +); +console.log( + "Temporal.ZonedDateTime", + Temporal.ZonedDateTime.from({ + timeZone: "America/Los_Angeles", + year: 1995, + month: 12, + day: 7, + hour: 3, + minute: 24, + second: 30, + millisecond: 0, + microsecond: 3, + nanosecond: 500, + }), +); +console.log( + "Temporal.PlainDate", + Temporal.PlainDate.from({ year: 2006, month: 8, day: 24 }), +); +console.log( + "Temporal.PlainTime", + Temporal.PlainTime.from({ + hour: 19, + minute: 39, + second: 9, + millisecond: 68, + microsecond: 346, + nanosecond: 205, + }), +); +console.log( + "Temporal.PlainDateTime", + Temporal.PlainDateTime.from({ + year: 1995, + month: 12, + day: 7, + hour: 15, + }), +); +console.log( + "Temporal.PlainYearMonth", + Temporal.PlainYearMonth.from({ year: 2020, month: 10 }), +); +console.log( + "Temporal.PlainMonthDay", + Temporal.PlainMonthDay.from({ month: 7, day: 14 }), +); +console.log( + "Temporal.Duration", + Temporal.Duration.from({ + hours: 130, + minutes: 20, + }), +); +console.log( + "Temporal.TimeZone", + Temporal.TimeZone.from("Africa/Cairo"), +); +console.log( + "Temporal.Calendar", + Temporal.Calendar.from("iso8601").dateFromFields({ + year: 1999, + month: 12, + day: 31, + }, {}), +); diff --git a/cli/tests/testdata/run/unstable_temporal_api/missing_flag.js b/cli/tests/testdata/run/unstable_temporal_api/missing_flag.js new file mode 100644 index 0000000000..92aed79314 --- /dev/null +++ b/cli/tests/testdata/run/unstable_temporal_api/missing_flag.js @@ -0,0 +1 @@ +Temporal.Now.instant(); diff --git a/cli/tests/testdata/run/unstable_temporal_api/missing_flag.out b/cli/tests/testdata/run/unstable_temporal_api/missing_flag.out new file mode 100644 index 0000000000..8f8e23e706 --- /dev/null +++ b/cli/tests/testdata/run/unstable_temporal_api/missing_flag.out @@ -0,0 +1,4 @@ +error: Uncaught (in promise) ReferenceError: Temporal is not defined +Temporal.Now.instant(); +^ + at [WILDCARD]missing_flag.js:1:1 diff --git a/cli/tsc/dts/lib.deno.unstable.d.ts b/cli/tsc/dts/lib.deno.unstable.d.ts index 555a6d5d82..827c95556f 100644 --- a/cli/tsc/dts/lib.deno.unstable.d.ts +++ b/cli/tsc/dts/lib.deno.unstable.d.ts @@ -3,6 +3,8 @@ /// /// /// +/// +/// declare namespace Deno { export {}; // stop default export type behavior @@ -2299,3 +2301,1995 @@ declare var WebSocketStream: { readonly prototype: WebSocketStream; new (url: string, options?: WebSocketStreamOptions): WebSocketStream; }; + +// Adapted from `tc39/proposal-temporal`: https://github.com/tc39/proposal-temporal/blob/main/polyfill/index.d.ts + +declare namespace Temporal { + export type ComparisonResult = -1 | 0 | 1; + export type RoundingMode = + | "ceil" + | "floor" + | "expand" + | "trunc" + | "halfCeil" + | "halfFloor" + | "halfExpand" + | "halfTrunc" + | "halfEven"; + + /** + * Options for assigning fields using `with()` or entire objects with + * `from()`. + */ + export type AssignmentOptions = { + /** + * How to deal with out-of-range values + * + * - In `'constrain'` mode, out-of-range values are clamped to the nearest + * in-range value. + * - In `'reject'` mode, out-of-range values will cause the function to + * throw a RangeError. + * + * The default is `'constrain'`. + */ + overflow?: "constrain" | "reject"; + }; + + /** + * Options for assigning fields using `Duration.prototype.with()` or entire + * objects with `Duration.from()`, and for arithmetic with + * `Duration.prototype.add()` and `Duration.prototype.subtract()`. + */ + export type DurationOptions = { + /** + * How to deal with out-of-range values + * + * - In `'constrain'` mode, out-of-range values are clamped to the nearest + * in-range value. + * - In `'balance'` mode, out-of-range values are resolved by balancing them + * with the next highest unit. + * + * The default is `'constrain'`. + */ + overflow?: "constrain" | "balance"; + }; + + /** + * Options for conversions of `Temporal.PlainDateTime` to `Temporal.Instant` + */ + export type ToInstantOptions = { + /** + * Controls handling of invalid or ambiguous times caused by time zone + * offset changes like Daylight Saving time (DST) transitions. + * + * This option is only relevant if a `DateTime` value does not exist in the + * destination time zone (e.g. near "Spring Forward" DST transitions), or + * exists more than once (e.g. near "Fall Back" DST transitions). + * + * In case of ambiguous or nonexistent times, this option controls what + * exact time to return: + * - `'compatible'`: Equivalent to `'earlier'` for backward transitions like + * the start of DST in the Spring, and `'later'` for forward transitions + * like the end of DST in the Fall. This matches the behavior of legacy + * `Date`, of libraries like moment.js, Luxon, or date-fns, and of + * cross-platform standards like [RFC 5545 + * (iCalendar)](https://tools.ietf.org/html/rfc5545). + * - `'earlier'`: The earlier time of two possible times + * - `'later'`: The later of two possible times + * - `'reject'`: Throw a RangeError instead + * + * The default is `'compatible'`. + */ + disambiguation?: "compatible" | "earlier" | "later" | "reject"; + }; + + type OffsetDisambiguationOptions = { + /** + * Time zone definitions can change. If an application stores data about + * events in the future, then stored data about future events may become + * ambiguous, for example if a country permanently abolishes DST. The + * `offset` option controls this unusual case. + * + * - `'use'` always uses the offset (if it's provided) to calculate the + * instant. This ensures that the result will match the instant that was + * originally stored, even if local clock time is different. + * - `'prefer'` uses the offset if it's valid for the date/time in this time + * zone, but if it's not valid then the time zone will be used as a + * fallback to calculate the instant. + * - `'ignore'` will disregard any provided offset. Instead, the time zone + * and date/time value are used to calculate the instant. This will keep + * local clock time unchanged but may result in a different real-world + * instant. + * - `'reject'` acts like `'prefer'`, except it will throw a RangeError if + * the offset is not valid for the given time zone identifier and + * date/time value. + * + * If the ISO string ends in 'Z' then this option is ignored because there + * is no possibility of ambiguity. + * + * If a time zone offset is not present in the input, then this option is + * ignored because the time zone will always be used to calculate the + * offset. + * + * If the offset is not used, and if the date/time and time zone don't + * uniquely identify a single instant, then the `disambiguation` option will + * be used to choose the correct instant. However, if the offset is used + * then the `disambiguation` option will be ignored. + */ + offset?: "use" | "prefer" | "ignore" | "reject"; + }; + + export type ZonedDateTimeAssignmentOptions = Partial< + AssignmentOptions & ToInstantOptions & OffsetDisambiguationOptions + >; + + /** + * Options for arithmetic operations like `add()` and `subtract()` + */ + export type ArithmeticOptions = { + /** + * Controls handling of out-of-range arithmetic results. + * + * If a result is out of range, then `'constrain'` will clamp the result to + * the allowed range, while `'reject'` will throw a RangeError. + * + * The default is `'constrain'`. + */ + overflow?: "constrain" | "reject"; + }; + + export type DateUnit = "year" | "month" | "week" | "day"; + export type TimeUnit = + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond"; + export type DateTimeUnit = DateUnit | TimeUnit; + + /** + * 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. + */ + export type PluralUnit = { + year: "years"; + month: "months"; + week: "weeks"; + day: "days"; + hour: "hours"; + minute: "minutes"; + second: "seconds"; + millisecond: "milliseconds"; + microsecond: "microseconds"; + nanosecond: "nanoseconds"; + }[T]; + + export type LargestUnit = "auto" | T | PluralUnit; + export type SmallestUnit = T | PluralUnit; + export type TotalUnit = T | PluralUnit; + + /** + * Options for outputting precision in toString() on types with seconds + */ + export type ToStringPrecisionOptions = { + fractionalSecondDigits?: "auto" | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + smallestUnit?: SmallestUnit< + "minute" | "second" | "millisecond" | "microsecond" | "nanosecond" + >; + + /** + * Controls how rounding is performed: + * - `halfExpand`: Round to the nearest of the values allowed by + * `roundingIncrement` and `smallestUnit`. When there is a tie, round up. + * This mode is the default. + * - `ceil`: Always round up, towards the end of time. + * - `trunc`: Always round down, towards the beginning of time. + * - `floor`: Also round down, towards the beginning of time. This mode acts + * the same as `trunc`, but it's included for consistency with + * `Temporal.Duration.round()` where negative values are allowed and + * `trunc` rounds towards zero, unlike `floor` which rounds towards + * negative infinity which is usually unexpected. For this reason, `trunc` + * is recommended for most use cases. + */ + roundingMode?: RoundingMode; + }; + + export type ShowCalendarOption = { + calendarName?: "auto" | "always" | "never" | "critical"; + }; + + export type CalendarTypeToStringOptions = Partial< + ToStringPrecisionOptions & ShowCalendarOption + >; + + export type ZonedDateTimeToStringOptions = Partial< + CalendarTypeToStringOptions & { + timeZoneName?: "auto" | "never" | "critical"; + offset?: "auto" | "never"; + } + >; + + export type InstantToStringOptions = Partial< + ToStringPrecisionOptions & { + timeZone: TimeZoneLike; + } + >; + + /** + * Options to control the result of `until()` and `since()` methods in + * `Temporal` types. + */ + export interface DifferenceOptions { + /** + * The unit to round to. For example, to round to the nearest minute, use + * `smallestUnit: 'minute'`. This property is optional for `until()` and + * `since()`, because those methods default behavior is not to round. + * However, the same property is required for `round()`. + */ + smallestUnit?: SmallestUnit; + + /** + * The largest unit to allow in the resulting `Temporal.Duration` object. + * + * Larger units will be "balanced" into smaller units. For example, if + * `largestUnit` is `'minute'` then a two-hour duration will be output as a + * 120-minute duration. + * + * Valid values may include `'year'`, `'month'`, `'week'`, `'day'`, + * `'hour'`, `'minute'`, `'second'`, `'millisecond'`, `'microsecond'`, + * `'nanosecond'` and `'auto'`, although some types may throw an exception + * if a value is used that would produce an invalid result. For example, + * `hours` is not accepted by `Temporal.PlainDate.prototype.since()`. + * + * The default is always `'auto'`, though the meaning of this depends on the + * type being used. + */ + largestUnit?: LargestUnit; + + /** + * Allows rounding to an integer number of units. For example, to round to + * increments of a half hour, use `{ smallestUnit: 'minute', + * roundingIncrement: 30 }`. + */ + roundingIncrement?: number; + + /** + * Controls how rounding is performed: + * - `halfExpand`: Round to the nearest of the values allowed by + * `roundingIncrement` and `smallestUnit`. When there is a tie, round away + * from zero like `ceil` for positive durations and like `floor` for + * negative durations. + * - `ceil`: Always round up, towards the end of time. + * - `trunc`: Always round down, towards the beginning of time. This mode is + * the default. + * - `floor`: Also round down, towards the beginning of time. This mode acts + * the same as `trunc`, but it's included for consistency with + * `Temporal.Duration.round()` where negative values are allowed and + * `trunc` rounds towards zero, unlike `floor` which rounds towards + * negative infinity which is usually unexpected. For this reason, `trunc` + * is recommended for most use cases. + */ + roundingMode?: RoundingMode; + } + + /** + * `round` methods take one required parameter. If a string is provided, the + * resulting `Temporal.Duration` object will be rounded to that unit. If an + * object is provided, its `smallestUnit` property is required while other + * properties are optional. A string is treated the same as an object whose + * `smallestUnit` property value is that string. + */ + export type RoundTo = + | SmallestUnit + | { + /** + * The unit to round to. For example, to round to the nearest minute, + * use `smallestUnit: 'minute'`. This option is required. Note that the + * same-named property is optional when passed to `until` or `since` + * methods, because those methods do no rounding by default. + */ + smallestUnit: SmallestUnit; + + /** + * Allows rounding to an integer number of units. For example, to round to + * increments of a half hour, use `{ smallestUnit: 'minute', + * roundingIncrement: 30 }`. + */ + roundingIncrement?: number; + + /** + * Controls how rounding is performed: + * - `halfExpand`: Round to the nearest of the values allowed by + * `roundingIncrement` and `smallestUnit`. When there is a tie, round up. + * This mode is the default. + * - `ceil`: Always round up, towards the end of time. + * - `trunc`: Always round down, towards the beginning of time. + * - `floor`: Also round down, towards the beginning of time. This mode acts + * the same as `trunc`, but it's included for consistency with + * `Temporal.Duration.round()` where negative values are allowed and + * `trunc` rounds towards zero, unlike `floor` which rounds towards + * negative infinity which is usually unexpected. For this reason, `trunc` + * is recommended for most use cases. + */ + roundingMode?: RoundingMode; + }; + + /** + * The `round` method of the `Temporal.Duration` accepts one required + * parameter. If a string is provided, the resulting `Temporal.Duration` + * object will be rounded to that unit. If an object is provided, the + * `smallestUnit` and/or `largestUnit` property is required, while other + * properties are optional. A string parameter is treated the same as an + * object whose `smallestUnit` property value is that string. + */ + export type DurationRoundTo = + | SmallestUnit + | ( + & ( + | { + /** + * The unit to round to. For example, to round to the nearest + * minute, use `smallestUnit: 'minute'`. This property is normally + * required, but is optional if `largestUnit` is provided and not + * undefined. + */ + smallestUnit: SmallestUnit; + + /** + * The largest unit to allow in the resulting `Temporal.Duration` + * object. + * + * Larger units will be "balanced" into smaller units. For example, + * if `largestUnit` is `'minute'` then a two-hour duration will be + * output as a 120-minute duration. + * + * Valid values include `'year'`, `'month'`, `'week'`, `'day'`, + * `'hour'`, `'minute'`, `'second'`, `'millisecond'`, + * `'microsecond'`, `'nanosecond'` and `'auto'`. + * + * The default is `'auto'`, which means "the largest nonzero unit in + * the input duration". This default prevents expanding durations to + * larger units unless the caller opts into this behavior. + * + * If `smallestUnit` is larger, then `smallestUnit` will be used as + * `largestUnit`, superseding a caller-supplied or default value. + */ + largestUnit?: LargestUnit; + } + | { + /** + * The unit to round to. For example, to round to the nearest + * minute, use `smallestUnit: 'minute'`. This property is normally + * required, but is optional if `largestUnit` is provided and not + * undefined. + */ + smallestUnit?: SmallestUnit; + + /** + * The largest unit to allow in the resulting `Temporal.Duration` + * object. + * + * Larger units will be "balanced" into smaller units. For example, + * if `largestUnit` is `'minute'` then a two-hour duration will be + * output as a 120-minute duration. + * + * Valid values include `'year'`, `'month'`, `'week'`, `'day'`, + * `'hour'`, `'minute'`, `'second'`, `'millisecond'`, + * `'microsecond'`, `'nanosecond'` and `'auto'`. + * + * The default is `'auto'`, which means "the largest nonzero unit in + * the input duration". This default prevents expanding durations to + * larger units unless the caller opts into this behavior. + * + * If `smallestUnit` is larger, then `smallestUnit` will be used as + * `largestUnit`, superseding a caller-supplied or default value. + */ + largestUnit: LargestUnit; + } + ) + & { + /** + * Allows rounding to an integer number of units. For example, to round + * to increments of a half hour, use `{ smallestUnit: 'minute', + * roundingIncrement: 30 }`. + */ + roundingIncrement?: number; + + /** + * Controls how rounding is performed: + * - `halfExpand`: Round to the nearest of the values allowed by + * `roundingIncrement` and `smallestUnit`. When there is a tie, round + * away from zero like `ceil` for positive durations and like `floor` + * for negative durations. This mode is the default. + * - `ceil`: Always round towards positive infinity. For negative + * durations this option will decrease the absolute value of the + * duration which may be unexpected. To round away from zero, use + * `ceil` for positive durations and `floor` for negative durations. + * - `trunc`: Always round down towards zero. + * - `floor`: Always round towards negative infinity. This mode acts the + * same as `trunc` for positive durations but for negative durations + * it will increase the absolute value of the result which may be + * unexpected. For this reason, `trunc` is recommended for most "round + * down" use cases. + */ + roundingMode?: RoundingMode; + + /** + * The starting point to use for rounding and conversions when + * variable-length units (years, months, weeks depending on the + * calendar) are involved. This option is required if any of the + * following are true: + * - `unit` is `'week'` or larger units + * - `this` has a nonzero value for `weeks` or larger units + * + * 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'` + * - `Temporal.PlainDate.from('2020-01-01')` + * + * `Temporal.ZonedDateTime` will be tried first because it's more + * specific, with `Temporal.PlainDateTime` as a fallback. + * + * If the value resolves to a `Temporal.ZonedDateTime`, then operation + * will adjust for DST and other time zone transitions. Otherwise + * (including if this option is omitted), then the operation will ignore + * time zone transitions and all days will be assumed to be 24 hours + * long. + */ + relativeTo?: + | Temporal.PlainDateTime + | Temporal.ZonedDateTime + | PlainDateTimeLike + | ZonedDateTimeLike + | string; + } + ); + + /** + * Options to control behavior of `Duration.prototype.total()` + */ + export type DurationTotalOf = + | TotalUnit + | { + /** + * The unit to convert the duration to. This option is required. + */ + unit: TotalUnit; + + /** + * The starting point to use when variable-length units (years, months, + * weeks depending on the calendar) are involved. This option is required if + * any of the following are true: + * - `unit` is `'week'` or larger units + * - `this` has a nonzero value for `weeks` or larger units + * + * 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'` + * - `Temporal.PlainDate.from('2020-01-01')` + * + * `Temporal.ZonedDateTime` will be tried first because it's more + * specific, with `Temporal.PlainDateTime` as a fallback. + * + * If the value resolves to a `Temporal.ZonedDateTime`, then operation will + * adjust for DST and other time zone transitions. Otherwise (including if + * this option is omitted), then the operation will ignore time zone + * transitions and all days will be assumed to be 24 hours long. + */ + relativeTo?: + | Temporal.ZonedDateTime + | Temporal.PlainDateTime + | ZonedDateTimeLike + | PlainDateTimeLike + | string; + }; + + /** + * Options to control behavior of `Duration.compare()`, `Duration.add()`, and + * `Duration.subtract()` + */ + export interface DurationArithmeticOptions { + /** + * The starting point to use when variable-length units (years, months, + * weeks depending on the calendar) are involved. This option is required if + * either of the durations has a nonzero value for `weeks` or larger units. + * + * 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'` + * - `Temporal.PlainDate.from('2020-01-01')` + * + * `Temporal.ZonedDateTime` will be tried first because it's more + * specific, with `Temporal.PlainDateTime` as a fallback. + * + * If the value resolves to a `Temporal.ZonedDateTime`, then operation will + * adjust for DST and other time zone transitions. Otherwise (including if + * this option is omitted), then the operation will ignore time zone + * transitions and all days will be assumed to be 24 hours long. + */ + relativeTo?: + | Temporal.ZonedDateTime + | Temporal.PlainDateTime + | ZonedDateTimeLike + | PlainDateTimeLike + | string; + } + + export type DurationLike = { + years?: number; + months?: number; + weeks?: number; + days?: number; + hours?: number; + minutes?: number; + seconds?: number; + milliseconds?: number; + microseconds?: number; + nanoseconds?: number; + }; + + /** + * A `Temporal.Duration` represents an immutable duration of time which can be + * used in date/time arithmetic. + * + * See https://tc39.es/proposal-temporal/docs/duration.html for more details. + */ + export class Duration { + static from( + item: Temporal.Duration | DurationLike | string, + ): Temporal.Duration; + static compare( + one: Temporal.Duration | DurationLike | string, + two: Temporal.Duration | DurationLike | string, + options?: DurationArithmeticOptions, + ): ComparisonResult; + constructor( + years?: number, + months?: number, + weeks?: number, + days?: number, + hours?: number, + minutes?: number, + seconds?: number, + milliseconds?: number, + microseconds?: number, + nanoseconds?: number, + ); + readonly sign: -1 | 0 | 1; + readonly blank: boolean; + readonly years: number; + readonly months: number; + readonly weeks: number; + readonly days: number; + readonly hours: number; + readonly minutes: number; + readonly seconds: number; + readonly milliseconds: number; + readonly microseconds: number; + readonly nanoseconds: number; + negated(): Temporal.Duration; + abs(): Temporal.Duration; + with(durationLike: DurationLike): Temporal.Duration; + add( + other: Temporal.Duration | DurationLike | string, + options?: DurationArithmeticOptions, + ): Temporal.Duration; + subtract( + other: Temporal.Duration | DurationLike | string, + options?: DurationArithmeticOptions, + ): Temporal.Duration; + round(roundTo: DurationRoundTo): Temporal.Duration; + total(totalOf: DurationTotalOf): number; + toLocaleString( + locales?: string | string[], + options?: Intl.DateTimeFormatOptions, + ): string; + toJSON(): string; + toString(options?: ToStringPrecisionOptions): string; + valueOf(): never; + readonly [Symbol.toStringTag]: "Temporal.Duration"; + } + + /** + * A `Temporal.Instant` is an exact point in time, with a precision in + * nanoseconds. No time zone or calendar information is present. Therefore, + * `Temporal.Instant` has no concept of days, months, or even hours. + * + * For convenience of interoperability, it internally uses nanoseconds since + * the {@link https://en.wikipedia.org/wiki/Unix_time|Unix epoch} (midnight + * UTC on January 1, 1970). However, a `Temporal.Instant` can be created from + * any of several expressions that refer to a single point in time, including + * an {@link https://en.wikipedia.org/wiki/ISO_8601|ISO 8601 string} with a + * time zone offset such as '2020-01-23T17:04:36.491865121-08:00'. + * + * See https://tc39.es/proposal-temporal/docs/instant.html for more details. + */ + 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( + durationLike: + | Omit< + Temporal.Duration | DurationLike, + "years" | "months" | "weeks" | "days" + > + | string, + ): Temporal.Instant; + subtract( + durationLike: + | Omit< + Temporal.Duration | DurationLike, + "years" | "months" | "weeks" | "days" + > + | string, + ): Temporal.Instant; + until( + other: Temporal.Instant | string, + options?: DifferenceOptions< + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.Duration; + since( + other: Temporal.Instant | string, + options?: DifferenceOptions< + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.Duration; + round( + roundTo: RoundTo< + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.Instant; + toZonedDateTime( + calendarAndTimeZone: { timeZone: TimeZoneLike; calendar: CalendarLike }, + ): Temporal.ZonedDateTime; + toZonedDateTimeISO(tzLike: TimeZoneLike): Temporal.ZonedDateTime; + toLocaleString( + locales?: string | string[], + options?: Intl.DateTimeFormatOptions, + ): string; + toJSON(): string; + toString(options?: InstantToStringOptions): string; + valueOf(): never; + readonly [Symbol.toStringTag]: "Temporal.Instant"; + } + + type YearOrEraAndEraYear = { era: string; eraYear: number } | { + year: number; + }; + type MonthCodeOrMonthAndYear = (YearOrEraAndEraYear & { month: number }) | { + monthCode: string; + }; + type MonthOrMonthCode = { month: number } | { monthCode: string }; + + export interface CalendarProtocol { + id: string; + year( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): number; + month( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | Temporal.PlainMonthDay + | PlainDateLike + | string, + ): number; + monthCode( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | Temporal.PlainMonthDay + | PlainDateLike + | string, + ): string; + day( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainMonthDay + | PlainDateLike + | string, + ): number; + era( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): string | undefined; + eraYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number | undefined; + dayOfWeek( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + dayOfYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + weekOfYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + yearOfWeek( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + daysInWeek( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + daysInMonth( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): number; + daysInYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): number; + monthsInYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): number; + inLeapYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): boolean; + dateFromFields( + fields: YearOrEraAndEraYear & MonthOrMonthCode & { day: number }, + options?: AssignmentOptions, + ): Temporal.PlainDate; + yearMonthFromFields( + fields: YearOrEraAndEraYear & MonthOrMonthCode, + options?: AssignmentOptions, + ): Temporal.PlainYearMonth; + monthDayFromFields( + fields: MonthCodeOrMonthAndYear & { day: number }, + options?: AssignmentOptions, + ): Temporal.PlainMonthDay; + dateAdd( + date: Temporal.PlainDate | PlainDateLike | string, + duration: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.PlainDate; + dateUntil( + one: Temporal.PlainDate | PlainDateLike | string, + two: Temporal.PlainDate | PlainDateLike | string, + options?: DifferenceOptions<"year" | "month" | "week" | "day">, + ): Temporal.Duration; + fields(fields: Iterable): Iterable; + mergeFields( + fields: Record, + additionalFields: Record, + ): Record; + toString?(): string; + toJSON?(): string; + } + + /** + * Any of these types can be passed to Temporal methods instead of a Temporal.Calendar. + */ + export type CalendarLike = + | string + | CalendarProtocol + | ZonedDateTime + | PlainDateTime + | PlainDate + | PlainYearMonth + | PlainMonthDay; + + /** + * A `Temporal.Calendar` is a representation of a calendar system. It includes + * information about how many days are in each year, how many months are in + * each year, how many days are in each month, and how to do arithmetic in + * that calendar system. + * + * See https://tc39.es/proposal-temporal/docs/calendar.html for more details. + */ + export class Calendar implements CalendarProtocol { + static from(item: CalendarLike): Temporal.Calendar | CalendarProtocol; + constructor(calendarIdentifier: string); + readonly id: string; + year( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): number; + month( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | Temporal.PlainMonthDay + | PlainDateLike + | string, + ): number; + monthCode( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | Temporal.PlainMonthDay + | PlainDateLike + | string, + ): string; + day( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainMonthDay + | PlainDateLike + | string, + ): number; + era( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): string | undefined; + eraYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number | undefined; + dayOfWeek( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + dayOfYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + weekOfYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + yearOfWeek( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + daysInWeek( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | PlainDateLike + | string, + ): number; + daysInMonth( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): number; + daysInYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): number; + monthsInYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): number; + inLeapYear( + date: + | Temporal.PlainDate + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | PlainDateLike + | string, + ): boolean; + dateFromFields( + fields: YearOrEraAndEraYear & MonthOrMonthCode & { day: number }, + options?: AssignmentOptions, + ): Temporal.PlainDate; + yearMonthFromFields( + fields: YearOrEraAndEraYear & MonthOrMonthCode, + options?: AssignmentOptions, + ): Temporal.PlainYearMonth; + monthDayFromFields( + fields: MonthCodeOrMonthAndYear & { day: number }, + options?: AssignmentOptions, + ): Temporal.PlainMonthDay; + dateAdd( + date: Temporal.PlainDate | PlainDateLike | string, + duration: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.PlainDate; + dateUntil( + one: Temporal.PlainDate | PlainDateLike | string, + two: Temporal.PlainDate | PlainDateLike | string, + options?: DifferenceOptions<"year" | "month" | "week" | "day">, + ): Temporal.Duration; + fields(fields: Iterable): string[]; + mergeFields( + fields: Record, + additionalFields: Record, + ): Record; + toString(): string; + toJSON(): string; + readonly [Symbol.toStringTag]: "Temporal.Calendar"; + } + + export type PlainDateLike = { + era?: string | undefined; + eraYear?: number | undefined; + year?: number; + month?: number; + monthCode?: string; + day?: number; + calendar?: CalendarLike; + }; + + type PlainDateISOFields = { + isoYear: number; + isoMonth: number; + isoDay: number; + calendar: string | CalendarProtocol; + }; + + /** + * A `Temporal.PlainDate` represents a calendar date. "Calendar date" refers to the + * concept of a date as expressed in everyday usage, independent of any time + * zone. For example, it could be used to represent an event on a calendar + * which happens during the whole day no matter which time zone it's happening + * in. + * + * See https://tc39.es/proposal-temporal/docs/date.html for more details. + */ + export class PlainDate { + static from( + item: Temporal.PlainDate | PlainDateLike | string, + options?: AssignmentOptions, + ): Temporal.PlainDate; + static compare( + one: Temporal.PlainDate | PlainDateLike | string, + two: Temporal.PlainDate | PlainDateLike | string, + ): ComparisonResult; + constructor( + isoYear: number, + isoMonth: number, + isoDay: number, + calendar?: CalendarLike, + ); + readonly era: string | undefined; + readonly eraYear: number | undefined; + readonly year: number; + readonly month: number; + readonly monthCode: string; + readonly day: number; + readonly calendarId: string; + getCalendar(): CalendarProtocol; + readonly dayOfWeek: number; + readonly dayOfYear: number; + readonly weekOfYear: number; + readonly yearOfWeek: number; + readonly daysInWeek: number; + readonly daysInYear: number; + readonly daysInMonth: number; + readonly monthsInYear: number; + readonly inLeapYear: boolean; + equals(other: Temporal.PlainDate | PlainDateLike | string): boolean; + with( + dateLike: PlainDateLike, + options?: AssignmentOptions, + ): Temporal.PlainDate; + withCalendar(calendar: CalendarLike): Temporal.PlainDate; + add( + durationLike: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.PlainDate; + subtract( + durationLike: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.PlainDate; + until( + other: Temporal.PlainDate | PlainDateLike | string, + options?: DifferenceOptions<"year" | "month" | "week" | "day">, + ): Temporal.Duration; + since( + other: Temporal.PlainDate | PlainDateLike | string, + options?: DifferenceOptions<"year" | "month" | "week" | "day">, + ): Temporal.Duration; + toPlainDateTime( + temporalTime?: Temporal.PlainTime | PlainTimeLike | string, + ): Temporal.PlainDateTime; + toZonedDateTime( + timeZoneAndTime: + | TimeZoneProtocol + | string + | { + timeZone: TimeZoneLike; + plainTime?: Temporal.PlainTime | PlainTimeLike | string; + }, + ): Temporal.ZonedDateTime; + toPlainYearMonth(): Temporal.PlainYearMonth; + toPlainMonthDay(): Temporal.PlainMonthDay; + getISOFields(): PlainDateISOFields; + toLocaleString( + locales?: string | string[], + options?: Intl.DateTimeFormatOptions, + ): string; + toJSON(): string; + toString(options?: ShowCalendarOption): string; + valueOf(): never; + readonly [Symbol.toStringTag]: "Temporal.PlainDate"; + } + + export type PlainDateTimeLike = { + era?: string | undefined; + eraYear?: number | undefined; + year?: number; + month?: number; + monthCode?: string; + day?: number; + hour?: number; + minute?: number; + second?: number; + millisecond?: number; + microsecond?: number; + nanosecond?: number; + calendar?: CalendarLike; + }; + + type PlainDateTimeISOFields = { + isoYear: number; + isoMonth: number; + isoDay: number; + isoHour: number; + isoMinute: number; + isoSecond: number; + isoMillisecond: number; + isoMicrosecond: number; + isoNanosecond: number; + calendar: string | CalendarProtocol; + }; + + /** + * A `Temporal.PlainDateTime` represents a calendar date and wall-clock time, with + * a precision in nanoseconds, and without any time zone. Of the Temporal + * classes carrying human-readable time information, it is the most general + * and complete one. `Temporal.PlainDate`, `Temporal.PlainTime`, `Temporal.PlainYearMonth`, + * and `Temporal.PlainMonthDay` all carry less information and should be used when + * complete information is not required. + * + * See https://tc39.es/proposal-temporal/docs/datetime.html for more details. + */ + export class PlainDateTime { + static from( + item: Temporal.PlainDateTime | PlainDateTimeLike | string, + options?: AssignmentOptions, + ): Temporal.PlainDateTime; + static compare( + one: Temporal.PlainDateTime | PlainDateTimeLike | string, + two: Temporal.PlainDateTime | PlainDateTimeLike | string, + ): ComparisonResult; + constructor( + isoYear: number, + isoMonth: number, + isoDay: number, + hour?: number, + minute?: number, + second?: number, + millisecond?: number, + microsecond?: number, + nanosecond?: number, + calendar?: CalendarLike, + ); + readonly era: string | undefined; + readonly eraYear: number | undefined; + readonly year: number; + readonly month: number; + readonly monthCode: string; + readonly day: number; + readonly hour: number; + readonly minute: number; + readonly second: number; + readonly millisecond: number; + readonly microsecond: number; + readonly nanosecond: number; + readonly calendarId: string; + getCalendar(): CalendarProtocol; + readonly dayOfWeek: number; + readonly dayOfYear: number; + readonly weekOfYear: number; + readonly yearOfWeek: number; + readonly daysInWeek: number; + readonly daysInYear: number; + readonly daysInMonth: number; + readonly monthsInYear: number; + readonly inLeapYear: boolean; + equals(other: Temporal.PlainDateTime | PlainDateTimeLike | string): boolean; + with( + dateTimeLike: PlainDateTimeLike, + options?: AssignmentOptions, + ): Temporal.PlainDateTime; + 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, + options?: ArithmeticOptions, + ): Temporal.PlainDateTime; + subtract( + durationLike: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.PlainDateTime; + until( + other: Temporal.PlainDateTime | PlainDateTimeLike | string, + options?: DifferenceOptions< + | "year" + | "month" + | "week" + | "day" + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.Duration; + since( + other: Temporal.PlainDateTime | PlainDateTimeLike | string, + options?: DifferenceOptions< + | "year" + | "month" + | "week" + | "day" + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.Duration; + round( + roundTo: RoundTo< + | "day" + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.PlainDateTime; + toZonedDateTime( + tzLike: TimeZoneLike, + options?: ToInstantOptions, + ): Temporal.ZonedDateTime; + toPlainDate(): Temporal.PlainDate; + toPlainYearMonth(): Temporal.PlainYearMonth; + toPlainMonthDay(): Temporal.PlainMonthDay; + toPlainTime(): Temporal.PlainTime; + getISOFields(): PlainDateTimeISOFields; + toLocaleString( + locales?: string | string[], + options?: Intl.DateTimeFormatOptions, + ): string; + toJSON(): string; + toString(options?: CalendarTypeToStringOptions): string; + valueOf(): never; + readonly [Symbol.toStringTag]: "Temporal.PlainDateTime"; + } + + export type PlainMonthDayLike = { + era?: string | undefined; + eraYear?: number | undefined; + year?: number; + month?: number; + monthCode?: string; + day?: number; + calendar?: CalendarLike; + }; + + /** + * A `Temporal.PlainMonthDay` represents a particular day on the calendar, but + * without a year. For example, it could be used to represent a yearly + * recurring event, like "Bastille Day is on the 14th of July." + * + * See https://tc39.es/proposal-temporal/docs/monthday.html for more details. + */ + export class PlainMonthDay { + static from( + item: Temporal.PlainMonthDay | PlainMonthDayLike | string, + options?: AssignmentOptions, + ): Temporal.PlainMonthDay; + constructor( + isoMonth: number, + isoDay: number, + calendar?: CalendarLike, + referenceISOYear?: number, + ); + readonly monthCode: string; + readonly day: number; + readonly calendarId: string; + getCalendar(): CalendarProtocol; + equals(other: Temporal.PlainMonthDay | PlainMonthDayLike | string): boolean; + with( + monthDayLike: PlainMonthDayLike, + options?: AssignmentOptions, + ): Temporal.PlainMonthDay; + toPlainDate(year: { year: number }): Temporal.PlainDate; + getISOFields(): PlainDateISOFields; + toLocaleString( + locales?: string | string[], + options?: Intl.DateTimeFormatOptions, + ): string; + toJSON(): string; + toString(options?: ShowCalendarOption): string; + valueOf(): never; + readonly [Symbol.toStringTag]: "Temporal.PlainMonthDay"; + } + + export type PlainTimeLike = { + hour?: number; + minute?: number; + second?: number; + millisecond?: number; + microsecond?: number; + nanosecond?: number; + }; + + type PlainTimeISOFields = { + isoHour: number; + isoMinute: number; + isoSecond: number; + isoMillisecond: number; + isoMicrosecond: number; + isoNanosecond: number; + }; + + /** + * A `Temporal.PlainTime` represents a wall-clock time, with a precision in + * nanoseconds, and without any time zone. "Wall-clock time" refers to the + * concept of a time as expressed in everyday usage — the time that you read + * off the clock on the wall. For example, it could be used to represent an + * event that happens daily at a certain time, no matter what time zone. + * + * `Temporal.PlainTime` refers to a time with no associated calendar date; if you + * need to refer to a specific time on a specific day, use + * `Temporal.PlainDateTime`. A `Temporal.PlainTime` can be converted into a + * `Temporal.PlainDateTime` by combining it with a `Temporal.PlainDate` using the + * `toPlainDateTime()` method. + * + * See https://tc39.es/proposal-temporal/docs/time.html for more details. + */ + export class PlainTime { + static from( + item: Temporal.PlainTime | PlainTimeLike | string, + options?: AssignmentOptions, + ): Temporal.PlainTime; + static compare( + one: Temporal.PlainTime | PlainTimeLike | string, + two: Temporal.PlainTime | PlainTimeLike | string, + ): ComparisonResult; + constructor( + hour?: number, + minute?: number, + second?: number, + millisecond?: number, + microsecond?: number, + nanosecond?: number, + ); + readonly hour: number; + readonly minute: number; + readonly second: number; + readonly millisecond: number; + readonly microsecond: number; + readonly nanosecond: number; + equals(other: Temporal.PlainTime | PlainTimeLike | string): boolean; + with( + timeLike: Temporal.PlainTime | PlainTimeLike, + options?: AssignmentOptions, + ): Temporal.PlainTime; + add( + durationLike: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.PlainTime; + subtract( + durationLike: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.PlainTime; + until( + other: Temporal.PlainTime | PlainTimeLike | string, + options?: DifferenceOptions< + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.Duration; + since( + other: Temporal.PlainTime | PlainTimeLike | string, + options?: DifferenceOptions< + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.Duration; + round( + roundTo: RoundTo< + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "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[], + options?: Intl.DateTimeFormatOptions, + ): string; + toJSON(): string; + toString(options?: ToStringPrecisionOptions): string; + valueOf(): never; + readonly [Symbol.toStringTag]: "Temporal.PlainTime"; + } + + /** + * A plain object implementing the protocol for a custom time zone. + */ + export interface TimeZoneProtocol { + id: string; + getOffsetNanosecondsFor(instant: Temporal.Instant | string): number; + getOffsetStringFor?(instant: Temporal.Instant | string): string; + getPlainDateTimeFor?( + instant: Temporal.Instant | string, + calendar?: CalendarLike, + ): Temporal.PlainDateTime; + getInstantFor?( + 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[]; + toString?(): string; + toJSON?(): string; + } + + /** + * Any of these types can be passed to Temporal methods instead of a Temporal.TimeZone. + */ + export type TimeZoneLike = string | TimeZoneProtocol | ZonedDateTime; + + /** + * A `Temporal.TimeZone` is a representation of a time zone: either an + * {@link https://www.iana.org/time-zones|IANA time zone}, including + * information about the time zone such as the offset between the local time + * and UTC at a particular time, and daylight saving time (DST) changes; or + * simply a particular UTC offset with no DST. + * + * `Temporal.ZonedDateTime` is the only Temporal type to contain a time zone. + * Other types, like `Temporal.Instant` and `Temporal.PlainDateTime`, do not + * contain any time zone information, and a `Temporal.TimeZone` object is + * required to convert between them. + * + * See https://tc39.es/proposal-temporal/docs/timezone.html for more details. + */ + export class TimeZone implements TimeZoneProtocol { + 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( + instant: Temporal.Instant | string, + calendar?: CalendarLike, + ): Temporal.PlainDateTime; + getInstantFor( + 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[]; + toString(): string; + toJSON(): string; + readonly [Symbol.toStringTag]: "Temporal.TimeZone"; + } + + export type PlainYearMonthLike = { + era?: string | undefined; + eraYear?: number | undefined; + year?: number; + month?: number; + monthCode?: string; + calendar?: CalendarLike; + }; + + /** + * A `Temporal.PlainYearMonth` represents a particular month on the calendar. For + * example, it could be used to represent a particular instance of a monthly + * recurring event, like "the June 2019 meeting". + * + * See https://tc39.es/proposal-temporal/docs/yearmonth.html for more details. + */ + export class PlainYearMonth { + static from( + item: Temporal.PlainYearMonth | PlainYearMonthLike | string, + options?: AssignmentOptions, + ): Temporal.PlainYearMonth; + static compare( + one: Temporal.PlainYearMonth | PlainYearMonthLike | string, + two: Temporal.PlainYearMonth | PlainYearMonthLike | string, + ): ComparisonResult; + constructor( + isoYear: number, + isoMonth: number, + calendar?: CalendarLike, + referenceISODay?: number, + ); + readonly era: string | undefined; + readonly eraYear: number | undefined; + readonly year: number; + readonly month: number; + readonly monthCode: string; + readonly calendarId: string; + getCalendar(): CalendarProtocol; + readonly daysInMonth: number; + readonly daysInYear: number; + readonly monthsInYear: number; + readonly inLeapYear: boolean; + equals( + other: Temporal.PlainYearMonth | PlainYearMonthLike | string, + ): boolean; + with( + yearMonthLike: PlainYearMonthLike, + options?: AssignmentOptions, + ): Temporal.PlainYearMonth; + add( + durationLike: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.PlainYearMonth; + subtract( + durationLike: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.PlainYearMonth; + until( + other: Temporal.PlainYearMonth | PlainYearMonthLike | string, + options?: DifferenceOptions<"year" | "month">, + ): Temporal.Duration; + since( + other: Temporal.PlainYearMonth | PlainYearMonthLike | string, + options?: DifferenceOptions<"year" | "month">, + ): Temporal.Duration; + toPlainDate(day: { day: number }): Temporal.PlainDate; + getISOFields(): PlainDateISOFields; + toLocaleString( + locales?: string | string[], + options?: Intl.DateTimeFormatOptions, + ): string; + toJSON(): string; + toString(options?: ShowCalendarOption): string; + valueOf(): never; + readonly [Symbol.toStringTag]: "Temporal.PlainYearMonth"; + } + + export type ZonedDateTimeLike = { + era?: string | undefined; + eraYear?: number | undefined; + year?: number; + month?: number; + monthCode?: string; + day?: number; + hour?: number; + minute?: number; + second?: number; + millisecond?: number; + microsecond?: number; + nanosecond?: number; + offset?: string; + timeZone?: TimeZoneLike; + calendar?: CalendarLike; + }; + + type ZonedDateTimeISOFields = { + isoYear: number; + isoMonth: number; + isoDay: number; + isoHour: number; + isoMinute: number; + isoSecond: number; + isoMillisecond: number; + isoMicrosecond: number; + isoNanosecond: number; + offset: string; + timeZone: string | TimeZoneProtocol; + calendar: string | CalendarProtocol; + }; + + export class ZonedDateTime { + static from( + item: Temporal.ZonedDateTime | ZonedDateTimeLike | string, + options?: ZonedDateTimeAssignmentOptions, + ): ZonedDateTime; + static compare( + one: Temporal.ZonedDateTime | ZonedDateTimeLike | string, + two: Temporal.ZonedDateTime | ZonedDateTimeLike | string, + ): ComparisonResult; + constructor( + epochNanoseconds: bigint, + timeZone: TimeZoneLike, + calendar?: CalendarLike, + ); + readonly era: string | undefined; + readonly eraYear: number | undefined; + readonly year: number; + readonly month: number; + readonly monthCode: string; + readonly day: number; + readonly hour: number; + readonly minute: number; + readonly second: number; + readonly millisecond: number; + 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 hoursInDay: number; + readonly daysInWeek: number; + readonly daysInMonth: number; + readonly daysInYear: number; + readonly monthsInYear: number; + readonly inLeapYear: boolean; + readonly offsetNanoseconds: number; + readonly offset: string; + readonly epochSeconds: number; + readonly epochMilliseconds: number; + readonly epochMicroseconds: bigint; + readonly epochNanoseconds: bigint; + equals(other: Temporal.ZonedDateTime | ZonedDateTimeLike | string): boolean; + with( + zonedDateTimeLike: ZonedDateTimeLike, + options?: ZonedDateTimeAssignmentOptions, + ): Temporal.ZonedDateTime; + 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( + durationLike: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.ZonedDateTime; + subtract( + durationLike: Temporal.Duration | DurationLike | string, + options?: ArithmeticOptions, + ): Temporal.ZonedDateTime; + until( + other: Temporal.ZonedDateTime | ZonedDateTimeLike | string, + options?: Temporal.DifferenceOptions< + | "year" + | "month" + | "week" + | "day" + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.Duration; + since( + other: Temporal.ZonedDateTime | ZonedDateTimeLike | string, + options?: Temporal.DifferenceOptions< + | "year" + | "month" + | "week" + | "day" + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.Duration; + round( + roundTo: RoundTo< + | "day" + | "hour" + | "minute" + | "second" + | "millisecond" + | "microsecond" + | "nanosecond" + >, + ): Temporal.ZonedDateTime; + startOfDay(): Temporal.ZonedDateTime; + toInstant(): Temporal.Instant; + toPlainDateTime(): Temporal.PlainDateTime; + toPlainDate(): Temporal.PlainDate; + toPlainYearMonth(): Temporal.PlainYearMonth; + toPlainMonthDay(): Temporal.PlainMonthDay; + toPlainTime(): Temporal.PlainTime; + getISOFields(): ZonedDateTimeISOFields; + toLocaleString( + locales?: string | string[], + options?: Intl.DateTimeFormatOptions, + ): string; + toJSON(): string; + toString(options?: ZonedDateTimeToStringOptions): string; + valueOf(): never; + readonly [Symbol.toStringTag]: "Temporal.ZonedDateTime"; + } + + /** + * The `Temporal.Now` object has several methods which give information about + * the current date, time, and time zone. + * + * See https://tc39.es/proposal-temporal/docs/now.html for more details. + */ + export const Now: { + /** + * Get the exact system date and time as a `Temporal.Instant`. + * + * This method gets the current exact system time, without regard to + * calendar or time zone. This is a good way to get a timestamp for an + * event, for example. It works like the old-style JavaScript `Date.now()`, + * but with nanosecond precision instead of milliseconds. + * + * Note that a `Temporal.Instant` doesn't know about time zones. For the + * exact time in a specific time zone, use `Temporal.Now.zonedDateTimeISO` + * or `Temporal.Now.zonedDateTime`. + */ + 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. + * + * @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. + */ + 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. + * + * 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` instead of this function. + * + * @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. + */ + 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. + * + * @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. + */ + plainDateISO: (tzLike?: TimeZoneLike) => Temporal.PlainDate; + + /** + * Get the current clock time in a specific time zone, using the ISO 8601 calendar. + * + * @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. + */ + plainTimeISO: (tzLike?: TimeZoneLike) => Temporal.PlainTime; + + /** + * Get the identifier of the environment's current time zone. + * + * This method gets the identifier of the current system time zone. This + * will usually be a named + * {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones|IANA time zone}. + */ + timeZoneId: () => string; + + readonly [Symbol.toStringTag]: "Temporal.Now"; + }; +} + +declare namespace Intl { + type Formattable = + | Date + | Temporal.Instant + | Temporal.ZonedDateTime + | Temporal.PlainDate + | Temporal.PlainTime + | Temporal.PlainDateTime + | Temporal.PlainYearMonth + | Temporal.PlainMonthDay; + + interface DateTimeFormatRangePart { + source: "shared" | "startRange" | "endRange"; + } + + export interface DateTimeFormat { + /** + * Format a date into a string according to the locale and formatting + * options of this `Intl.DateTimeFormat` object. + * + * @param date The date to format. + */ + format(date?: Formattable | number): string; + + /** + * Allow locale-aware formatting of strings produced by + * `Intl.DateTimeFormat` formatters. + * + * @param date The date to format. + */ + formatToParts( + date?: Formattable | number, + ): globalThis.Intl.DateTimeFormatPart[]; + + /** + * Format a date range in the most concise way based on the locale and + * options provided when instantiating this `Intl.DateTimeFormat` object. + * + * @param startDate The start date of the range to format. + * @param endDate The start date of the range to format. Must be the same + * type as `startRange`. + */ + formatRange(startDate: T, endDate: T): string; + formatRange(startDate: Date | number, endDate: Date | number): string; + + /** + * Allow locale-aware formatting of tokens representing each part of the + * formatted date range produced by `Intl.DateTimeFormat` formatters. + * + * @param startDate The start date of the range to format. + * @param endDate The start date of the range to format. Must be the same + * type as `startRange`. + */ + formatRangeToParts( + startDate: T, + endDate: T, + ): DateTimeFormatRangePart[]; + formatRangeToParts( + startDate: Date | number, + endDate: Date | number, + ): DateTimeFormatRangePart[]; + } + + export interface DateTimeFormatOptions { + // TODO: remove the props below after TS lib declarations are updated + dayPeriod?: "narrow" | "short" | "long"; + dateStyle?: "full" | "long" | "medium" | "short"; + timeStyle?: "full" | "long" | "medium" | "short"; + } +} diff --git a/cli/tsc/dts/lib.es2020.intl.d.ts b/cli/tsc/dts/lib.es2020.intl.d.ts index 8f356b4899..9c41b38b2e 100644 --- a/cli/tsc/dts/lib.es2020.intl.d.ts +++ b/cli/tsc/dts/lib.es2020.intl.d.ts @@ -267,7 +267,7 @@ declare namespace Intl { } interface DateTimeFormatOptions { - calendar?: string | undefined; + calendar?: string | (typeof globalThis extends { Temporal: { CalendarProtocol: infer T; }; } ? T : undefined) | undefined; dayPeriod?: "narrow" | "short" | "long" | undefined; numberingSystem?: string | undefined; diff --git a/cli/tsc/dts/lib.es5.d.ts b/cli/tsc/dts/lib.es5.d.ts index 55ce47cade..439ed6b819 100644 --- a/cli/tsc/dts/lib.es5.d.ts +++ b/cli/tsc/dts/lib.es5.d.ts @@ -4474,7 +4474,7 @@ declare namespace Intl { timeZoneName?: "short" | "long" | "shortOffset" | "longOffset" | "shortGeneric" | "longGeneric" | undefined; formatMatcher?: "best fit" | "basic" | undefined; hour12?: boolean | undefined; - timeZone?: string | undefined; + timeZone?: string | (typeof globalThis extends { Temporal: { TimeZoneProtocol: infer T; }; } ? T : undefined) | undefined } interface ResolvedDateTimeFormatOptions { diff --git a/ext/console/01_console.js b/ext/console/01_console.js index ae629a4329..101b7ed1cc 100644 --- a/ext/console/01_console.js +++ b/ext/console/01_console.js @@ -188,6 +188,7 @@ const styles = { regexp: "red", module: "underline", internalError: "red", + temporal: "magenta", }; const defaultFG = 39; @@ -776,6 +777,55 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) { return ctx.stylize(base, "date"); } } + } else if ( + proxyDetails === null && + typeof globalThis.Temporal !== "undefined" && + ( + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.Instant.prototype, + value, + ) || + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.ZonedDateTime.prototype, + value, + ) || + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainDate.prototype, + value, + ) || + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainTime.prototype, + value, + ) || + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainDateTime.prototype, + value, + ) || + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainYearMonth.prototype, + value, + ) || + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainMonthDay.prototype, + value, + ) || + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.Duration.prototype, + value, + ) || + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.TimeZone.prototype, + value, + ) || + ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.Calendar.prototype, + value, + ) + ) + ) { + // Temporal is not available in primordials yet + // deno-lint-ignore prefer-primordials + return ctx.stylize(value.toString(), "temporal"); } else if ( (proxyDetails === null && (isNativeError(value) || diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index e196fd1040..97b4a9531f 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -167,9 +167,10 @@ const unstableIds = { http: 5, kv: 6, net: 7, - unsafeProto: 8, - webgpu: 9, - workerOptions: 10, + temporal: 8, + unsafeProto: 9, + webgpu: 10, + workerOptions: 11, }; const denoNsUnstableById = {};