Skip to content

March 2025 era code discussion #25

@sffc

Description

@sffc

We had a joint Temporal-ICU4X call today in order to discuss how to move forward with the era codes. Notes below.

  • @sffc (explains the situation)
  • @Manishearth The main reason I remember about why we landed with what we had is that the "gregory" era always means the same date.
  • @sffc I wanted (y, m, d, era) to be a 4-tuple that specifies a date. but i'm ok with it being a 5-tuple
  • @robertbastian It is a 4-tuple in single-era calendars. Many calendars are single-era, and we should not assign identifiers to these eras, nor ask for them in APIs
  • @Manishearth Do we want to support era codes in single-era calendars at all, or just like return None? Chinese and Korean don't have the eras. It's unclear that we need codes for them.
  • @hsivonen The Common Era in Gregorian is the same as the Common Era in Japanese as a fallback, and it is also a subset of the single era of the ISO calendar. What's the philosophy of calendars that share an era like Gregorian and Japanese?
  • @nekevss Regarding the 4-tuple/5-tuple, I think of a 4-tuple in the context of a calendar. It comes up when resolving fields in Temporal.
  • @sffc It's not actually true these calendars don't have two eras, e.g. the islamic calendar can talk about dates before it. There are some single era calendars where the count backwards may be needed.
  • @justingrant About single-era calendars: for callers of Temporal APIs, I would worry a little bit about not returning era codes as strings. Always having a string in the era field is good for consistency.
  • @robertbastian Can it be an optional string?
  • @justingrant It still makes it less predictable. Most developers will take it and move it somewhere else. I guess having null or None makes it more clear that it is a single-era calendar? But just returning a string, and then storing the string in a database, seems like a more common use case.
  • @hsivonen There are 3 kinds of single era calendars. There's ISO, "by definition". There are calendars, like Hijri, which arguably should be having BH (cldr bug?), and then the chinese case where the calendar has a number of competing eras and CLDR picks a computational one without really picking favorites. Is it a CLDR bug to not to have before-epoch eras in calendards that conceptually look like they could have a "before" era defined?
  • @Manishearth What @sffc said isn't consistent with what I learned; people don't use these calendars to talk about dates before their era. It's unclear. That's often the case: the calendars can talk about dates before their era but people don't consistently do that.
  • @robertbastian Gregorian is also sort-of a single era calendar. Only Ethiopic and Japanese have multiple eras where one of the eras has a limited positive range. Maybe we just model BC as the negative of AD.
  • @pipobscure I agree that we should have the era specified all the time in order to make it easier to handle the API. If you are storing the data, missing/null fields are always problematic. If you're transporting this data, it makes it easier if you have something there. For consistency sake.
  • @sffc About missing values: we should define a string for these. Environments don't need to agree on how to use them. But we should make them available.
  • @sffc About the 4-tuple vs 5-tuple: one can merge the 5-tuple down to a 4-tuple by merging the era code and calendar code, and if the era code is the singleton era, it can be elided.
  • @sffc Another value for how we picked the names we have: we wanted to avoid Gregorian favoritism.
  • @robertbastian: Want to respond to "absent values being problematic", they may be in JS, they certainly aren't in Rust. If we make the era code optional, you can still inject an AH string. You can do different things in temporal because everything needs to be a pile of strings. We don't need to define names in CLDR for singletons. I don't think we need to align here.
  • @Manishearth all of this is about what we reject and accept. if we start accepting BH, do we reject negative AH? I'm opposed to choices where we reject certain patterns that will only come up in uncommon cases
  • @justingrant: I agree that "always except none" for single era calendars is good. Be permissive. I like Shane's pattern of using gregory-ce isn't bad. Finally relating to optional names: no strong opinions on Rust, if it returns None, would be great if there were a source of single era names exposed other way.
  • @nekevss: No issure returning None. Kinda like the idea that if you're calling an era, it's always a calendar-era. Makes sense to associate calendar with it.
  • @hsivonen: What do we mean by avoiding gregorian favoritism, and how does that gel with user experience, given that Gregorian is way more common than anything else
  • @sffc Here's a proposal.
    • Every calendar has a default era, which is the one that defines the extended year for that calendar.
    • If the era is null, it is assumed to be the default era. Implementations are not required to accept null.
    • The string "primary" is also universally accepted for the default era.
    • CLDR defines lots of aliases and accept them as input.
    • CLDR defines on a case-by-case basis what the return values should be for the eras. We will generally prefer well-known English/Latin standard or short names.
  • @robertbastian Defining eras for the Hijri calendars is imposing a Gregorian concept on them. The calendar has a year number that just runs forever. Hijri, Buddhist, and Chinese just do not use eras.
  • @hsivonen How about the calendar name hyphen era name?
  • @sffc I'm proposing a scheme for the calendar-specific era code only. Calendar-hyphen-era could be specified semarately. I'm not proposing that at this time
  • @sffc Chinese is a cyclic calendar. It sounds like @robertbastian is proposing we have three categories: era calendars, cyclic, and singleton.
  • @Manishearth It depends on whether we define eras based on a formatting concern or a data concern. It's not clear whether the Hijri era "behaves" like an era.
  • @hsivonen Since these era names exist for disambiguating the calendar, and that they have names for formatting, and they have names on wikipedia... it's not particularly useful to argue that they don't exist. But they do have well-known names, so they exist in that sense.
  • @robertbastian I think @sffc's proposal is very Temporal-focused. In Rust, the era should not be a string you need to validate and check. It should be an enumeration. Or for singleton calendars, there should just not be an era on the API. So in general I don't like that we pass these as strings; it strikes me as a JS issue bleeding into Rust.
  • @justingrant I agree with @robertbastian that enums seem fine in Rust. I want to reiterate that there should be some centralized mapping of the strings for eras. I don't think implementations should be able to define separate strings.
  • @sffc We could introduce enums, sure, in the future. Months would also be enums. But we still need the cross-calendar date_from_codes.
  • @robertbastian date_from_codes is a Temporal thing, not an ICU4X thing.
  • @Manishearth (a) i think it is better for cldr to maintain a list over temporal, if temporal if needs it. (b) i think icu4x should try to be helpful to temporal
  • @justingrant I agree with @Manishearth... there should be one place in the ecosystem where the resolution takes place. We shouldn't push the resolution into the client. We should keep it in the core library, one place.
  • @nekevss When I was talking about resolution earlier, I was talking about date_from_codes. I think it is an important code path. That's our way in to ICU4X. Unless they're going in through a specific constructor, most APIs end up using it. I don't think date_from_codes should be in temporal_rs. I would prefer to centralize it in ICU4X.
  • @robertbastian CLDR didn't have strings for era codes for the first 20 years of its existence. They were added for Temporal. I don't understand why they can't live in Temporal.
  • @nekevss We need translations from strings. But enums as a lower-level type are great.
  • @robertbastian I don't think CLDR should define a mess of aliases
  • @pipobscure Every group is saying "not me" for defining these.
  • @Manishearth I agree that we don't have an intrinsic need. But we also want to support Temporal.
  • (missed)
  • @Manishearth: Probably we should emit none for monoera calendars as well. Add a centralzied way for querying all eras as Justin previously requested

Proposal:

  • Recommend the following to the Temporal Era Month Code proposal, which will likely be reflected in CLDR:
    • Every calendar has a default era, which is the one that defines the extended year for that calendar.
    • The absence of an era on input is resolved to be the default era.
      • Temporal may define a string such as "primary" that is universally accepted for the default era. To be discussed with the Temporal champions. However, this string will not be accepted by ICU4X; None should be favored.
    • CLDR defines input aliases. The exact aliases are not in scope of this proposal; only that a set of aliases may continue to exist.
    • CLDR defines what the canonical names should be for the eras. We will generally prefer well-known English/Latin standard or short names.
      • Principles:
        • No era code other than null for cyclic calendars that have no eras
        • Where there is a well known latin/english standard, preferably short name, we use it.
      • For example (not binding):
        • bce/ce, ah, am, ap, be, saka, minguo
        • Ethiopic: am/ad? needs research
        • Coptic: bd/ad?
  • In ICU4X, keep date_from_codes that implements this. It accepts an Option<&str>. If the option is None, it is the default era defined above.
  • Consider adding calendar-specific enum-based APIs to ICU4X in the future

LGTM: (@Manishearth) @sffc @pipobscure @justingrant @nekevss @gibson042 (@robertbastian)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions