In support of Instant.minus(Instant)

Stephen Colebourne scolebourne at joda.org
Thu May 16 20:14:29 UTC 2024


I remain happy to see until() go into the JDK. Potentially on more
classes than the recent PR.

*If* Java gets operator overloading, and *if* it is based on a mapping
to method names, then *perhaps* there is a case to consider adding
minus(). But I don't feel now is the time.

Stephen


On Thu, 16 May 2024 at 17:50, Kurt Alfred Kluever <kak at google.com> wrote:
>
> Hi all,
>
>
> Sorry for the delay here. I took a quick look at other popular date/time libraries and there seems to be a fairly strong preference for minus (JS/TS's Temporal library is the only other date/time library that I found which uses until for this concept):
>
>
> Abseil's Time (C++) overloads the - (minus) operator to allow for end - start
>
> NodaTime (.NET) defines end.minus(start) (which also allows end - start)
>
> Kotlinx.datetime defines end.minus(start) (which also allows end - start)
>
> Python's date/time API allows end - start
>
> Temporal (JS/TS) defines start.until(end)
>
>
> The first 4 APIs support both instant - instant = duration and instant - duration = instant — I find this quite natural.
>
>
> Additionally, "until" seems to imply it will return a positive duration. This is fine if you're certain that "end" is after "start". However, it becomes very confusing otherwise. E.g., if you ask: "how long from when you were married until now?". If you were married 4 years ago, that makes sense. But if your wedding is in 3 months, then the result is a negative duration (which often cause confusion). If you ask the question the other way around ("how long from now until your wedding day?"), that works if your wedding is in the future, but not so much if you were married 4 years ago (again, you'll get a negative duration).
>
>
> Additionally, the word "until" seems to imply a range with defined start/end points; e.g., "I'm out from Tuesday until next Thursday" --- that's more of a Range<Instant> (or an Interval which java.time doesn't have – but of course JodaTime did), not just a span of time (a Duration).
>
>
> Does that sway anybody's opinion?
>
>
> Thanks,
>
> -kak
>
>
>
> On Mon, May 13, 2024 at 1:38 PM Naoto Sato <naoto.sato at oracle.com> wrote:
>>
>> Hi,
>>
>> With Stephen/Roger's comments, as well as Kevin's observation that
>> until(end) has a good argument ordering that is easy to understand, I'd
>> still propose `until()`. Please post if you have further comments.
>>
>> Naoto
>>
>> On 5/3/24 6:39 AM, Roger Riggs wrote:
>> > Hi,
>> >
>> > I would also reinforce Stephen's early observation that the pattern for
>> > "until" methods in java.time includes those of the XXXDate classes, with
>> > a single Temporal parameter.  Period and Duration are similar values
>> > holding relative TemporalAmounts.
>> >
>> >      public Period until(ChronoLocalDate endDateExclusive)
>> >
>> > In addition to Instant, the LocalTime class might also benefit from adding:
>> >
>> >      public Duration until(LocalTime endExclusive)`
>> >
>> > The API design of java.time included an emphasis on consistent naming
>> > across the packages.
>> >
>> > Regards, Roger
>> >
>> >
>> > On 5/2/24 4:01 PM, Naoto Sato wrote:
>> >> `Temporal` interface is clear that its `minus` methods return objects
>> >> of the same `Temporal` type, and `until` calculates the amount of time
>> >> until another `Temporal` type. Introducing `Instant.minus` that
>> >> returns `Duration` would be confusing to me.
>> >>
>> >> Naoto
>> >>
>> >> On 5/2/24 10:41 AM, Éamonn McManus wrote:
>> >>> I'd say too that this makes intuitive sense based on algebra. If we
>> >>> have:
>> >>> /instant1/ + /duration/ = /instant2/
>> >>> then we can subtract /duration/ from both sides:
>> >>> /instant1 = instant2 - duration/
>> >>> or we can subtract /instant1/ from both sides:
>> >>> /duration = instant2 - instant1/
>> >>>
>> >>> There's no manipulation we can do that would cause us to try to add
>> >>> instants together, and it's a bit surprising for the API to allow the
>> >>> first subtraction but not the second.
>> >>> I also think that if I see instant2.minus(instant1) it's immediately
>> >>> obvious to me what that means, while instant1.until(instant2) seems
>> >>> both less discoverable and less obvious.
>> >>>
>> >>> On Thu, 2 May 2024 at 10:29, Louis Wasserman <lowasser at google.com
>> >>> <mailto:lowasser at google.com>> wrote:
>> >>>
>> >>>     That doesn't follow for me at all.
>> >>>
>> >>>     The structure formed by Instants and Durations is an affine space
>> >>> <https://en.wikipedia.org/wiki/Affine_space#Definition>, with
>> >>>     instants the points and durations the vectors.  (An affine space is
>> >>>     a vector space without a distinguished origin, which of course
>> >>>     Instants don't have.)  It is 100% standard to use the minus sign for
>> >>>     the operation "point - point = vector," even when "point + point" is
>> >>>     not defined, and to use all the other standard idioms for
>> >>>     subtraction; the Wikipedia article uses "subtraction" and
>> >>>     "difference" ubiquitously.
>> >>>
>> >>>     Personally, I'd be willing to live with a different name for the
>> >>>     operation, but consider "users keep getting it wrong" a strong
>> >>>     enough argument all by itself for a version with the swapped
>> >>>     argument order; it's not obvious to me that another API with the
>> >>>     same argument order adds enough value over Duration.between to
>> >>>     bother with.
>> >>>
>> >>>     On Thu, May 2, 2024 at 10:04 AM Stephen Colebourne
>> >>>     <scolebourne at joda.org <mailto:scolebourne at joda.org>> wrote:
>> >>>
>> >>>         On Thu, 2 May 2024 at 15:58, Kurt Alfred Kluever <kak at google.com
>> >>> <mailto:kak at google.com>> wrote:
>> >>>          > instant − instant = duration // what we're discussing
>> >>>          > instant + duration = instant // satisfied by
>> >>>         instant.plus(duration)
>> >>>          > instant - duration = instant // satisfied by
>> >>>         instant.minus(duration)
>> >>>          > duration + duration = duration // satisfied by
>> >>>         duration.plus(duration)
>> >>>          > duration - duration = duration // satisfied by
>> >>>         duration.minus(duration)
>> >>>          > duration × real number = duration // satisfied by
>> >>>         duration.multipliedBy(long)
>> >>>          > duration ÷ real number = duration // satisfied by
>> >>>         duration.dividedBy(long)
>> >>>          >
>> >>>          > All but the first operation have very clear translations from
>> >>>         conceptual model to code. I'm hoping we can achieve the same
>> >>>         clarity for instant - instant by using the obvious name:
>> >>>         instant.minus(instant)
>> >>>
>> >>>         But you can't have
>> >>>           instant + instant = ???
>> >>>         It doesn't make sense.
>> >>>
>> >>>         This is at the heart of why minus isn't right in this case.
>> >>>         Stephen
>> >>>
>> >>>
>> >>>
>> >>>     --     Louis Wasserman (he/they)
>> >>>
>> >
>
>
>
> --
> kak


More information about the core-libs-dev mailing list