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月11日T00:00+02:00[Europe/Berlin]
2 Answers 2
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()
}
Comments
Based on your output, it seems the conversion functions are working as intended. The timestamp 1728597600000 corresponds to October 10th, 2024, in UTC. When converted to the Europe/Berlin time zone, it correctly becomes October 11th, 2024, due to the time difference.
You can check below mentioned point :
Daylight Saving Time:
Ensure that your logic accounts for daylight saving time, which seems correct given your output. Berlin is UTC+2 during daylight saving time.
DatePicker Initialization:
Verify that the DatePicker correctly interprets the initial timestamp. The timestamp should correspond to the local start of the day (midnight) on October 11th.
Conversion and Display:
Ensure that the conversion from timestamp to LocalDate and back to timestamp doesn’t introduce any off-by-one errors. Your current functions appear correct, but double-check that DatePicker uses the correct initialSelectedDateMillis.
Check DatePicker Logic:
Review the CustomDatePickerDialog implementation to ensure it initializes and updates correctly. Make sure it correctly interprets the timestamp in the local time zone.
println("Initial LocalDate: ${selectedDate.value}") // Should print 2024年10月11日 println("Initial Timestamp: ${initialTimestamp}") // Should be 1728597600000 println("Selected Timestamp: ${datePickerState.selectedDateMillis}") // Check this value println("Converted LocalDate: ${convertTimestampToLocalDate(datePickerState.selectedDateMillis!!)}") // Should print 2024年10月11日
Also ensure that selectedDateMillis is not null before using it in convertTimestampToLocalDate.