unicode-org / icu4x

Solving i18n for client-side and resource-constrained environments.
https://icu4x.unicode.org
Other
1.33k stars 174 forks source link

How to implement ordering on AnyCalendarInner? #3469

Open sffc opened 1 year ago

sffc commented 1 year ago

There are a few general approaches:

  1. Compare calendar first, calendar date second
  2. Compare ISO date first, calendar second
  3. Compare ISO date and don't look at the calendar

Temporal uses approach (3), but it's a non-starter for the Ord impl because it must be a total order.

If we can get to (2), that's probably the best for ICU4X's purposes, but it's actually a bit tricky because there is not currently a space into which we can project the full range of dates in all calendars. fixed_date is limited to i32, and the range of years in some calendars covers a different span than the range of years in others. One way to fix that problem is to change fixed_date to be an i64, which I think is a change we should make anyway.

However, approach (1) works around both of these problems, and we can even use derive(Ord). It's maybe not that bad from a user perspective, too.

Another way to get out of this conundrum is to add different types of Ord functions like we did to Locale (#1709).

Discuss with:

Optional:

robertbastian commented 1 year ago
  1. Implement correct comparisons for all combinations of calendars
Manishearth commented 1 year ago

I think approach (3) should be a separate function. I think we should use preferably (2) but (1) is also fine.

I think date comparison is a complex situation anyway and we should have good docs telling people what the different options are. In such a scenario derive(Ord) doesn't seem too bad.

But also, the RataDie type fixed the problem wrt bounds.

If people want to use these dates as BTreeMap keys then derive(Ord) is probably better.

sffc commented 1 year ago

Proposals:

  1. Derive Ord; Expose the ISO comparison function 2/3 as its own function
  2. Do not derive Ord; expose both comparison functions (the ones corresponding to options 1 and 2/3). If the user wants to stick it in a BTreeMap, they need to write their own Ord.

Consensus:

  1. Do not implement Ord on Date<AnyCalendar>; we are not convinced that there are sufficiently motivated use cases for a general implementation, and clients like ECMAScript can implement their own.
  2. Implement Eq and Hash on Date<AnyCalendar>, including data comparison, including on whichever internal types are required to get it to bubble up to Date<AnyCalendar>: AnyDateInner and AnyCalendar, including all DateInner types and all calendar types, with or without data. Make sure they are implemented optimally. We are assuming that we can make an efficient Eq by comparing data pointers; if not, we need to revisit the implementation with the group to decide the best path forward. OK to ignore the data in Hash. If a DateInner has a cached field, we should ignore the cache.
  3. We are okay implementing PartialOrd that returns None if the calendar types are different.

LGTM: @robertbastian @Manishearth @sffc @echeran @sotam1069 @atcupps