Proposal-temporal: Document motivation for choice of types

Created on 29 Oct 2018  Â·  12Comments  Â·  Source: tc39/proposal-temporal

The choice of types supported seems to be the biggest design decision in this proposal. I'd be interested to understand better what led to the resolution of https://github.com/tc39/proposal-temporal/issues/7 and the omission of a Duration type (which a few people have asked me about, and which even comes up in the W3C TAG's design principles). Is the rationale documented anywhere?

documentation

Most helpful comment

@kaizhu256 The same advantage any type has over a plain json object; it gets to more easily carry identity, as well as shared behavior methods. Business logic and general purpose programming are very much a common use case for JS, and serialization is achieved with a toJSON method - there’s no need to constrain things to a plain object.

All 12 comments

what advantage does a Duration-type have over plain-JSON object? e.g.

{
    "months": 2,
    "days": 21,
    "seconds": 26
}

again, the common use-case for data in javascript-land is weighted more towards serialization/baton-passing (via JSON), rather than for low-level business-logic/general-purpose-programming.

@kaizhu256 The same advantage any type has over a plain json object; it gets to more easily carry identity, as well as shared behavior methods. Business logic and general purpose programming are very much a common use case for JS, and serialization is achieved with a toJSON method - there’s no need to constrain things to a plain object.

I definitely like how things like the plus method take a plain JS object rather than forcing an overkill duration object. However, it's interesting how that linked page recommends using numbers of milliseconds for durations; I think it'd be worth thinking about whether we want to continue recommending that.

Durantion could implement same interface used by .plus’s param, having Duration type doesn’t block using plain object in .plus.

It’s good to have Duration, as Duration has its own calculation (plus, minus), and its own ISO string representation.

But it seems OK to have it in further proposals.

i prefer milliseconds, with support for seconds as extra-sugar (internally just multiply by 1000, which is easier than dividing by 1000):

  1. temporals are never going to completely replace millisecond-based Date's ecosystem (just like promise/async/await will never completely replace callbacks, fat-arrow will never replace function, es-module will never replace commonjs, etc...). in the web-reality where temporals and Date are forced to coexist/interoperate forever (regardless of what tc39 fantasizes in lalaland), you should try and make the two as compatible with each other as possible - hopefully a lesson learned by tc39 from the es-module fiasco.

  2. millisecond is the most useful timing-unit in web-development for measuring UX performance metrics. additionally, nanosecond usage is uncommon, and its precision is not meaningful to most web-developers besides hackers so it should be optional, rather than basic unit.

I’ve a good example for why it’s bad to use millisecond as Duration working with Date:

Say, we have a now Date: “const now = new Date”. Then what’s the Date corresponding to “now” of tommorow? You may say it’s “new Date(now + 246060*1000)”. But it’s not always correct, considering the transition day of DST, which has 23 or 25 hours in a day.

Sorry for the briefness and ugly format as typing in phone.

i don't see how the DST argument is in favor of seconds over milliseconds. both have the same problem.

and trusting opaque Duration-types to magically handle DST/leap-year/leap-seconds for us is going to create more hard-to-find bugs, than solutions. explicitly handling those inconsistencies with easy-to-inspect JSON-objects is far easier to debug from web-integration perspective.

The example is for milliseconds v.s. Duration, not for second v.s. millisecond, nor plain object v.s. Duration.

There is no magic behind Duration type, it just contains common manipulations & calculations for the plain { years, months, days, ... } in its prototype.

There is no magic for DST, leap year, leap second too. It’s just abstraction of human’s understanding of duration. When we say, “one month later”, it’s the same time of same day of next month, though it correponds to different count of milliseconds for different “now”. For result out of scope, like “one month later of Jan 31”, surely we could have different strategy as options. And that’s the problem you need to consider when using plain object/milliseconds too. Difference here is plain object/milliseconds are enforcing the implementation of the strategies at user land instead of inside the engine, which means more error-prone.

There are, however, two interpretations of a Duration: fixed-time durations ("2 hours and 15 minutes"), and relative-period durations ("next month" or "in two years"). Fixed-time durations can easily be represented as milliseconds, but are only ever useful at small time-scales (hours, minutes, seconds, etc.). This is because an hour is always 60 minutes, a minute is always 60 seconds (aside from leap seconds), etc. However fixed-time durations do not work at large time-scales (days, months, years, centuries, etc.) because the meaning of "2 months" cannot be fixed without a relative starting point. "2 months" from January 10th, 2019 is _not_ the same number of fixed-time units (i.e. milliseconds) as "2 months" from January 10th, 2020 due to leap-year calculations. In Java they use Duration for fixed-time, and Period for relative-time because of these inherent differences.

Fixed-time durations are _easy_, and most developers don't struggle with them. Relative-period durations are _complicated_, and most developers _do_ struggle with them (at least, when there isn't a reliable API they can leverage).

I for one would _like_ to see a Duration type, as I have had need of it for a number of cases:

  • Serialize/deserialize in a consistent manner (i.e. the ISO duration P6Y3M4D or PT5H3M2S)
  • Perform duration arithmetic (i.e., add two durations together, scale a duration, compare two durations)
  • Calculate a duration as a difference between two temporals (i.e. "how many days between X and Y?")
  • Define temporal intervals (start/end, start+duration, end-duration), and repeating intervals (i.e. "every 3rd Friday")

That said, since the plus API can accept any object with the right properties, its certainly possible a userland Duration type could satisfy those use cases. However, it does seem to be a gap in the API.

@pipobscure could you please take care of this?

The idea here is that we will have a Duration type that is created via the minus method on temporal objects. Depending on the origin objects, the underlying value can be represented for both long-term as well as fixed-time.

In terms of what plus accepts, we have concluded that we want to fully support POJOs with the right properties. We call those a DurationLike. The first step in the plus casts this to a Duration which normalizes all values to positive integers.

I think https://github.com/tc39/proposal-temporal/blob/main/mentalmodel.md does a great job of describing the motivation for the design of this proposal. We could continue to debate the design for Duration, but I think that's best done in another thread.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mj1856 picture mj1856  Â·  7Comments

ptomato picture ptomato  Â·  5Comments

pipobscure picture pipobscure  Â·  6Comments

Ms2ger picture Ms2ger  Â·  6Comments

justingrant picture justingrant  Â·  4Comments