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

CalendarFieldDescriptors: Require eraYear to be alway positive? #2900

Open
anba opened this issue Jun 19, 2024 · 13 comments
Open

CalendarFieldDescriptors: Require eraYear to be alway positive? #2900

anba opened this issue Jun 19, 2024 · 13 comments
Labels
Milestone

Comments

@anba
Copy link
Contributor

anba commented Jun 19, 2024

CalendarFieldDescriptors:

For example, "era" (with ToString conversion) and "eraYear" (with ToIntegerWithTruncation conversion) are returned when calendar is "gregory" or "japanese" and type is date or year-month or a List containing "year".

Should eraYear require ToPositiveIntegerWithTruncation instead of ToIntegerWithTruncation?

The current SpiderMonkey implementations uses ICU4X, which doesn't allow negative era years. The consensus from #1231 (comment) matches my understanding:

  • year is the algorithmic (signed) year, in order to make it easy to write code using the ISO calendar that "just works" with non-ISO calendars.
  • eraYear is the numeric year within the era.

But the implementation notes from #1231 (comment) suddenly state that negative era years are allowed:

  • [...] eraYear can be negative, for example when referring to dates before the first era.

Maybe this different implementation is because the polyfill accepts eraYear as an equivalent to year (#2870)?

I'd prefer to restrict signed years for algorithmic use to the year property and eraYear to count up from the start of the era.


The polyfill allows negative eraYear inputs in some cases. I'm not sure about the exact rules, but I guess the polyfill allows negative eraYear for all eras but the very first era. For example this works in the polyfill:

// -1 CE, which is resolved to 2 BCE.
Temporal.PlainDate.from({calendar: "gregory", era: "ce", eraYear: -1, month: 1, day: 1})

Whereas this throws:

Temporal.PlainDate.from({calendar: "gregory", era: "bce", eraYear: -1, month: 1, day: 1})
@justingrant
Copy link
Collaborator

justingrant commented Jun 19, 2024

The current SpiderMonkey implementations uses ICU4X, which doesn't allow negative era years.

@sffc How does ICU4X handle far-past years in calendars which have positive-counting (not inverse) eras as their first era? Does it refuse to create dates before the first year of those eras? If not, then eraYear should be able to be negative, right?

@anba
Copy link
Contributor Author

anba commented Jun 19, 2024

@justingrant
Copy link
Collaborator

Looking at the docs for the Ethiopian calendar:

This calendar supports three era codes, based on what mode it is in. In the Amete Mihret scheme it has the "incar" and "pre-incar" eras, 1 Incarnation is 9 CE. In the Amete Alem scheme, it instead has a single era, "mundi, where 1 Anno Mundi is 5493 BCE. Dates before that use negative year numbers.

What is the eraYear in the Amete Mihret scheme for 6000 BCE? I'd assume it's -6 or something like that.

Or should it throw because the world hadn't been created yet so time didn't exist? 😄

@anba
Copy link
Contributor Author

anba commented Jun 20, 2024

The ISO date "-006000-01-01" is resolved to the era year 6009 in the "pre-incar" era.

Output:

AmeteMihret: 6009-6-22 "pre-incar"
AmeteAlem: -508-6-22 "mundi"
use icu::calendar::{Calendar, Date};
use icu::calendar::ethiopian::{Ethiopian, EthiopianEraStyle};

fn main() {
  let iso = Date::try_new_iso_date(-6000, 1, 1).unwrap();

  let styles = [
    EthiopianEraStyle::AmeteMihret,
    EthiopianEraStyle::AmeteAlem,
  ];

  for style in styles {
    let cal = Ethiopian::new_with_era_style(style);
    let date = cal.date_from_iso(iso);
    let era = cal.year(&date).era.0;

    println!(
      "{}: {}-{}-{} {}",
      format!("{style:?}"),
      cal.year(&date).number,
      cal.month(&date).ordinal,
      cal.day_of_month(&date).0,
      format!("{era:?}"),
    );
  }
}

@sffc
Copy link
Collaborator

sffc commented Jun 20, 2024

eraYear can be negative in ICU4X. unicode-org/icu4x#5087

Such years are usually nonsense. But, we've been working for a long time that all ISO dates are representable in all calendars, and calendars just need to do something reasonable (the definition of "reasonable" is a topic for another thread, #2869).

@anba
Copy link
Contributor Author

anba commented Jun 20, 2024

eraYear can be negative in ICU4X. unicode-org/icu4x#5087

This only applies to calendars with a single era, right?

CalendarDateEraYear requires to return undefined for calendars which don't use eras. I'm interpreting this to mean that calendar systems which have a single era (in ICU4X) don't actually use eras. So for example eraYear for the Hebrew calendar should always return undefined in Temporal.

@sffc
Copy link
Collaborator

sffc commented Jun 20, 2024

For some additional discussion on Ethiopian, please see tc39/proposal-intl-era-monthcode#4. I think we probably want to support negative eraYear with mixed eras, definitely on input and probably on output, though I could be convinced otherwise if we can work out Ethiopian. What is the advantage to adding this restriction, though?

@anba
Copy link
Contributor Author

anba commented Jun 20, 2024

I think we probably want to support negative eraYear with mixed eras, [...]

Can you explain "mixed eras"? I'm not sure what you mean and I don't want to misinterpret your comment.

What is the advantage to adding this restriction, though?

Adding this restriction avoids having to define how to interpret inputs like "-100 BCE" or "-123 Reiwa".

@pipobscure
Copy link
Collaborator

It seems to me the issue isn't so much negative eraYears as much as it is eras whose eraYear increase with earlier times and decrease as time moves forward.

So BCE would be a prime candidate as -100 BCE could translate to 100 CE being later.
while the ethiopian calendar example above wouldn't be a good example because the negative eraYears in the earliest era would simply indicate a year beyond eras as a concept.
That in turn is the same dilemma for postive eraYears in the current era as well. Think current regal calendars: we already know that no king/emperor will live in the year 3000 (ISO). But we'd use some high number in the current regal era to represent that none-the-less.

So I think it's more about:

  1. eras in that are not at the end of the range
  2. eraYears that exceed the limits of the era
  3. eraYears progressing counter to ISO timeflow & possibly being negative

Now in my personal view, any calendar should be able to handle those cases smoothly and I'd be surprised if ICU4X didn't do this well already.

@ptomato
Copy link
Collaborator

ptomato commented Sep 19, 2024

Meeting, 2024-09-19: We don't want to add this restriction. So in the Gregorian calendar, an input of -5 CE should resolve to 6 BCE, and an input of -5 BCE should resolve to 6 CE. I'm pretty sure this needs test262 coverage.

We do want to avoid outputting negative eraYear wherever possible, but @sffc noted that currently the Ethiopian calendar requires this.

@ptomato ptomato added this to the Stage 4 milestone Sep 20, 2024
@anba
Copy link
Contributor Author

anba commented Sep 26, 2024

We do want to avoid outputting negative eraYear wherever possible, but @sffc noted that currently the Ethiopian calendar requires this.

FWIW ICU4C and ICU4X don't agree on this. (Bug reports already exist for this.)

ICU4C switches to Amete Alem, whereas ICU4X uses BCE-style backwards counting. Both choices are possible according to [1], for example this article about Alexander the Great uses:

364-331 ዓክልበ.

These dates can easily be verified to match 356-323 BCE.

Or this article about Nebuchadnezzar. The dates there can also easily be matched to the BCE dates given here.

Googling for "ዓክልበ" gives more results, but I can't read Amharic and automatic translation isn't great.

[1] https://de.wikipedia.org/wiki/%C3%84thiopischer_Kalender#Jahresz%C3%A4hlung (English Wiki doesn't have this information.)

@sffc
Copy link
Collaborator

sffc commented Sep 28, 2024

The Gregorian calendar is exceptional in that it has an era that counts backwards. Most calendars only define dates that occur after their epoch. But since Temporal requires that all dates are representable in all calendars, the only natural solution is to print negative numbers for years before the epoch.

I used the ethiopic example because it is a calendar with two eras, but I'm not aware of an era that counts backwards relative to the mundi epoch. The Alexander the Great example is great, but it it is still between mundi and incarnation. Do we have examples of how it behaves on dates before mundi?

@anba
Copy link
Contributor Author

anba commented Sep 30, 2024

The Alexander the Great example is great, but it it is still between mundi and incarnation. Do we have examples of how it behaves on dates before mundi?

That'd mean a third possible option for the Ethiopian calendar:

  1. Before and after incarnation, using BC and AD styles similar to the Gregorian calendar.
  2. Before and after incarnation like in (1), but mundi era for dates before mundi.
  3. After incarnation, otherwise mundi era.

ICU4C uses option (3):

js> new Intl.DateTimeFormat("en-u-ca-ethiopic", {timeZone:"UTC"}).format(new Date("+000008-08-27"))
"1/1/1 ERA1"
js> new Intl.DateTimeFormat("en-u-ca-ethiopic", {timeZone:"UTC"}).format(new Date("+000008-08-26")) 
"13/5/5500 ERA0"
js> new Intl.DateTimeFormat("en-u-ca-ethiopic", {timeZone:"UTC"}).format(new Date("-005493-07-18"))
"1/1/0 ERA0"
js> new Intl.DateTimeFormat("en-u-ca-ethiopic", {timeZone:"UTC"}).format(new Date("-005493-07-17")) 
"13/6/-1 ERA0"

I didn't find many examples for dates before 5500 BC, most Wiki-pages were about later dates. But here are some examples:

Searching for "ዓ.ዓ." (Amete Alem) shows mostly results related to biblical texts, I don't know if this is an indication that there are differences in use for civil and religious purposes.

And there are many examples where "ዓክልበ" and "ዓ.ዓ." are both used to refer to (BCE) dates in the Gregorian calendar:

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

No branches or pull requests

5 participants