Today we’re excited to announce the first milestone release of the kotlinx-datetime library, version 0.1.
There is a longstanding request for the ability to work with dates in Kotlin. In Kotlin/JVM, you can rely on the java.time.* API, but there’s no such option when developing a multiplatform project.
Though several multiplatform kotlin libraries already exist in this field, we feel that such a fundamental need should be addressed by a kotlinx.* library.
kotlinx-datetime is a multiplatform library for working with dates and times in Kotlin. It supports Kotlin/JVM, Kotlin/JS, and a variety of Kotlin/Native targets.
Our vision is first to provide a minimal API that can cover the most common practical use cases, and then to extend that API to cover more.
You can learn more about what’s in the library and find instructions for setting up a dependency in your project in the README.
This release is a first step on the path to a stable library, so we are particularly looking forward to your feedback.
Feel free to submit issues to GitHub or ask questions here or in Slack (get an invite here).
I always wondered why “local” prefix is needed in the name of each date/time class.
I think this prefix just confuses people. Here’s an example. They make incorrect assumptions about “locality”, e.g. they think LocalDateTime is in local timezone. The funny thing is that people added “local” prefix so that programmers understand it does not contain time zone or any kind of offset. Here are some interesting thoughts.
Look at Java LocalDateTime description. There is nothing about locality. It says about the absence of time zone and inability to represent an instant on the time-line. If we want name to represent the exact meaning of the class then why don’t we call it DateTimeWithoutTimeZoneNotInstant?
If people do not understand the true meaning of date/time class with prefixes “naive”, “local”, “civil” etc. then why are these prefixes needed? Let’s make it less verbose and save people from wrong assumptions about locality by removing “local” prefix completely.
val now: LocalDateTime = now.toLocalDateTime(TimeZone.currentSystemDefault())
val today: LocalDate = Clock.System.todayAt(TimeZone.currentSystemDefault())
→
val now: DateTime = now.toDateTime(TimeZone.currentSystemDefault())
val today: Date = Clock.System.todayAt(TimeZone.currentSystemDefault())
Alternative proposal - make it backwards:
rename LocalDateTime to DateTimeNoTZ / DateTimeNoZone / DateTimeWithoutZone
rename hypotetical ZonedDateTime (does it planned?) to DateTime
I strongly advice to keep the “Local” prefix.
While I think that you are right and the “Local” prefix is not very intuitive (or maybe even the contrary) - it is used in all(?) modern JVM date APIs.
In my opinion following already established convention is more important. Especially when targeting the JVM and Java developers.
I’ve been developing on a product that works with timeseries at its core for over 2 years now. From my experience so far it’s crucial to be absolutely precise and let everybody now whether you talk about a LocalDateTime or an OffsetDateTime or a ZonedDateTime (not just among programmers, also with the business).
Removing the prefix from any of these types will drop context for no reason and open room for errors and misunderstandings. Please keep this. Coming from Java to Kotlin the amount of explicitly written types has dropped massively, so it can’t be an argument for readability of code.
In my opinion people who get confused by this or want it simplified try to avoid the inherent complexity of the topic. I can totally understand that. But the complexity is there and closing your eyes to it won’t make it go away.
Agree with Jschneider. It took years to sort this out in the Java space, and while painful to have to learn Instant/Local/Zoned/Offset, they have purpose and a lot of things need the precision.
Kotlin just directly mapping them would be preferable to trying to rename anything and muddy the waters.
People get tripped up because they think the “Local” in LocalDateTime means their “Location”, and therefore their Timezone, but never did. Its always used the precise meaning of Local “relating to a particular space or place or serving only a small portion of something”. In this case the notion or date and/or time divorced from the underlying Timeline and Zones.
I agree with the confusing names. Naming in the Java (and other language) ecosystem is usually bad. Here are some other classes that can be renamed in my opinion:
Instant: It is not instantaneous; it represent a period lasting a whole nanosecond. You can execute a couple to dozens of instructions in that “instant”.
DateTime: What about Timestamp?
This is a silly reason: We should not improve because developers may have to adjust? I think having a Date & Time API with much clearer names can be a Kotling selling point.
I’m not even sure that multi-platform is really a thing. Is this a good direction for Kotlin? It’s a stretch to think people want their code to be run on multiple platforms. Perhaps the best direction is to have a Kotlin VM which combines the best of JVM and Node.
I think this is a good idea. Java date naming is quite unclear at first glance and Kotlin is its own language so should feel free to make its own decisions.
I like the proposal for DateTimeWithoutZone. It’s not much more verbose than Java but more descriptive and does not clash with other platforms.
Also, I think right choice to keep it practical for most real use cases!
I don’t think it interops directly with C++. The native interface uses the C ABI and a C header. Only the implementation of that header is in C++. It has always been possible to implement C headers in C++. It could just as well have been Rust or any other language, that can expose a function to C.
Making wrappers instead of typealiasing java.time types gives us some flexibility in changing the implementation later. Also we’d like to avoid conflict of our API with the member functions that would be visible on type aliases. Of course, we could use inline classes for that, but that would bring some limitations on usage on these types, which we wouldn’t like to impose for now.
To be honest, DateTime-related operations usually aren’t going to be in a tight loop where performance really matters, and if you are in a situation like that, usually you should probably use some clever math instead.