Alexandru Gheorghe
11/21/2024, 2:50 PM.toInstant(TimeZone.UTC)
I'm converting it to UTC. I noticed that the time is kept the same. I was expecting it to change to a time in UTC timezone. This creates a disparity between the user creating data in their timezone and expecting it to show up with the same time (when converted back from UTC into system's timezone) however this is not the case as the time is not adjusted. Am I missing something?Stylianos Gakis
11/21/2024, 2:58 PMMichael Krussel
11/21/2024, 2:59 PMLocalDateTime
has no timezone, so toInstant
will just create an Instant
based on that time in the UTC timezone.
You probably need to convert the local time into a zoned time in the users timezone and then convert that to UTC. Or pass the user's time zone into the toInstant
time.Michael Krussel
11/21/2024, 3:00 PMLocalDateTimes
exist in all time zones and sometimes they may exist at multiple instants in some timezones.Casey Brooks
11/21/2024, 4:25 PMCasey Brooks
11/21/2024, 4:27 PMAlexandru Gheorghe
11/21/2024, 4:30 PMMichael Krussel
11/21/2024, 5:26 PMtoInstant
to be the user's timezone. The local times have no timezone, so there can be no timezone conversion. Instant does have a timezone, so the timezone passed to toInstant
will indicate how to convert.Alexandru Gheorghe
11/21/2024, 5:41 PMval pickedDateTime = LocalDateTime(
year,
month,
day,
hour,
minute
)
val utcDateFormattedTimestamp =
pickedDateTime.toInstant(TimeZone.UTC)
val utcDateTimestamp = utcDateFormattedTimestamp
.toEpochMilliseconds()
I'd have expected utcDateFormattedTimestamp
to be converted to UTC (with time included). Isn't this enough?Michael Krussel
11/21/2024, 5:43 PMpickedDataTime
has no timezone, so converting it to an instant with timezone UTC will create an instant whose time is the same string as pickedDateTime
in the UTC timezone. If you are trying to make the time change, you need to call toInstant
with the timezone you are trying to convert from.Alexandru Gheorghe
11/21/2024, 5:48 PMtoInstant
on what? Please bare with me as I'm trying to get my head around kotlinx datetimeMichael Krussel
11/21/2024, 5:49 PMpackedDataTime
like you are, you are just using the wrong timezone. You should be passing in the timezone that pickedDataTime
is for not UTC.Michael Krussel
11/21/2024, 5:51 PMAlexandru Gheorghe
11/21/2024, 5:54 PM.toInstant(TimeZone.currentSystemDefault())
and then convert to UTC using toInstant
?Michael Krussel
11/21/2024, 5:55 PMInstant's
don't have a timezone. They are just the time since the epoch. So there's no need to call toInstant
again since you already have an Instant
after the first call. Look at the sample code in the documentation for the function.Alexandru Gheorghe
11/21/2024, 5:57 PMMichael Krussel
11/21/2024, 5:59 PMtoInstant
. pickedDateTime.toInstant(TimeZone.UTC)
says convert pickedDataTime
to an instant assuming the time specified there is in UTC timezone.Oliver.O
11/21/2024, 11:06 PMimport kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
fun main() {
// This datetime has no time zone, it cannot specify a point in time without interpretation.
val zoneLessDateTime = LocalDateTime(year = 2024, monthNumber = 11, dayOfMonth = 21, hour = 18, minute = 41)
// This is the timezone we choose to interpret our zoneLessDateTime.
val localTimeZone = TimeZone.currentSystemDefault()
// Combining the zoneLessDateTime with the time zone makes it an instant, an actual point in time.
val instant = zoneLessDateTime.toInstant(localTimeZone)
println("zone-less: $zoneLessDateTime")
println("instant: $instant")
println("instant in the local time zone: ${instant.toLocalDateTime(localTimeZone)} $localTimeZone")
}
Which produces the following output in my timezone:
zone-less: 2024-11-21T18:41
instant: 2024-11-21T17:41:00Z
instant in the local time zone: 2024-11-21T18:41 Europe/Berlin
The misunderstanding above is: pickedDateTime.toInstant(TimeZone.UTC)
does not convert between time zones. Since your pickedDateTime
never had any time zone, you were basically saying "make pickedDateTime
an instant by interpreting it to be in UTC".Alexandru Gheorghe
11/22/2024, 5:47 AMtimeInTimeZoneA.toInstant(TimeZone.UTC)
and have the time be correctly transitioned to represent datetime in UTC as transformed from timezone A.
There's https://github.com/Kotlin/kotlinx-datetime/discussions/237 but even this uses instantOliver.O
11/22/2024, 9:06 AMZonedDateTime
, which would represent your timeInTimeZoneA
. Currently, the time zone is always a separate entity, which has to be applied when converting to or from a user-readable form (LocalDateTime
).Dmitry Khalanskiy [JB]
11/22/2024, 9:55 AMZonedDateTime
is not provided, as most of its needs are already fulfilled by Instant
. The discussion you've linked to is about the introduction of a data type for some rare special occasions.
If you're getting date and time separately and know which time zone they are in, then this is exactly what @Oliver.O’s example shows: given a LocalDateTime
(the wall-clock representation that a normal person sees), you receive an Instant
(the actual moment in time when something happened). If you then want to find out what a person in the UTC time zone would see, you can do this:
val localDateTimeInZoneA = LocalDate(2024, 11, 22)
.atTime(10, 56)
val instant = localDateTimeInZoneA.toInstant(
TimeZone.of("Europe/Berlin"))
val localDateTimeInUtc = instant.toLocalDateTime(
TimeZone.UTC)