androidkotlintimezoneutc

Android Kotlin LocalDate Timestamp conversion


I have a problem with my DatePicker and the conversion of LocalDate an timestamp

When opening the DatePicker, I choose a day and on confirm I convert the timestampt to a LocalDate and store in an a value.
When opening the DatePicker I want to convert the LocalDate to a timestamp and initial select this day in the DatePicker.

The Problem is now, that the saved LocalDate is correct. But the loaded Date for setting the initial Date in the DatePicker is one day off. It is one day before the actual date of LocalDate.

I tried this. First line prints this: 1728597600000 second line prints this: 1728518400000

I don't understand why.

println("Initial LocalDate: ${convertLocalDateToTimestamp(selectedDate.value)}")
                val datePickerState = rememberDatePickerState(
                    initialSelectedDateMillis = convertLocalDateToTimestamp(selectedDate.value)
                )
                println("Initial LocalDate: ${datePickerState.selectedDateMillis}")

CustomDatePicker is just a wrapper for the Standard DatePicker.

DatePicker(state = datePickerState)
fun convertTimestampToLocalDate(timestamp: Long, timeZone: ZoneId = ZoneId.systemDefault()): LocalDate {
    return Instant.ofEpochMilli(timestamp)
        .atZone(timeZone)
        .toLocalDate()
}

fun convertLocalDateToTimestamp(localDate: LocalDate): Long {
    val zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault())
    val instant = zonedDateTime.toInstant()
    return instant.toEpochMilli()
}
val selectedDate = remember { mutableStateOf(LocalDate.now()) }

val datePickerState = rememberDatePickerState(
                        initialSelectedDateMillis = convertLocalDateToTimestamp(selectedDate.value)
                    )
                    CustomDatePickerDialog(
                        datePickerState,
                        isDatePickerShown,
                        onClick = {
                            selectedDate.value =
                                convertTimestampToLocalDate(datePickerState.selectedDateMillis!!)
                        }
                    )

I printed out the TimeZone. It is correct (Europe/Berlin)
I printed out the Timestamp. it is 1728597600000 which is 10. October in UTC but locally in Germany it is 11. October.
Smartphone localization is set correctly
I printed out zonedDateTime: 2024-10-11T00:00+02:00[Europe/Berlin]


Solution

  • I found the solution.

    DatePicker allways expect the standard UTC Time Zone for Millis. Not the Localized one.

    So. ZoneId.systemDefault() is wrong. You need UTC.toZoneId()

    fun convertLocalDateToTimestampUTC(localDate: LocalDate): Long {
       val zonedDateTime = localDate.atStartOfDay(UTC.toZoneId())
       val instant = zonedDateTime.toInstant()
       return instant.toEpochMilli()
    }