Reputation: 61
When I create a MaterialDatePicker
it picks the previous date of the date I specified, instead of the specified date:
You can see that the EditText has May 12, 2019 but the DatePicker shows as May 11, 2019
Code for the openDatePicker is:
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();
}
Possible way that I know to is to fix by offsetting the EditText
binding.etDate.setTag
at onCreate
to the current timezone I am in (since the issue is the time being May 12, 2019 0:00:00 that might be the issue of the DatePicker picking the previous date when opened) but it would be really helpful if there is a better way to do this, since this seems like a more common code that will be useful everywhere so that I can make it as a library and just call this as a library code in my main application.
Any help would be appreciated.
Upvotes: 3
Views: 1714
Reputation: 11
I am a little late here. I also end up with the same issue. Here is the solution that I have came up with to convert the date into milliseconds in UTC timezone. The solution is in 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
is an extension field in kotlin that can be directly called on a date object. When creating the date picker, you can set the selection in UTC as given below.
val datePicker =
MaterialDatePicker.Builder.datePicker()
.setTitleText("Select payment date")
.setSelection(
date?.utcMilliSeconds ?: MaterialDatePicker.todayInUtcMilliseconds()
)
.setCalendarConstraints(constraintsBuilder.build())
.build()
datePicker.show(parentFragmentManager, TAG)
Here, in the setSelection()
method, we are converting our date object into milliseconds in UTC timezone by using the extension field utcMilliSeconds
that we have created before.
Hope this helps someone. Happy coding...😇
Upvotes: 1
Reputation: 61
So, after going through loads of GitHub issues, I found that MaterialDatePicker
has getters and setters only for time in UTC, so offsetting values won't be a good idea so pass in the current time to it as a UTC like: Link for converting current timezone to UTC
My sample code:
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();
}
I will be using the tag from the EditText
later to populate my CalendarConstraints
and the MaterialDatePicker
's setSelection
later.
Hope this is helpful!
Upvotes: 3
Reputation: 5261
builder.setSelection(defaultDate.getTimeInMillis());
You have to add offset with current time like this
builder.setSelection(defaultDate.getTimeInMillis() + TimeZone.getDefault().getOffset(defaultDate.getTimeInMillis()));
Upvotes: 0