MaterialDatePicker returns incorrect date after selection
Asked Answered
R

3

6

For some unknown reason, MaterialDatePicker returns incorrect date after selection. For example, user is in Mexico region with timezone: America/Tijuana. When he selects in visual representation: 2021-10-05, in resulting text I have -1 day, 2021-10-04. For RU region everything works fine. Here is the code:

public void startDateSelectionPicker() {
    try {
        MaterialDatePicker<Long> picker = MaterialDatePicker.Builder.datePicker()
                .setSelection(MaterialDatePicker.todayInUtcMilliseconds())
                .setTheme(R.style.CustomDatePickerDialog)
                .build();

        picker.addOnPositiveButtonClickListener(selection -> {
            TimeZone t = TimeZone.getDefault();
            Calendar c1 = Calendar.getInstance();
            c1.setTimeInMillis(selection);
            c1.setTimeZone(TimeZone.getDefault());

//here I need to receive correct date, but receiving -1 from originally selected date.

            String date = ToolsManager.calendarToDate(this, c1, "yyyy-MM-dd");
        });
        picker.show(getSupportFragmentManager(), picker.getTag());
    } catch (IllegalArgumentException e) {
    }
}

public static String calendarToDate(Context context, Calendar calendar, String dateFormat) {
        if (calendar == null) {
            return null;
        }

        Locale locale = context.getResources().getConfiguration().locale;
        DateFormat df = new SimpleDateFormat(dateFormat, locale);

        return df.format(calendar.getTime());
    }

And also when I am setting: .setSelection(MaterialDatePicker.todayInUtcMilliseconds())

it display 18 of October on calendar, but really today is 20 of Octobeer.

Renwick answered 20/10, 2021 at 14:58 Comment(0)
R
5

I have solved this issue with such code:

public void startDateSelectionPicker() {
        try {
            MaterialDatePicker<Long> picker = MaterialDatePicker.Builder.datePicker()
                    .setSelection(MaterialDatePicker.todayInUtcMilliseconds())
                    .setTheme(R.style.CustomDatePickerDialog)
                    .build();

            picker.addOnPositiveButtonClickListener(selection -> {
                Calendar utc = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
                utc.setTimeInMillis(selection);
                String date = ToolsManager.calendarToDate(this, utc, ToolsManager.LETY_FILTRATION_DATE_FORMAT);
                binding.textview.setText(date);
            });
            picker.show(getSupportFragmentManager(), picker.getTag());
        } catch (IllegalArgumentException e) {
        }
    }

public static String calendarToDate(Context context, Calendar calendar, String dateFormat) {
        if (calendar == null) {
            return null;
        }

        Locale locale = context.getResources().getConfiguration().locale;
        DateFormat df = new SimpleDateFormat(dateFormat, locale);
        TimeZone timeZone = TimeZone.getTimeZone("UTC");
        df.setTimeZone(timeZone);

        Date d = calendar.getTime();
        return df.format(d);
    }

So, the core solver was to create Calendar with UTC timezone (because it works only with UTC values, and in formatted also I had to init UTC timezone, in other case it was shifting values for some hours depending on time zone.

Also these two links helped to understand: https://github.com/material-components/material-components-android/blob/00dc4c6b5af3939418f1c7d1e4c737dc3fb7fd67/docs/components/Picker.md#timezones

https://github.com/material-components/material-components-android/tree/master/catalog/java/io/material/catalog/datepicker

And converter: https://www.epochconverter.com/

Renwick answered 21/10, 2021 at 13:22 Comment(0)
R
0

Use:

   c1.setTimeZone(TimeZone.getTimeZone("UTC"));

instead of

   c1.setTimeZone(TimeZone.getDefault());

See if this helps or not:

    Calendar c1 = Calendar.getInstance(Locale.getDefault())
Runion answered 20/10, 2021 at 15:16 Comment(4)
Thanks, but didn't help. Still returns -1 day valueRenwick
Try this it may work Calendar c1 = Calendar.getInstance(Locale.getDefault()) instead of Calendar c1 = Calendar.getInstance();Runion
Your answer was helpful, but it didn't fixed my issue fully, so I +1, thank you, but down below I have posted the fully working example with links to official documentations and samples by this library.Renwick
Please try to explain a bit more next time so that the people seeing this in future understand why is it happeningAhmedahmedabad
F
0
val datePickerState = rememberDatePickerState(
    initialSelectedDateMillis = System.currentTimeMillis()
)
DatePicker(state = datePickerState, modifier = Modifier.padding(16.dp))

Text(
    text = "Selected date: ${
        LocalDateTime.ofInstant(
            Instant.ofEpochMilli(datePickerState.selectedDateMillis!!),
            ZoneId.of("UTC")
        ) ?: "no selection"
    }",
    modifier = Modifier.align(Alignment.CenterHorizontally)
)
Finkelstein answered 11/7 at 6:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.