⌚ Temporal

Ujjwal Sharma
Igalia, in partnership with Bloomberg
TC39 June 2022

DRAFT

Temporal update

  • Similar to what we asked for consensus on last time!
  • Asking for consensus on several minor normative changes:
    • Changes suggested by implementors ("adjustments")
    • Changes to make spec text accurately reflect the decisions made in the champions group ("bugs")
  • No big discussions this time, just fixes

Temporal update

  • Will continue turning implementor feedback into presentations like this as bandwidth allows
  • Number of normative PRs per plenary meeting still decreasing 📉

IETF update

  • (fill out this slide)

Adjustments

Non-402 impls with calendars (PR #2193)

  • Currently, an implementation that does not have Intl, is constrained to support only the ISO 8601 calendar.
  • Remove this constraint
  • But, require that any supported calendars are from the set supported by Intl. An implementation becoming 402-capable shouldn't remove functionality
Tests: not possible?

Order of operations in dateFromFields (PR #2203)

  • Changes the order of thrown exceptions in a really esoteric case
  • Why do we care about this? It came up in the reviews for Stage 3 but Philip didn't realize it would be observable
  • Makes the spec text a bit nicer
  • In case you care about it:
calendar.dateFromFields({ get year() { throw "not called"; } })
// Before: throws "not called"
// After: throws TypeError due to missing `day` property
Tests: ❌

Bugs

Remove erroneous range check (PR #2189)

  • Faulty range check when parsing Instant strings with UTC offsets
  • Made some valid strings invalid:
Temporal.Instant.from('-271821-04-19T23:00-01:00').epochSeconds
// Current spec text: throws
// Intended: -86400e8
Temporal.Instant.from('+275760-09-13T01:00+01:00').epochSeconds
// Current spec text: throws
// Intended: 86400e8
Tests: ❌

Fix time zone name grammar (PR #2200)

  • Time zone strings with UTC offset time zones not in grammar
  • More invalid strings that should've been valid:
Temporal.TimeZone.from('+05:30')
// Current spec text: throws
// Intended: UTC offset time zone of +05:30
Temporal.TimeZone.from('2022-05-23T17:49-07:00[-07:00]')
// Current spec text: throws
// Intended: UTC offset time zone of -07:00
Tests: ❌

Fix mistake in exact time rounding (PR #2210)

  • Exact times should be rounded as if they are positive numbers, even if they are before the Unix epoch
  • In other words, rounding is relative to the Big Bang, not 1970
inst = Temporal.Instant.from('1969-12-31T23:30Z');
inst.round('hour')
// Current spec text: instant at 1969-12-31T23:00Z
// Intended: instant at 1970-01-01T00:00Z
Tests: ✅

Use null-proto objects in more places (PR #2219)

  • Last time, changed to use null-prototype objects in some places
  • Do the same for other property bags where we create an object and then look up properties on it
  • Also one place where we missed it last time in PlainYearMonth
  • Guards against this kind of shenanigans:
Temporal.PlainDate.from('2022-01-01').with({
  get year() {
    Object.prototype.day = 31;
    return 2023;
  },
});
Tests: ❌

Validate overflow option in from() (PR #2225)

  • Similar to previous item
  • For consistency with property bags, validate overflow option when converting Temporal objects to PlainDate and PlainDateTime
plainDate = Temporal.PlainDate.from({ year: 2022, month: 6, day: 6 }, { overflow: 'bogus value' });
// throws (unchanged)

const plainDateTime = Temporal.Now.plainDateTimeISO();
plainDate = Temporal.PlainDate.from(plainDateTime, { overflow: 'bogus value' });
// Current spec text: normal PlainDate
// Intended: throws RangeError due to `overflow` value

// (Ditto for PlainDateTime.from())
Tests: ❌

Requesting consensus

On the normative changes just presented

Sneak peek for next plenary

Three major pieces of implementor feedback remaining to address:

  • Investigate optimizing the built-in calendar case (issue #1808)
  • Integrate Calendar and TimeZone into Intl.DTF options (#2005)
  • Investigate removing [[Calendar]] slot from PlainTime (#1588)

Finally:

  • Implement conclusions of IETF string standardization (#1450)
  • Fix some other minor errors that you probably don't care about

--- <! _footer: Tests: ❌ > ### Check calendar in PlainTime (PR [#2224](https://github.com/tc39/proposal-temporal/pull/2224)) - For consistency with property bags, check calendar when converting to PlainTime - Only ISO 8601 calendar allowed in PlainTime - Necessary for web-compatibility if PlainTime gets calendar later ```js plainTime = Temporal.PlainTime.from({ hour: 12, minute: 0, calendar: 'gregory' }); // throws (unchanged) const plainDateTime = Temporal.Now.plainDateTime('gregory'); plainTime = Temporal.PlainTime.from(plainDateTime); // Current spec text: normal PlainTime // Intended: throws RangeError, e.g. "only ISO 8601 calendar allowed in PlainTime" // (Ditto for plainDateTime.toPlainTime(), ZonedDateTime.from(), and ZonedDateTime.p.toPlainTime()) ```

--- <! _footer: Tests: ❌ > ### Fix overflow case in Duration.total (PR #0000) - Fix an edge case where the result of `.total()` overflows - Could return ∞ or throw - ∞ is what you'd get if you calculated it yourself ```js Temporal.Duration.from({ microseconds: Number.MAX_VALUE }).total('nanoseconds') // Current spec text: unclear what you should get; fails assertion // After this change: Infinity ```

I hope to present all of these in July. Follow along with the issues if you are interested in these topics.