⌚ Temporal

Philip Chimento
Igalia, in partnership with Bloomberg
TC39 July 2023

Progress update

  • Presenting integer arithmetic change discussed in previous plenaries
  • Also presenting two normative changes arising from implementor discussions
  • All known discussions settled; these are the last expected changes
  • Implementation continues (JSC, LibJS, SpiderMonkey, V8)

IETF standardization progress (#1450)

  • IETF document currently in last call
  • Some suggestions from area directors, and one complaint
  • Complaint seems to be able to be handled with discussion

Normative changes

Integer math in durations (PR #2612) (1/3)

  • Storage doesn't change; one f64-representable integer for each unit
    • "90 minutes" preserved unless explicitly balanced to "1 hour 30"
  • Calculations with time units (days* through nanoseconds) use "normalized form", s × 10⁹ + ns
    • |s| ≤ max safe integer
    • |ns| ≤ 999,999,999
    • Can be implemented as: i96 ns; i64 s + i32 ns; f64 s + f64 ns
    • At end of calculation, converted back to integer-per-unit for storage

*Why are days a time unit? We allow calculations without calendar, and assume 24-hour days in that case.

Integer math in durations (2/3)

  • Calendar units years, months, weeks, all limited to maxuint32
    • |N| < 2³² for N = y, mon, w
    • Why not maxint32? Because sign is common to all units
    • Implementations can choose to store as u32 instead of f64
  • Note, performing calculations with relativeTo date can still fail
    • 2³²-1 years ≫ representable range
  • With limits, calculations in loops no longer necessary
    • Concern emerged in review of SpiderMonkey implementation

Integer math in durations (3/3)

  • Spec text encapsulates all 96-bit operations in AOs
  • Can be changed editorially to explicitly be 64+32 or seconds+subseconds, if implementations prefer
  • Few observable effects, but some durations no longer allowed
// e.g. no longer allowed:
Temporal.Duration.from({ seconds: Number.MAX_VALUE })
Temporal.Duration.from({
  seconds: Number.MAX_SAFE_INTEGER,
  milliseconds: 1000
})
// Maximum duration now accepted:
Temporal.Duration.from({ years: 2**32-1, months: 2**32-1, weeks: 2**32-1, days: 104249991374,
    hours: 7, minutes: 36, seconds: 31, milliseconds: 999, microseconds: 999, nanoseconds: 999 })
Temporal.Duration.from({ years: -(2**32-1), months: -(2**32-1), weeks: -(2**32-1),
    seconds: -Number.MAX_SAFE_INTEGER, nanoseconds: -999_999_999 })

Limit precision of offset time zones (PR #2607)

  • Offset time zones: e.g., "+01:00"
  • Previously allowed up to ns precision: "+01:00:00.000000001"
  • IXDTF (the IETF string format) does not actually support <minutes precision in these; we overlooked this
  • Better to limit now and relax later, than change IETF at this point
  • Offsets of named time zones can still be <minutes precision
    • e.g. Africa/Monrovia
Temporal.TimeZone.from("+01:00:01")  // no longer allowed

Adjustment of string coercion (PR #2574) (1/2)

  • Some Numbers are valid ISO strings (e.g. 20230711)
  • Some are not (e.g. 05000101 equals 1310785)
  • Concern found through Anba's test cases for Firefox
  • Proposed change: don't use ToString, require primitives to be String
  • Throw TypeError ("wrong type"), not RangeError ("converted to a disallowed string")

Adjustment of string coercion (2/2)

Examples:

Temporal.Calendar.from(10).id
    // Current spec text: "iso8601" (parsed as TemporalTimeString)
    // Proposed: from() throws TypeError
Temporal.TimeZone.from(-10).id
    // Current spec text: "-10:00"
    // Proposed: from() throws TypeError
Temporal.PlainDate.from(20230711)
    // Current spec text: PlainDate of July 11, 2023
    // Proposed: throws TypeError
Temporal.PlainDate.from(true)
    // Current spec text: throws RangeError ("true" is not a valid ISO string)
    // Proposed: throws TypeError

Questions?

Requesting consensus

On the normative changes just presented

Proposed conclusion for the notes

Consensus on making normative changes to:

  • Remove arbitrary-precision integer math and calculations in loops (PR #2612)
  • Limit offset time zones to minutes precision (PR #2607)
  • Require ISO strings and offset strings to be Strings (PR #2574)