Hey guys :wave: I’ve just published a kotlinx-date...
# kotlinx-datetime
r
Hey guys 👋 I’ve just published a kotlinx-datetime-ext library the fills the gap between
java.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 Conversation
d
FYI 1: there's already
atStartOfDayIn
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.
👍 2
r
Thank you Dmitry for pointing out! coming from Java.datetime its a bit frustrating to work with kotlinx’s as it doesn’t have most of the “quick to use” functionality, you might be right here that people should rely mostly on instants instead of localdatetime objects as its clearer and the origin of any date or time but in many if not most apps, the implementation details are not really needed/important for the developer OR they need a quick access to a functionality so I actually 💯 agree with the library implementation as the official library should be as abstract as possible and fully rely on the Instants & TimeZones, and then this leaves a space for other devs like my self to create libraries that makes it easier to use the original one which devs can use or not based on their preferences one example is your first point to get a “at start of the day” LocalDateTime I have to do this:
Copy code
val date = LocalDate.now().atStartOfDayIn(TimeZone.currentSystemDefault()).toLocalDateTime(TimeZone.currentSystemDefault())
while in my lib its a bit more convenient:
Copy code
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!
d
while in my lib its a bit more convenient:
Copy code
val newLibDate = LocalDate.now().atStartOfDay()
My point is that it's also a bit more wrong: if clocks shifted directly from
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.
r
oh wow, good point! didn’t think of that, will defiantly consider this in the readme file and documentation/optIn QQ: is this an issue currently in java.datetime?
d
It is a problem when using
LocalDate.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
.
1
💡 1
r
interesting, so if I changed the implementation of my function from
Copy code
fun LocalDate.atStartOfDay(): LocalDateTime {
    return LocalDateTime(this, LocalTime.MIN)
}
to
Copy code
fun LocalDate.atStartOfDay(timeZone: TimeZone): LocalDateTime {
    return this.atStartOfDayIn(timeZone).toLocalDateTime(timeZone)
}
would that make it a bit more correct?
its a bit hard to think of edge-cases examples to verify
d
This is entirely correct, yes.
r
cool
btw since we’re at this, my app relies heavily on date and time, do you think its better to use Instants in data classes and everywhere and only convert to LocalDateTime when it needs to be used/displayed?
as between creating the LocalDateTime object and using it, in theory, the timezone can change, which will then display inaccurate data
d
Depends on what you're trying to express. If the user inputs "remind me on 2024-03-02, 23:00", they do mean 23:00, you shouldn't adjust this value. If the user says "in two hours," yes, that's an
Instant
.
r
what if its something like, post creation datetime that I get from the server
it will then be displayed according to the user timezone
d
That's an
Instant
.
r
right, makes total sense
d
If the user moves to another country, the numbers they see should change, shouldn't they?
r
yup
one more thing, since I also have
atEndOfDay
function
Copy code
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?
d
localDate.plus(1, DateTimeUnit.DAY).atStartOfDayIn(zone).minus(1.nanoseconds).toLocalDateTime(zone)
If you add
23:59:59.999999999
, you can end up in a non-existant time anyway.
So, instead, the end of a day is exactly almost the start of the next day. And we know how do express that.
r
yeah, I got this value from java.datetime but your way is more accurate and should never fail
but yeah I’ll add those changes, thanks a lot for your time and knowledge sharing that was pretty inspiring!
d
Sure thing!