Reputation: 317
i'm trying to get te selected date from DatePicker but always i have one day less than the selected
For example, if I select 14/2/2022 i obtain 13/2/2022 and if I select 8/10/2018 i obtain 7/10/2018
This is my code:
private fun DatePickerSelected() {
val picker = MaterialDatePicker.Builder.datePicker()
.setTitleText("Select date of birth")
.setSelection(MaterialDatePicker.todayInUtcMilliseconds())
.build()
picker.addOnPositiveButtonClickListener {
val date = Date(picker.selection!!)
Log.d("Date",date.toString())
val dateString = SimpleDateFormat("dd/MM/yyyy").format(date)
binding.edtBirthday.editText?.setText(dateString)
}
picker.show(requireActivity().supportFragmentManager, "BirthdayPicker")
}
Which is the problem? Thanks!
Upvotes: 8
Views: 2240
Reputation: 134
I have the same issue in jetpack compose, material date picker ,
Root cause These date pickers return epoch time - AKA UTC (universal Coordinated Time) e.g : if you click a date of 25 jan 2024 , these Api's will return epoch date and time of **25 jan 2024 00:00:00 AM ,
but problem arrives when you directly consume the data, because ,users aren't use UTC time,
FIX convert the UTC -> LocalTimeZone before consuming data in api
fun epochToLocalTimeZoneConvertor(epoch: Long): Long{
val epochCalendar = Calendar.getInstance()
epochCalendar.timeZone = TimeZone.getTimeZone("UTC")
epochCalendar.timeInMillis = epoch
val converterCalendar = Calendar.getInstance()
converterCalendar.set(
epochCalendar.get(Calendar.YEAR),
epochCalendar.get(Calendar.MONTH),
epochCalendar.get(Calendar.DATE),
epochCalendar.get(Calendar.HOUR_OF_DAY),
epochCalendar.get(Calendar.MINUTE),
)
converterCalendar.timeZone = TimeZone.getDefault()
return converterCalendar.timeInMillis }
this solution is written in Kotlin,
Upvotes: 3
Reputation: 547
It turns out that the result from a call to picker is a timestamp in UTC timezone, all you gotta do is to convert it to yout local timezone.
Below is the logic to show a DialogPicker with a listener that converts the result from UTC to the device´s time zone:
// create the dialog picker
val picker = MaterialDatePicker.Builder
.datePicker()
.setSelection(initialDate)// initial date can be a date on local timezone
.setTitleText("")
.build()
picker.addOnPositiveButtonClickListener {
// create an object with a matching timezone
val utcDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(it), ZoneOffset.UTC)
// create an object converting from UTC to the device´s timezone
val myTimeZoneDate = ZonedDateTime.of(utcDate, ZoneId.systemDefault())
// get the long timestamp to use as you want
val myTimeZoneDateLong = myTimeZoneDate.toInstant().toEpochMilli()
}
// show picker
picker.show(parentFragmentManager, "tag")
Remember: You should always handle Date as time zoneless what includes store it in a database, using it to synchronize data or make comparations. The only exception is when you show it to user in this case obviously it should be converted to local timezone. Not doing this will cause really big problems if your users use your app with diferent timezones.
Upvotes: 5
Reputation: 79
try this code, add one day
date.add(Calendar.DAY_OF_MONTH,1)
Upvotes: -1
Reputation: 317
I found the solution using calendar
picker.addOnPositiveButtonClickListener {
val utc = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
utc.timeInMillis = it
//+1: The first month of the year in the Gregorian and Julian calendars is JANUARY which is 0
val stringData = "${utc.get(Calendar.DAY_OF_MONTH)}/${utc.get(Calendar.MONTH)+1}/${utc.get(Calendar.YEAR)}"
binding.edtBirthday.editText?.setText(stringData)
}
Upvotes: 1