Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: split option name into disambiguation (for DST) vs. overflow (for ranges) #607

Closed
justingrant opened this issue May 20, 2020 · 12 comments · Fixed by #876
Closed

Comments

@justingrant
Copy link
Collaborator

justingrant commented May 20, 2020

Of all the concepts in Temporal, the one that confused me most was the disambiguation option.

I finally understood today why this confused me so much: there are two somewhat-unrelated questions mapped to one name.

  • How to handle overflow of units like {minute: 66}? Choices are: 'constrain' | 'balance' | 'reject' (or sometimes just 'constrain' | 'reject')
  • How to handle DST ambiguity? Choices are 'earlier' | 'later' | 'reject'.

Did I get this correct? If yes, to remove "disambiguation ambiguity" 😃 my suggestion would be to rename the former usage to overflow which is easier to type and spell and would more clearly explain what the option is doing.

An additional benefit would be avoiding potential future conflict. For example, if we build ZonedAbsolute, then its with method would probably need to offer both overflow and DST-ambiguity handling. Even if we don't want to add such a type now, it's probably unwise to preclude it in the future.

@ptomato
Copy link
Collaborator

ptomato commented May 21, 2020

I wouldn't be opposed to changing the options keyword to overflow for the second sense.

(When these were originally separate arguments as opposed to options keys, it wasn't so important what they were called since you could call them whatever you wanted in your code.)

@justingrant justingrant changed the title Suggestion: clarify the disambiguation option Suggestion: split disambiguation option name into to disambiguation (for DST) vs. overflow (for ranges) May 25, 2020
@justingrant justingrant changed the title Suggestion: split disambiguation option name into to disambiguation (for DST) vs. overflow (for ranges) Suggestion: split option name into disambiguation (for DST) vs. overflow (for ranges) May 25, 2020
@ryzokuken
Copy link
Member

I'm personally in favor of disambiguation. While it's a slightly uncommon word, it means exactly what the parameter does (help Temporal disambiguate between multiple conflicting values) while being general enough to be used across the proposal (as opposed to overflow which is very specific and only applies for a subset of cases).

@justingrant
Copy link
Collaborator Author

Yep, after thinking this over I think the biggest issue with the current naming is potential for future conflict. The particular use case I'm concerned about is a method that converts a {DateTimeLike, TimeZone} pair into an Absolute.

This method would need to have an option to control overflow when converting the DateTimeLike into a valid DateTime AND an option to control DST disambiguation when converting the {DateTime, TimeZone} to Absolute.

If those two options had different names then it'd be easy to combine both options into a single bag, e.g. {disambiguation: 'earlier', overflow: 'reject'}. If the options had the same name, then what would that method's options look like?

The best I've been able to come up with are {disambiguation: {timeZoneOffsetTransition: 'earlier', overflow: 'reject'} } or {timeZoneOffsetTransitionDisambiguation: 'earlier', overflowDisambiguation: 'reject'}. But those seem unnecessarily complex.

Even if Temporal opts not to offer a ZonedAbsolute type (whose from and with methods would need both options), it's likely that someone will want to build an OSS wrapper library that includes a {DateTimeLike, TimeZone} => Absolute method. In either Temporal or OSS, it'd seem better if that method could share the same options types as other methods in Temporal.

@rbuckton
Copy link

rbuckton commented Jun 2, 2020

I was considering something like: { overflow: { disambiguation: 'reject' }, timeZone: { disambiguation: 'earlier' } } for APIs where they are combined. Its somewhat easier to pass around in user code as well:

function f(dateTimeLike, timeZone, options = {}) {
  const dateTime = DateTime.from(dateTimeLike, options.overflow);
  const absolute = dateTime.inTimeZone(timeZone, options.timeZone);
  ...
}

@ptomato ptomato added this to the Stable API milestone Jun 4, 2020
@justingrant
Copy link
Collaborator Author

@rbuckton I was considering something like: { overflow: { disambiguation: 'reject' }, timeZone: { disambiguation: 'earlier' } } for APIs where they are combined.

Yep, that's an OK workaround for userland libraries' internal use, but if options are exposed to users (either in a future Temporal type or in a userland library) then it's still a lot more ergonomic to use different property names. For example, using different property names is over 70% more typing:

{ overflow: { disambiguation: 'reject' }, timeZone: { disambiguation: 'earlier' } }
// vs. 
{ overflow: 'reject' , disambiguation: 'earlier' }

Seems unwise to restrict Temporal to the +70% syntax for any future additions that may require multiple options, or to force userland libraries to choose between ergonomics vs. matching Temporal's options syntax.

Also, the philosophy of Temporal is to use strong typing to avoid ambiguity, so it's unexpected that we're not following the same strong-typed path with options types.

Finally, now that disambiguation: 'balance' is gone from all non-Duration types' from and with options, then the from and with option isn't really doing any "disambiguation" any more. It's simply deciding if invalid values should throw or clamp.

For these reasons, I still encourage renaming this option to overflow.

@ptomato
Copy link
Collaborator

ptomato commented Aug 3, 2020

I think now that we have decided to add LocalDateTime, this becomes necessary?

@ryzokuken
Copy link
Member

Using overflow and disambiguation seems to be a good choice as outlined by @justingrant already.

@justingrant
Copy link
Collaborator Author

In 2020-08-13 meeting, this change was approved. Specifically:

  • Usage of disambiguation for DST will be retained as-is
  • All other usage of disambiguation will be renamed to overflow.

@ptomato - this will be a straightforward to PR but massive: ~100 files, 1500+ replacements. I'm happy to PR it but it will probably have many merge conflicts with your Negative Durations PR #811. Should we wait to PR this overflow change until your PR is merged, or is it better to make this overflow change first and adapt #811 to use the new overflow name before it's merged?

@ptomato
Copy link
Collaborator

ptomato commented Aug 13, 2020

I don't mind rebasing #811, but I would hope that the it's close enough to merging now anyway that it wouldn't be an issue.

@justingrant
Copy link
Collaborator Author

Agreed. Let's merge #811 first. Once #811 is merged I'll prepare a PR for this big rename.

@ptomato
Copy link
Collaborator

ptomato commented Sep 3, 2020

@justingrant #811 is merged now, so this can start. Happy to leave the PR to you, or I can take this one if you're busy.

@justingrant
Copy link
Collaborator Author

@ptomato - If you could take this one that'd be great. My kids just started school and my free time is looking like it's going to be limited over the next few weeks between tech support, homework support, and emotional support for the joy that's remote schooling. ;-) Also this will give me more bandwidth to wrap up remaining LocalDateTime issues (esp. the algorithm testing with the JSCalendar folks). Thanks!

Here's some minor help: the TS declaration from #700 for the new option. I assume we'll want a separate DurationOverflowOptions too.

export interface OverflowOptions {
  /**
   * 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';
  // Assuming name change from `disambiguation` to `overflow`. See #607.
}

ptomato added a commit that referenced this issue Sep 4, 2020
"Overflow" is how to deal with out-of-range values for a particular unit
(for example, minute 61, or day 0 of the month.) "Disambiguation" is how
to deal with skipped or double wall clock times during time zone
transitions. Previously, they were both called "disambiguation".

This split is necessary, because for the zoned type being added, we will
need to provide both options to the same function call.

Closes: #607
ptomato added a commit that referenced this issue Sep 10, 2020
"Overflow" is how to deal with out-of-range values for a particular unit
(for example, minute 61, or day 0 of the month.) "Disambiguation" is how
to deal with skipped or double wall clock times during time zone
transitions. Previously, they were both called "disambiguation".

This split is necessary, because for the zoned type being added, we will
need to provide both options to the same function call.

Closes: #607
ptomato added a commit that referenced this issue Sep 10, 2020
"Overflow" is how to deal with out-of-range values for a particular unit
(for example, minute 61, or day 0 of the month.) "Disambiguation" is how
to deal with skipped or double wall clock times during time zone
transitions. Previously, they were both called "disambiguation".

This split is necessary, because for the zoned type being added, we will
need to provide both options to the same function call.

Closes: #607
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants