Raed Ghazal
01/06/2024, 11:23 AMjava.datetime
and kotlinx.datetime
since java had much more functionalities
you can find it here https://github.com/RaedGhazal/kotlinx-datetime-ext with full documentation on what it provides and how to use it
initially I just wrote a blog post on how to write you own helper functions but then thought of making it even easier by creating the library, will appreciate your support by giving me feedback, opening issues or even contribute! (leaving a star can be also nice ❤️)
Thanks!
Slack ConversationDmitry Khalanskiy [JB]
01/08/2024, 8:07 AMatStartOfDayIn
in the kotlinx-datetime
library itself: https://kotlinlang.org/api/kotlinx-datetime/kotlinx-datetime/kotlinx.datetime/at-start-of-day-in.html
FYI 2: we don't provide atStartOfDay
in the form you show, atEndOfDay
, or the local date-time arithmetic because they are error-prone: https://github.com/Kotlin/kotlinx-datetime#date--time-arithmetic By not providing arithmetic operations on LocalDateTime
, we're nudging people to a clearer conceptual model of date-time in their code (in most cases, one should use Instant
primarily). This is not a theoretical concern: when writing the library, we analyzed how code is typically written using Java.Time, and most of the usages of LocalDateTime
arithmetic was buggy. I think it would be nice if you mentioned this in your documentation and/or added an OptIn
requirement like UnsafeDateTimeArithmetic
for the API.
FYI 3: the Locale
parameter for the fixed-format-string formats, too, is error-prone: https://github.com/Kotlin/kotlinx-datetime/discussions/253 Ideally, there should be an API that accepts a skeleton (like "`yyyyMMMdd`") and a locale and formats a string into something like 23 Jan 2023
, but given that there's no such API on plain Java (only on Android), it would be tough to implement this. For now, I'd advise to simply mention in the documentation and/or add an OptIn
to an overload of parsing and formatting that accepts a Locale
.
Other than that, thank you for collecting our users' pain points and acting on them! The code for parsing and formatting is especially valuable, at least until our solution ships.Raed Ghazal
01/08/2024, 11:49 AMval date = LocalDate.now().atStartOfDayIn(TimeZone.currentSystemDefault()).toLocalDateTime(TimeZone.currentSystemDefault())
while in my lib its a bit more convenient:
val newLibDate = LocalDate.now().atStartOfDay()
so as a next step after your reply I will add your points in my readme, and see where it makes since to add OptIn
for UnsafeDateTimeArithmetic
(I might get back to you here for some clarification but after work 😄 )
Thank you!Dmitry Khalanskiy [JB]
01/08/2024, 11:55 AMwhile in my lib its a bit more convenient:
My point is that it's also a bit more wrong: if clocks shifted directly fromCopy codeval newLibDate = LocalDate.now().atStartOfDay()
23:30
to 00:30
due to a DST transition, returning 00:00
is, quite simply, incorrect, as there's no such time on that day. In some problem domains, it's okay, in others, it's a bug.
I think it is fine if the pitfalls of the approach are extremely clear to the user of the library and they consciously choose that yes, they are okay with potentially introducing this class of bugs.Raed Ghazal
01/08/2024, 11:58 AMDmitry Khalanskiy [JB]
01/08/2024, 12:00 PMLocalDate.atStartOfDay()
(https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#atStartOfDay--), but not when using LocalDate.atStartOfDay(ZoneId)
. The latter returns ZonedDateTime
, which is essentially Instant
+ TimeZone
.Raed Ghazal
01/08/2024, 12:03 PMfun LocalDate.atStartOfDay(): LocalDateTime {
return LocalDateTime(this, LocalTime.MIN)
}
to
fun LocalDate.atStartOfDay(timeZone: TimeZone): LocalDateTime {
return this.atStartOfDayIn(timeZone).toLocalDateTime(timeZone)
}
would that make it a bit more correct?Raed Ghazal
01/08/2024, 12:03 PMDmitry Khalanskiy [JB]
01/08/2024, 12:04 PMRaed Ghazal
01/08/2024, 12:04 PMRaed Ghazal
01/08/2024, 12:06 PMRaed Ghazal
01/08/2024, 12:07 PMDmitry Khalanskiy [JB]
01/08/2024, 12:08 PMInstant
.Raed Ghazal
01/08/2024, 12:09 PMRaed Ghazal
01/08/2024, 12:09 PMDmitry Khalanskiy [JB]
01/08/2024, 12:09 PMInstant
.Raed Ghazal
01/08/2024, 12:10 PMDmitry Khalanskiy [JB]
01/08/2024, 12:10 PMRaed Ghazal
01/08/2024, 12:10 PMRaed Ghazal
01/08/2024, 12:14 PMatEndOfDay
function
fun LocalDate.atEndOfDay(): LocalDateTime {
return LocalDateTime(this, LocalTime(23, 59, 59, 999999999))
}
this should also not be fully correct according to what we discussed, so is a better way of doing it, using atStartOfDayIn(timeZone)
then adding 23:59:59:999999999
to it, then converting back to localdatetime?Dmitry Khalanskiy [JB]
01/08/2024, 12:15 PMlocalDate.plus(1, DateTimeUnit.DAY).atStartOfDayIn(zone).minus(1.nanoseconds).toLocalDateTime(zone)
Dmitry Khalanskiy [JB]
01/08/2024, 12:15 PM23:59:59.999999999
, you can end up in a non-existant time anyway.Dmitry Khalanskiy [JB]
01/08/2024, 12:16 PMRaed Ghazal
01/08/2024, 12:16 PMRaed Ghazal
01/08/2024, 12:22 PMDmitry Khalanskiy [JB]
01/08/2024, 12:22 PM