-
Notifications
You must be signed in to change notification settings - Fork 155
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
What about the default calendar? #292
Comments
I want to suggest that, rather than a broad survey like @codehag created for the pipeline operator, we focus on some targeted outreach to developers who work with various non-ISO calendars and locales. This may be more in the form of interviews rather than a survey, since this information is pretty detailed. I met one such developer, and wrote about his feedback in #268 (comment) (sorry for posting on the wrong issue); my overall impression is that any of 1-4 would be acceptable for his needs, which span both Gregorian and Hijri (Islamic) calendars. |
Sorry i totally missed this issue. Happy to help where I can though. |
Yes I agree with @littledan in addition I'd ask people about their circumstance. I believe knowing whether respondents regularly deal with differing calendars will be a key input. |
See also my PR in #309 |
We've been thinking about this for a while. Now that we have an extensive cookbook, and the polyfill for non-Gregorian calendars is coming along, I think we're coming to the understanding of the design space where we could really come to a decision, based on consulting with more people. |
I've updated calendar-draft.md in #590 with relevant cookbook changes and some new material in the default calendar explainer, including a closer look at the different factory methods used for constructing Temporal types. |
@sffc requested specific feedback on each of the 6 options, considered individually, so here's mine. I'd like to preface it by saying that I do see disadvantages in each of the options, so to me the question is picking the one with the least serious disadvantage.
Here's approximately how I'd weight the various criteria that the proposals are validated by:
I can make a pull request to calendar-draft.md showing how I'd change the emoji faces in the table if anyone wants that, but hopefully this illustrates my opinion. |
I agree with all the points that @ptomato mentioned above, and his weighing of them. I want to mention a few more disadvantages of option 4, which I've mentioned in some calls but don't think I properly wrote down anywhere:
Across options 2, 3, 5 and 6, there is a common API design principle that, if we ask developers to explicitly invoke the "iso" calendar in one way or another, then that will lead to a decision point from them. I share @ptomato 's skepticism about what this would mean in practice--I think the meaning of this would remain confusing to many programmers, and wouldn't constitute a choice point in practice. However, this is just a hypothesis, which we might investigate by talking to more programmers, distributing sample implementations/documentation for API alternatives, etc. Among options 2, 3, 5 and 6, I prefer 6--I think it has the lowest syntactic overhead in practice, and it still meets the goal of "providing an explicit choice point", if that's taken to be a goal. The alternate naming that @ptomato proposes in option 6 seems interesting to me--this alternative option 6 would still create a situation where, in the documentation listing, tab completion for methods, etc, you see an option where there's an explicit calendar parameter, so this may still lead developers to invoke the right calendar-specific APIs. Option 6 seems to me like, at worst, a very minor source of slight ugliness compared to Option 1. Overall, I prefer option 1, but the only option I am very strongly concerned about is option 4. |
I think the high-order bit for defaults is (as @littledan notes above) that calendar defaults are nuanced and can affect application logic more than other localization domains. By contrast, a "default locale" is simpler, e.g. Japanese user only wants to see Japanese text or number formats. In that case, a developer's job is mostly to pass the right locale parameter to the right APIs, but otherwise their application logic could be almost identical across locales. I don't think calendars will ever work like that. In markets using non-ISO calendars, both developers and end-users must navigate the complexity of local and/or ISO calendars used depending on the user (e.g. young vs. old users) or the app (e.g. government websites vs. ecommerce). A "default calendar" at the user or app level may not really exist. It could be a toggle, like @littledan's Jordanian friend describes. Or could even be 2 calendars side-by-side in the same UI. Also, I think it's important to think of defaults in context of which users will need them:
With those customer profiles in mind, here's some specific suggestions:
const WesternTemporal = Temporal;
const HijriTemporal = Temporal.withCalendar('hijri');
const HijriDateTime = HijriTemporal.DateTime; Overall I agree with @littledan's and @ptomato's prioritization so I won't rehash the pro/con arguments for each option, other than to be careful not to make an already-complex API even more complicated for the vast majority of developers who only use ISO. |
Meeting, May 28: We'll initially ship the polyfill with option 1 (default is full ISO) with the understanding that it is revisited for Stage 3 based on feedback. It would be helpful to think about how we can most effectively gather that feedback (talk to individual developers using these calendars?) and what sort of feedback would change our minds vs. what sort of feedback would not. |
(Moving to Stage 3 milestone since option 1, like 2 or 6, doesn't require writing any significant extra code, I'll just implement it that way in the calendar branch) |
This implements "option 1" for the default calendar, which is defaulting to the full ISO 8601 calendar everywhere. We add optional calendar parameters to Temporal.Absolute.prototype.inTimeZone, Temporal.now.date, Temporal.now.dateTime, and Temporal.TimeZone.prototype.getDateTimeFor. See: #292.
This implements "option 1" for the default calendar, which is defaulting to the full ISO 8601 calendar everywhere. We add optional calendar parameters to Temporal.Absolute.prototype.inTimeZone, Temporal.now.date, Temporal.now.dateTime, and Temporal.TimeZone.prototype.getDateTimeFor. See: #292.
This implements "option 1" for the default calendar, which is defaulting to the full ISO 8601 calendar everywhere. We add optional calendar parameters to Temporal.Absolute.prototype.inTimeZone, Temporal.now.date, Temporal.now.dateTime, and Temporal.TimeZone.prototype.getDateTimeFor. See: #292.
Some ideas stemming from discussions in last Friday's meeting: First, we decided to add (see #625) an Second, in Friday's meeting we discussed using an ESLint rule to catch cases where users specify string or object literals without specifying a calendar. The more I thought about this approach, the more I liked it, because ESLint rules are highly configurable. The developer could dial up or dial down the "strictness" of the rule, e.g. whether to require the a calendar to be explicitly specified for object bags vs. strings vs. now() vs. toLocalDateTime/toDateTime. If we had such a lint rule, @sffc how would you feel about // 2 required parameters, so object bag required
absolute.toLocalDateTime({timeZone: 'America/Los_Angeles', calendar: 'iso8601'});
// optional calendar, so can provide only a string
absolute.toLocalDateTime('America/Los_Angeles'); |
Works for me.
I would rather not rely solely on ESLint rules to enforce best i18n practices. The comment I made about strings is intended as a general comment about strings in code. My hope is that as more platforms adopt our convention for expressing calendars in strings, issues involving strings will diminish over time. I also acknowledge the brevity argument, since it is the number 1 complaint about Temporal overall. However, I do think that this particular case warrants the extra code. It's now the one and only place where we're still talking about making the calendar a required option, and I think it will go great lengths to help developers understand this crucial difference between Absolute and the rest of Temporal. I would likely be happy with |
Okay. Here is my latest proposal, based on a synthesis of suggestions from @justingrant, @macchiati, and @pipobscure. Thanks everyone for hanging with me over the last several months. I truly hope that this solution makes everyone happy. Instant → LocalDateTimeSince this is the only transition that adds a calendar field to the Temporal data model, it is the one and only transition that needs to get a calendar from somewhere. My proposal is to have two methods:
Temporal.nowThis is a situation where the current time and time zone already come from the environment, so it makes intuitive sense that the calendar system also come from the environment. However, @littledan feels strongly that the ecosystem for user preferences hasn't evolved far enough yet to make the environment calendar high quality. I therefore propose two separate pieces:
Temporal.*.from(string)As discussed in #293, I am engaging the Calsify group in IETF to discuss an extension to RFC 3339 that adds support for IANA time zone identifiers as well as calendars. As more of the ecosystem adopts this convention, strings are more and more likely to contain the correct calendar information when that information is pertinent. Therefore, I do not feel it is warranted to have a separate calendar argument in this method. Temporal.*.from(fields)@ptomato astutely observed that at the point when the field object is created, the calendar system was already considered. For example, if a developer wrote Therefore, I do not feel it is warranted to have a separate calendar argument in this method. |
2020-09-18: Consensus on #292 (comment), with the following amendment: keep // Current date in the ISO calendar
Temporal.now.dateISO();
Temporal.now.date({ calendar: "iso8601" });
Temporal.now.date("iso8601"); // shortcut according to #889
// Current date in the Hebrew calendar
Temporal.now.date({ calendar: "hebrew" });
Temporal.now.date("hebrew"); // shortcut
// Current date in the environment calendar
Temporal.now.date({ calendar: new Intl.DateTimeFormat().resolvedOptions().calendar });
Temporal.now.date(new Intl.DateTimeFormat().resolvedOptions().calendar); // shortcut
// Throws an exception: calendar must be provided
Temporal.now.date() |
…te() This also requires switching the order of the arguments so that the calendar comes before the time zone, which is still optional. See: #292
Convenience methods that give the current date and datetime in the ISO 8601 calendar. See: #292
Convenience method that does the conversion in the ISO 8601 calendar. Also adds Instant.toZonedDateTimeISO() to the documentation, even though it is not implemented yet. See: #292
…te() This also requires switching the order of the arguments so that the calendar comes before the time zone, which is still optional. See: #292
Convenience methods that give the current date and datetime in the ISO 8601 calendar. See: #292
Convenience method that does the conversion in the ISO 8601 calendar. Also adds Instant.toZonedDateTimeISO() to the documentation, even though it is not implemented yet. See: #292
Calendar support has landed in Temporal. Now we need to decide on the default calendar.
Option 1 is for the API to always assume the ISO (Gregorian) calendar. The programmer can opt-in to an alternative calendar system, but the API doesn't nudge them to do the right thing when a non-Gregorian calendar should actually be used.
However, it is bad i18n practice to assume that dates should be represented in the Gregorian calendar by default.
I have presented several ways that we could improve the API to nudge developers to do the right thing when it comes to non-Gregorian calendars:
Intl.defaultCalendar
(a new symbol), or ISO if that field doesn't exist.Intl.defaultCalendar
in Temporal.now, and explicit elsewhere. See What about the default calendar? #292 (comment)More details on these six options is documented in the explainer doc: https://github.com/tc39/proposal-temporal/blob/main/docs/calendar-draft.md#default-calendar
The text was updated successfully, but these errors were encountered: