Skip to content

Conversation

@robertbastian
Copy link
Member

Currently we only support the r symbol for cyclic calendars, however nothing in the LDML says that it is only usable with cyclic calendars. This adds support for all other calendars.

///
/// Lunar calendars, like [`Hijri`](crate::cal::Hijri), drift quickly through the Gregorian year, so related Gregorian
/// years are frequently repeated.
pub fn related_gregorian(self) -> i32 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that it's allowed to be negative (no eras), this should be ISO year, yes? or gregorian extended year.

I agree that hte "ISO calendar" isn't the most consistent concept, but "ISO year" is much more well defined

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLDR calls it "related Gregorian" year

ISO is a format, Gregorian is a calendar. I will die on this hill

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's what CLDR calls it fair enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gregorian does not have signed years.

It has extended years; you could call it related_extended_gregorian but I don't think anyone wants that.

Plus, we already call it related_iso for cyclic years. You're the king of consistency.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to deprecate any mentions of related_iso

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ISO is a format

ISO-8601 defines a calendar system, not just a format.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it defines a string format for the proleptic Gregorian calendar

Copy link
Member

@sffc sffc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in CLDR, but it seems to have footguns. We shouldn't add new things that have known footguns.

}
}

/// The Gregorian year in which this year started.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Observation: This produces surprising results for calendars with new years in the second half of the year, like Hebrew, Ethiopian, Coptic. It also means that multiple Hijri years will have the same related ISO year.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@sffc sffc Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, and I consider it a footgun. It is there because of Chinese, and it has a definition for other calendars, but that doesn't mean it should be used by those other calendars.

For Hebrew, I did some research with help from Gemini and found that there are a number of sources that use the later of the two years since it has more overlap (5786 <-> 2026, not 2025). For example:

https://web.library.yale.edu/cataloging/hebraica/about-hebrew-calendar

However, most sources write it as "2025-2026"

https://www.judaicaplace.com/jewish-year-calendar-5786-2025-2026-spiralbound/767278911413/

So in that sense, maybe r should print 2025-2026.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to take that up with CLDR? this PR moves towards parity with ICU and implements the spec

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's long been a principle that we don't implement spec that we know is garbage.

Sometimes we accidentally implement spec that we didn't know was garbage and it's almost always been a pain point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: is there data in CLDR that is impacted by this? As in, are there Hebrew formatting patterns that use this? (I can go searching, but I suspect that answer to already be known). That impacts how much our choices matter here. If there is no such data we can start by documenting this as "The related ISO year, this is currently the ISO year in which this calendar year started, but we may tweak this definition later" and then pursue proper resolution in CLDR.

Also, what I see here is that if the spec is garbage, it's not necessarily garbage in a "simple" way, it's garbage in an architecturally-relevant way that we may not be able to quickly work around. A good design here would probably allow the symbols {r}, {r +1}, and {r - 1}, so Chinese calendars could use {r} and Hebrew calendars could use {r - 1} - {r} (or whatever, as needed). The needs of Chinese and Hebrew are different here.

I'm in favor of bopping this to CLDR, landing the code as-is with documentation saying that it may change.

Overall I would prefer to not delay proper Chinese formatting based on open questions about Hebrew formatting.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I would prefer to not delay proper Chinese formatting based on open questions about Hebrew formatting.

Hm? r already works for Chinese and anything that returns cyclic years.

I'm not aware of any data that uses r except in cyclic calendars.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I misunderstood, I thought we still had hacks for chinese formatting.

In that case I think we can wait on CLDR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still also in favor of landing this with less committal docs, though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual behavior change is in components/datetime/src/format/datetime.rs. Previously it checked for cyclic year before trying to load the related year. This PR adds the ability to load the related year from other calendars by adding things to the traits.

I probably have comments on the trait structure, too, but I don't agree with the PR on principle so I haven't spent time thinking too much abut them.

Copy link
Member

@sffc sffc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been consistent about Gregorian meaning the calendar with eras and nonzero year numbers. Let's not muck it up

@robertbastian
Copy link
Member Author

It's in CLDR, but it seems to have footguns. We shouldn't add new things that have known footguns.

what's the footgun?

We've been consistent about Gregorian meaning the calendar with eras and nonzero year numbers. Let's not muck it up

related_gregorian_extended_year then. We've also generally tried to be consistent with CLDR.

@sffc
Copy link
Member

sffc commented Dec 18, 2025

It's in CLDR, but it seems to have footguns. We shouldn't add new things that have known footguns.

what's the footgun?

That there isn't a 1-to-1 mapping.

We've been consistent about Gregorian meaning the calendar with eras and nonzero year numbers. Let's not muck it up

related_gregorian_extended_year then. We've also generally tried to be consistent with CLDR.

I prefer related_iso but won't veto related_gregorian_extended_year.

Temporal uses ISO for this. It's literally encoded into the API: Temporal.Now.plainDateISO()

@robertbastian
Copy link
Member Author

That there isn't a 1-to-1 mapping.

The r symbol can be used to add additional context to a non-gregorian date. Yes you can format dd-MM-rr, but that's not a footgun, because you don't do that accidentally.

@robertbastian
Copy link
Member Author

Temporal uses ISO for this. It's literally encoded into the API: Temporal.Now.plainDateISO()

I consider ECMA's and Temporal's distinction between ISO and Gregorian a major flaw. I'd also like to point out that Temporal.PlainDate.year returns the extended/arithmetic year (even for Gregorian), and .eraYear returns the era year, so by Temporal logic this shouldn't be the extended Gregorian year, just the Gregorian year.

@sffc
Copy link
Member

sffc commented Dec 19, 2025

There were lengthy discussions in Temporal where we arrived at these designs, weighing lots and lots of tradeoffs. I could write it up but I have better things to spend my time on today.

@Manishearth
Copy link
Member

I don't really care about the name here. Self-consistency is a good motivator. I'd like to avoid deprecating things further just for naming reasons.

Copy link
Member Author

@robertbastian robertbastian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were lengthy discussions in Temporal where we arrived at these designs, weighing lots and lots of tradeoffs.

I'm not arguing against Temporal's decision, I'm arguing that we should follow it.

}
}

/// The Gregorian year in which this year started.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}

/// The Gregorian year in which this year started.
Copy link
Member

@sffc sffc Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, and I consider it a footgun. It is there because of Chinese, and it has a definition for other calendars, but that doesn't mean it should be used by those other calendars.

For Hebrew, I did some research with help from Gemini and found that there are a number of sources that use the later of the two years since it has more overlap (5786 <-> 2026, not 2025). For example:

https://web.library.yale.edu/cataloging/hebraica/about-hebrew-calendar

However, most sources write it as "2025-2026"

https://www.judaicaplace.com/jewish-year-calendar-5786-2025-2026-spiralbound/767278911413/

So in that sense, maybe r should print 2025-2026.

@robertbastian robertbastian requested a review from sffc January 6, 2026 22:59
Copy link
Member

@Manishearth Manishearth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine architecturally.

On the ISO vs Gregorian debate I find myself slightly in favor of ISO naming (as it is currently in the PR): CLDR nomenclature compatability is a compelling argument, but I also find "ISO year" to be a good shorthand for "Gregorian extended year"

The year overlap direction question is probably something that can be figured out in a CLDR context.

Copy link
Member

@sffc sffc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a path for this PR until we work with CLDR on improving the spec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants