-
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
Remove MonthDay.compare and add equals() methods #588
Conversation
Codecov Report
@@ Coverage Diff @@
## main #588 +/- ##
==========================================
+ Coverage 97.77% 97.80% +0.03%
==========================================
Files 16 16
Lines 3635 3686 +51
Branches 617 633 +16
==========================================
+ Hits 3554 3605 +51
Misses 79 79
Partials 2 2
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also realized that when this comes to the calendar, we may need another .equals() method there, because you can't ===
calendars since they aren't singletons any more.
I'm confused; why would |
da42340
to
d028c74
Compare
By the way,
I didn't add one to TimeZone yet because you can do
In the absence of those precedents, I'd say this behaviour seems useful; in |
d028c74
to
4a7d73e
Compare
I think that the calendar system shouldn't be disregarded for |
What do you think the result of this code should be? const today = Temporal.now.date();
Temporal.Date.compare(today.withCalendar('japanese'), today.withCalendar('hebrew')) |
I don't have an intuition - but |
Due to the data model (#391), comparisons always take place in the ISO calendar space, no matter what is in the calendar slot. So, in |
In that case, In other words, anything for which |
The way to fix that issue would be to return nonzero when the calendars differ. I don't really understand why that's important, though. We could alternatively do string comparison on the calendar IDs to break ties. |
When sorting, two elements are either conceptually identical (0), or need to be sorted (negative or positive). It's fine if two conceptually identical things are observably different! However, |
Where is this precedent coming from? There are no new Intl.Collator('en', { sensitivity: 'base' }).compare('e', 'é')
// => 0 |
@ptomato from other languages that have a "compare" protocol. see also this proposal on the next agenda. |
If we're comparing to other languages, Rust uses PartialOrd and PartialEq for its |
I can see the argument that what we do here sets precedent, since as @ptomato pointed out, there aren't many other |
I think the comparison order should be first ISO fields, and then calendar, such that calendar is only checked if two date[time]s are otherwise identical. Probably make ISO always sort first (or last) in a list of calendars. I think this should basically cover the "ignore calendar" use case, since you get dates in their natural order, with calendar merely as a tiebreaker. For example, an ordering would be:
|
I agree calendar should be checked last, if we check it at all, but in my estimation the most common use case is going to be checking if two dates are the same date, regardless of calendar, and I think the above suggestion makes that less ergonomic: PS. After the latest revision, this discussion no longer blocks the PR from being merged, since there is no calendar slot in the polyfill yet anyway ... 😉 |
How can they be the same date if they're not using the same calendar? |
These are all the same date, not using the same calendar:
|
@ptomato is that generally true? or is that just true in those instances? what i mean is, if they're the same because their ISO fields are the same, then great, that's what |
They're the same date because they're all showing on the calendars on people's walls at the same time 😄 I've already given up on having compare() and equals() treat the calendar differently. So now the question is whether equals() and compare() both compare the calendar after comparing the ISO fields, or both ignore the calendar. If I understand correctly, either of these will fulfill your requirement. If both methods compare the calendar after comparing the ISO fields, but you want to compare the actual dates, i.e. the dates I listed in my previous comment all compare equal, then you need to work around it like this:
If both methods ignore the calendar, but you want object identity, then you need to work around it like this:
I estimate that comparison of actual dates is the more common use case, so I'd prefer the latter workarounds to the former ones. |
Fair enough; I'll certainly defer to the champion group here on which alternative is better. (ᕕ( ᐛ )ᕗ |
Can we make if (a.compare(b) === 0) {
// date and calendar are both equal
}
if (Math.abs(a.compare(b)) <= 1) {
// dates are equal, but in different calendar systems
} FWIW, I don't find the |
Just an observation about #588 (comment): that example also has the correct string ordering. If we order calendar IDs alphabetically, then the ISO strings are also in lexicographic order, which seems nice. |
Sure, but I'd recommend moving that discussion to another issue. I can't implement it in this pull request because there is no calendar slot yet 😄 Is there a precedent for using specific codes in the return value of a compare-like function? |
|
Temporal.MonthDay is cyclical, like Temporal.Time, so it's not well-defined whether 12-31 should come before or after 01-01. Unlike Temporal.Time where we resolve the ambiguity by assuming the times occur in the same day, it's less well-defined for Temporal.MonthDay because the operands could be in different calendars. Since Temporal.MonthDay already doesn't have arithmetic, it's not a big stretch to remove comparison as well. Closes: #523
When calendars are added, getters will return the calendar fields, but we want to use the internal ISO 8601-valued slots. Dates are before, after, or equal to other dates regardless of which calendar system is used.
This adds an equals() method to Absolute, Date, DateTime, MonthDay, Time, and YearMonth. For types with a compare() method, `a.equals(b)` is equivalent to `Temporal.X.compare(a, b) === 0` Duration doesn't have an equals() method at this time because, does `{ minutes: 1, seconds: 30 }` equal `{ seconds: 90 }`? TimeZone doesn't have one either because it's simple enough to compare the .name property.
5f54668
to
e574d1a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. The champion group has agreed that it's fair to merge this in as-is for shipping the polyfill and discuss the concerns raised here before Stage 3.
I opened #625 to summarize the discussion so far, and as a place to continue it. |
Closes: #523