https://kotlinlang.org logo
Title
h

holgerbrandl

01/19/2023, 8:47 PM
Hi there, I'm trying to figure why the use of LocalDateTime feels discouraged. The docs say "The arithmetic on LocalDateTime values is not provided, since without accounting for the time zone transitions it may give misleading results.". Could you provide an example of such a mistake? I'd love to do
LocalDateTime.now() + 10.hours
, and I struggle to see what's wrong with it.
m

mbonnin

01/19/2023, 9:28 PM
I initially wrote an answer but I'm pretty sure it was wrong... Curious about this too 👀
d

Desmond van der Meer

01/20/2023, 7:14 AM
If you take for example March 26, 2023, 22:00 as a value for the
LocalDateTime
then it's ambiguous what happens if you add 10 hours to it because that's when daylight saving time starts. If you just add 10 hours to the clock it would be 8:00, but if just waited 10 hours it would be 9:00.
Ofc the example above depends on which time zone you're in (in this case I took the US as an example)
m

mbonnin

01/20/2023, 9:52 AM
Well, that's the thing.
LocalDateTime
isn't timezone aware, is it? So arithmetics could be defined without any time zone, leap second, etc.. considerations
2023-26-03 22:00
+
10.hours
could always equal
2023-27-04 08:00
d

Desmond van der Meer

01/20/2023, 9:53 AM
No because "10 hours later" depends on the time zone.
m

mbonnin

01/20/2023, 9:53 AM
What I'm saying is that it could be a choice
We could define the arithmetic to be non time-zone aware
d

Desmond van der Meer

01/20/2023, 9:53 AM
Implementing it like that would encourage incorrect date/time calculations.
m

mbonnin

01/20/2023, 9:54 AM
right, I can see how people could expect the wrong thing
And going trhough
Instant
isn't very complicated
But if you're doing arithmetics on something that does'nt contain a time zone, I wouldn't expect the arithmetic to use the time zone?
d

Desmond van der Meer

01/20/2023, 9:57 AM
I even wonder what the use case is for the "+10 hours" example mentioned in the original question. My first guess is that it should be implemented in a timezone-aware manner.
You can actually do arithmetic with days, just not time-of-day.
m

mbonnin

01/20/2023, 9:57 AM
I had to do that recently, let me see if I can dig the use case
Alright, it's here
It was to set the end time of a conference talk if none was there
(it was known the talk was 40min)
d

Desmond van der Meer

01/20/2023, 10:02 AM
So in this case using UTC time-zone is incorrect. You'd have to use the time zone of where the conference takes place. If the conference was across a DST change boundary this would give the wrong result. I know it's quite an edge-case in your example, but an API should always be correct.
m

mbonnin

01/20/2023, 10:02 AM
Yep, agreed
Alright, I'm convinced! Thanks for the walk through!
d

Desmond van der Meer

01/20/2023, 10:08 AM
No worries 😉 Unfortunately working with date/time is always complex and/or annoying. The time zone rules across the world are a hot mess
h

holgerbrandl

01/20/2023, 11:46 AM
Thanks gentleman for this great thread. Regarding "I even wonder what the use case is for the "+10 hours": I'm working out a production schedule, and was just wondering if the more minimalistic LocalDateTime would be sufficient (since the factory is clearing never moving to a different time zone). However, I understand now that the timezone also models summertime/wintertime transitions, so Instant is the correct choice.
Because I'm old and forgetful, I've created a PR to find this argument maybe later in the documentation itself. See https://github.com/Kotlin/kotlinx-datetime/pull/248
t

Todd

03/01/2023, 11:44 PM
Digging up this old thread. I have a usecase where some businesses consider 2AM or 3AM to be the end of the day, sometimes known as a closeout time. I want to figure out what the business date is of someones particular shift. So if I finish a shift at 2023-01-02T01:59:00 and the closeout time is 2:00:00, then the business date for the end of the shift would be 2023-01-01. If I finish a shift at 2023-01-02T2:00:00, then the business date for the end of the shift would be 2023-01-02. Using the java api I can do this to figure it out:
zonedDateTime.toLocalDateTime().minusHours(closeoutHour).toLocalDate()
But in kotlinx.datetime we can’t do arithmetic on the LocalDateTime. However, in this case doing arithmetic on the Instant could get us wrong answers depending on daylight savings time, since the closeout time does not shift. Is there some gotcha I’m missing about the java api in this use case?
fwiw I think this would work with kotlinx.datetime
fun getBusinessDay(instant: Instant, timeZone: TimeZone, closeoutTime: LocalTime): LocalDate {
    val localDateTime = instant.toLocalDateTime(timeZone)
    return if (localDateTime.time < closeoutTime) {
        localDateTime.date.minus(1, DateTimeUnit.DAY)
    } else {
        localDateTime.date
    }
}
m

mbonnin

03/02/2023, 12:19 AM
Why do you have to substract? Can't you compare to
2
instead of
0
?
t

Todd

03/02/2023, 1:24 AM
Like the example I have above? I guess that’s a fair point. Maybe since it’s not completely necessary to subtract hours in this use case it’s still more beneficial to lock the api down to prevent confusion.
d

Dmitry Khalanskiy [JB]

03/02/2023, 8:21 AM
If clocks are shifted back due to DST and it takes three actual hours to get from midnight to 02:00, or if the clocks are shifted forward and it takes just an hour to do so, do the businesses adapt the schedule? In other words, what is more important: the mark "02" on the clocks or the actual length of the workday?
t

Todd

03/02/2023, 8:02 PM
Just the mark “02”. The actual length of the workday doesn’t matter.
The more I think about this, the more I think the comparison approach is better. A localdatetime is still a representation of a time at a zone, so the subtraction doesn’t really make sense.
d

Dmitry Khalanskiy [JB]

03/06/2023, 2:34 PM
Also, the subtraction approach is a bit more error-prone:
zonedDateTime.minusHours(closeoutHour).toLocalDate()
would be incorrect, but it looks almost the same.
m

mbonnin

03/22/2023, 2:06 PM
Just bumped into this (
LocalDateTime.plusHours()
). Interesting that Java made the opposite choice.
The Javadoc doesn't give too many details though 😞