MaterialDatePicker android 选择指定日期之前的日期而不是指定日期

问题描述 投票:0回答:3

当我创建

MaterialDatePicker
时,它会选择我指定的日期的前一个日期,而不是指定的日期:

您可以看到 EditText 的日期为 2019 年 5 月 12 日,但 DatePicker 显示为 2019 年 5 月 11 日

You can see that the EditText has May 12, 2019 but the DatePicker shows as May 11, 2019

openDatePicker 的代码是:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    binding = ActivityMainBinding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());

    setSupportActionBar(binding.toolbar);

    String dateText = "May 12, 2019";
    binding.etDate.setText(dateText);
    try {
        Date date = new SimpleDateFormat("MMM dd, yyyy").parse(dateText);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        binding.etDate.setTag(cal);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    binding.etDate.setOnClickListener(v -> {
        Calendar defaultCal = Calendar.getInstance();
        if (binding.etDate.getTag() != null) {
            defaultCal = (Calendar) binding.etDate.getTag();
        }
        openDatePicker(binding.etDate, defaultCal, createDatePickerConstraints(defaultCal, null, null));
    });
}

private void openDatePicker(final EditText tv, Calendar defaultDate, CalendarConstraints constraints) {
    try {
        MaterialDatePicker.Builder<Long> builder = MaterialDatePicker.Builder.datePicker();
        builder.setCalendarConstraints(constraints);
        builder.setSelection(defaultDate.getTimeInMillis());
        MaterialDatePicker<Long> datePicker = builder.build();
        datePicker.addOnPositiveButtonClickListener(selection -> {
            Calendar selectedCalObj = Calendar.getInstance();
            selectedCalObj.setTimeInMillis((long) selection);
            SimpleDateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH);
            dateFormat.setTimeZone(TimeZone.getDefault());
            String date = dateFormat.format(selectedCalObj.getTime())
                    .replace("a.m.", "AM")
                    .replace("p.m.", "PM")
                    .replace("am", "AM")
                    .replace("pm", "PM");;
            tv.setText(date);
            tv.setTag(selectedCalObj);
        });
        datePicker.addOnNegativeButtonClickListener(view -> {
            Log.d(TAG, "Cancelled");
        });
        datePicker.show(getSupportFragmentManager(), TAG);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

// helper function to give the constraints:
private CalendarConstraints createDatePickerConstraints(final Calendar entry, final Calendar start, final Calendar end) {
    CalendarConstraints.Builder constraintsBuilder = new CalendarConstraints.Builder();
    if (entry != null)
        constraintsBuilder.setOpenAt(entry.getTimeInMillis());
    if (start != null) {
        constraintsBuilder.setStart(start.getTimeInMillis());
        constraintsBuilder.setValidator(DateValidatorPointForward.from(start.getTimeInMillis()));
    }
    if (end != null) {
        constraintsBuilder.setEnd(end.getTimeInMillis());
        constraintsBuilder.setValidator(DateValidatorPointBackward.before(end.getTimeInMillis()));
    }
    return constraintsBuilder.build();
}

我知道的可能方法是通过将

EditText
处的
binding.etDate.setTag
onCreate
偏移到我所在的当前时区来修复(因为问题是目前的 2019 年 5 月 12 日 0:00:00 DatePicker 在打开时选择上一个日期的问题),但如果有更好的方法来做到这一点,那将非常有帮助,因为这似乎是一个更常见的代码,在任何地方都很有用,因此我可以将其作为一个库并在我的主应用程序中将其称为库代码。

如有任何帮助,我们将不胜感激。

java android materialdatepicker
3个回答
3
投票

因此,在浏览了大量 GitHub 问题后,我发现

MaterialDatePicker
仅具有 UTC 时间的 getter 和 setter,因此偏移值不是一个好主意,因此将当前时间作为 UTC 传递给它,如下所示: 将当前时区转换为 UTC 的链接

我的示例代码:

try { 
    SimpleDateFormat fromDate = new SimpleDateFromat("MMM dd, yyyy");
    fromDate.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date date = fromDate.parse(inputDateString);
    Calendar cal = Calendar.getInstance(Locale.getDefault());
    cal.setTime(date);
    binding.etDate.setTag(cal);
} catch (ParseException e) {
    e.printStackTrace();
}

稍后我将使用

EditText
中的标签来填充我的
CalendarConstraints
MaterialDatePicker
setSelection

希望这对您有帮助!


0
投票

builder.setSelection(defaultDate.getTimeInMillis());

你必须像这样添加当前时间的偏移量

builder.setSelection(defaultDate.getTimeInMillis() + TimeZone.getDefault().getOffset(defaultDate.getTimeInMillis()));


0
投票

我来晚了一点。我也遇到了同样的问题。这是我想出的将日期转换为 UTC 时区的毫秒的解决方案。解决方案是在 kotlin 中。

val Date.utcMilliSeconds: Long
get() {
    val calendar = Calendar.getInstance()
    calendar.time = this

    val utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
    utcCalendar.set(
        calendar.get(Calendar.YEAR),
        calendar.get(Calendar.MONTH),
        calendar.get(Calendar.DAY_OF_MONTH)
    )
    return utcCalendar.timeInMillis
}

utcMilliSeconds
是kotlin中的扩展字段,可以直接在日期对象上调用。创建日期选择器时,您可以按 UTC 格式设置选择,如下所示。

val datePicker =
    MaterialDatePicker.Builder.datePicker()
        .setTitleText("Select payment date")
        .setSelection(
            date?.utcMilliSeconds ?: MaterialDatePicker.todayInUtcMilliseconds()
        )
        .setCalendarConstraints(constraintsBuilder.build())
        .build()
datePicker.show(parentFragmentManager, TAG)

在这里,在

setSelection()
方法中,我们使用之前创建的扩展字段
utcMilliSeconds
将日期对象转换为 UTC 时区中的毫秒。

希望这对某人有帮助。快乐编码...😇

© www.soinside.com 2019 - 2024. All rights reserved.