Hi! I try to use `kotlinx-datetime` to parse offse...
# kotlinx-datetime
v
Hi! I try to use
kotlinx-datetime
to parse offset dates like: 2020-02-25T130909+01:00. But I can’t find out how to use DateTimeFormat<DateTimeComponents> to format LocalDateTime. I looked through docs and found several examples for the opposite conversion, but got stuck with formatting LocalDateTime back to string.
d
You can't format just a
LocalDateTime
using this format because this format includes an offset, and
LocalDateTime
doesn't include one, so there is nothing to meaningfully format. You can do
Copy code
offsetDateTimeFormat.format {
  setDateTimeOffset(value, someOffset)
}
but you need to choose the offset to use.
v
Then I definitely do something wrong from very beginning, because the offset is ignored while parsing string to
LocalDateTime
. What should I do to have an access to the information about offset and do not ignore/lose it?
Copy code
override fun deserialize(decoder: Decoder): LocalDateTime {
        val instant = offsetDateTimeFormat.parse(decoder.decodeString()).toInstantUsingOffset()
        return instant.toLocalDateTime(TimeZone.currentSystemDefault())
    }
will this be better solution?
c
LocalDateTime
is just a datetime with no timezone information at all. It can't ever store anything more than
2020-02-25T13:09:09
, because if it did, then by definition it would something else than a
LocalDateTime
. If you gave this to an instant,
2020-02-25T13:09:09+01:00
would be stored as
2020-02-25T12:09:09Z
. If your goal is to compare two events to know which one happened first, that's the correct data structure. However, it doesn't store in which timezone the event happened. If you want to store the exact timezone, then you essentially want a
Pair<LocalDateTime, FixedOffsetTimeZone>
, which I believe is what Java calls a
ZonedDateTime
but I don't think exists in KotlinX.Datetime (yet?)
d
The better solution depends on what you need. •
Instant
remembers the moment in time. From its point of view,
2020-02-25T13:09:09+01:00
is exactly the same thing as
2020-02-25T14:09:09+02:00
. Use this if you want to know the moment in time, but don't care in which timezone it happens. This is for things like "the moment this e-mail was sent". •
LocalDateTime
remembers what the clocks say. It can't distinguish between
2020-02-25T13:09:09+01:00
and
2020-02-25T13:09:09-10:00
. Use this if you want to know what the residents of the timezone see on their clocks, but don't care in which timezone it happens. For example, this is ok for local train schedules. •
DateTimeComponents
doesn't have specific semantics, it's just a bunch of values grouped together for parsing and formatting. Use it if you need to know both the offset and the moment in time.
👌 1
v
I’m closer to the 2nd case. I receive date and time of a certain event from the backend and just show it to the user on UI like “You joined 11 Apr 2024 at 12:03”, but our users are located in a few different timezones, so I just want to convert the backend data to
LocalDateTime
according to my user’s timezone. I believe the code I posted above does it.
d
If the offset that's provided by the backend isn't an offset that the users are interested in (but, for example, what the backend itself sees), you can simply use
InstantIso8601Serializer
and convert to and from
Instant
, and then to convert the
Instant
to the
LocalDateTime
outside of the serializer.
Typically, you shouldn't convert an
Instant
to a
LocalDateTime
until the very last moment when you want to show the datetime to the user. For example, if the user changed the timezone on their device, it doesn't mean that the program should re-request the same data from the server, but the displayed text should update. If you're storing
Instant
values throughout your program, this is achieved automatically, whereas with
LocalDateTime
, you have to deal with cache invalidation.
v
ok, will switch to Instant then.
thanks for clarifying all this!