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

Allow relational comparison of instants #92

Closed
gibson042 opened this issue Sep 27, 2018 · 13 comments
Closed

Allow relational comparison of instants #92

gibson042 opened this issue Sep 27, 2018 · 13 comments

Comments

@gibson042
Copy link
Collaborator

Originally raised in #42 (comment) , and I'm opening as an independent issue per #74 (comment) .

I believe that instants should be comparable with built-in operators (e.g., ECMAScript is not Java and shouldn't force consumers into methods), and that such comparison should be strictly numeric and therefore ignore timezone (since instants are necessarily on a global timeline).

t1 = Instant.fromString("2018-09-27T12:00-04:00");
t1_EDT = t1.withZone("America/New_York");
t1_NZST = t1.withZone("Pacific/Auckland");
t1 <= t1_EDT && t1 >= t1_EDT &&
    t1 <= t1_NZST && t1 >= t1_NZST &&
    t1_EDT <= t1_NZST && t1_EDT >= t1_NZST;
// → true

t2 = Instant.fromString("2018-09-27T13:00-04:00");
t2_EDT = t2.withZone("America/New_York");
t2_NZST = t2.withZone("Pacific/Auckland");
t1 < t2 && t1 < t2_EDT && t1 < t2_NZST &&
    t1_EDT < t2 && t1_EDT < t2_EDT && t1_EDT < t2_NZST &&
    t1_NZST < t2 && t1_NZST < t2_EDT && t1_NZST < t2_NZST;
// → true
@gibson042 gibson042 changed the title relational comparison of instants Allow relational comparison of instants Sep 27, 2018
@pipobscure
Copy link
Collaborator

Comparing the instants themselves causes problems with comparing between different object types.

Instead simply go instant2.nanoseconds < instant1.nanoseconds and just compare the nanos since epoch. Beign explicit in what exactly it is you are comparing is a good thing™️.

@gibson042
Copy link
Collaborator Author

Current spec text documents nanoseconds as returning a value in in the range of 0 to 999999, and milliseconds as not including sub-ms precision. So what you're proposing (a getter of "nanoseconds since the epoch") is also an addition, and will need a good name that makes clear the absence of similar value truncation. If we affirmatively resolve this issue, then the name—or at least an alias thereof—is just valueOf().

@pipobscure
Copy link
Collaborator

pipobscure commented Oct 10, 2018 via email

@gibson042
Copy link
Collaborator Author

I think we're misunderstanding each other. The correspondence is more than "conceptual"... a BigInt-returning valueOf would absolutely satisfy this issue.

@pipobscure
Copy link
Collaborator

It would satisfy the issue, but we had this discussion in #74 so something has to give.

What I'm thinking is that comparison of Instant can be done via the .nanosecond member (or any granularity you wish) satifying this point (although not fully) while still keeping with the arguments put forth in #74.

@gibson042
Copy link
Collaborator Author

#74 was too jumbled in both scope (unfair equal consideration of instant vs. non-instant values) and reasoning (ignoring the implications of toString without valueOf upon abstract relational comparison) to be useful. I'm asking for explicit decisions in the context of a common operation (approximately nobody calls valueOf directly, but toString is used in its stead without protection from @@toPrimitive).

@pipobscure
Copy link
Collaborator

pipobscure commented Oct 10, 2018

Comparing Instant objects with either .valueOf() of @@toPrimitive() means <, >, <= and >= work while == does not. That makes this a really bad solution. It's what Date did and I'd consider this one of the Bad Parts™️.

If we really want to have this kind of comparison, then the only way to achieve this would be by operator overloading putting the temporal objects (or at least Instant) on the level of a primitive. I don't think that's the status it should have.

let a = {}, b = {};
a[Symbol.toPrimitive] = b[Symbol.toPrimitive] = ()=>5;

a == 5; // true
b == 5; // true
a == b; // false
a <= b; // true
a >= b; // true

If you ask me, then I'd say that even in the 21st century we have proven to be capable of producing more Bad Parts™️. Let's not do more of that.

That's why I'd say let it be explicit: use the .nanoseconds member for comparison, which makes it explicit of what is being compared.

@gibson042
Copy link
Collaborator Author

I am conceptually in favor of comparing instants via a numeric member, but its name should have a single obvious meaning. I'm not sure nanoseconds, fits the bill, since that name is used to identify "time since the last millisecond transition" in this very same proposal.

And even with such a member, the result of instant <= instant still must be decided. I don't support string comparison (which works until it doesn't), so that basically leaves using valueOf or @@toPrimitive for either numeric conversion or throwing an exception.

@littledan
Copy link
Member

I'm wondering if we should leave support for comparison operators as a case study for a future operator overloading proposal, and start with a comparison method. I just don't see a non-broken way to do this right now.

@gibson042
Copy link
Collaborator Author

I understand your sentiments, but instant <= instant will do something—compare numerically, compare lexicographically, or throw. I'm in favor of the first, but having a well-named means of extracting BigInt-typed absolute time from instants would make the third palatable as well.

@littledan
Copy link
Member

I'd argue for throwing, and hope having a nanoseconds getter (and comparison methods?) could make this more palatable.

@gibson042
Copy link
Collaborator Author

hope having a nanoseconds getter (and comparison methods?) could make this more palatable

I would find it confusing if civilValue.nanosecond had a bounded range (i.e., since last second or millisecond or microsecond transition) but instant.nanoseconds was an unbounded count since the epoch (cf. #97 (comment) ).

@ryzokuken
Copy link
Member

Between nanosecond-level comparison and Duration objects, I think this has been addressed. Closing this, but please feel free to reopen.

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

No branches or pull requests

4 participants