Skip to content

Commit

Permalink
[DatePicker] Fix wrong month title with certain months
Browse files Browse the repository at this point in the history
The issue is caused by failing to correctly take the daylight saving time into account - internally we use UTC time to represent dates, however when generating month titles we try to calculate the time difference of the UTC time and the local time, which can result in off-by-one errors when the first day of the month is also the first day of the daylight saving time, e.g., April 1, 1979 in Poland.

Fixes this by always using UTC time to generate month titles. Also clears the relevant implementation for a little bit since context is actually not required when we only need to format years and months.

Resolves #1935

PiperOrigin-RevId: 413505587
  • Loading branch information
drchen authored and dsn5ft committed Dec 2, 2021
1 parent 2e73d1a commit 62e8993
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 17 deletions.
Expand Up @@ -15,7 +15,6 @@
*/
package com.google.android.material.datepicker;

import android.content.Context;
import android.icu.text.DateFormat;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
Expand All @@ -26,17 +25,15 @@
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/** Util methods for formatting date strings for use in {@link MaterialDatePicker}. */
class DateStrings {

private DateStrings() {}

static String getYearMonth(Context context, long timeInMillis) {
int flags = DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_NO_MONTH_DAY;
long offsetMillis = TimeZone.getDefault().getOffset(timeInMillis);
return DateUtils.formatDateTime(context, timeInMillis - offsetMillis, flags);
static String getYearMonth(long timeInMillis) {
int flags = DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_NO_MONTH_DAY | DateUtils.FORMAT_UTC;
return DateUtils.formatDateTime(null, timeInMillis, flags);
}

static String getYearMonthDay(long timeInMillis) {
Expand Down
Expand Up @@ -390,7 +390,7 @@ public void onInitializeAccessibilityNodeInfo(
yearFrame = root.findViewById(R.id.mtrl_calendar_year_selector_frame);
dayFrame = root.findViewById(R.id.mtrl_calendar_day_selector_frame);
setSelector(CalendarSelector.DAY);
monthDropSelect.setText(current.getLongName(root.getContext()));
monthDropSelect.setText(current.getLongName());
recyclerView.addOnScrollListener(
new OnScrollListener() {
@Override
Expand Down
5 changes: 2 additions & 3 deletions lib/java/com/google/android/material/datepicker/Month.java
Expand Up @@ -15,7 +15,6 @@
*/
package com.google.android.material.datepicker;

import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.IntDef;
Expand Down Expand Up @@ -189,9 +188,9 @@ Month monthsLater(int months) {

/** Returns a localized String representation of the month name and year. */
@NonNull
String getLongName(Context context) {
String getLongName() {
if (longName == null) {
longName = DateStrings.getYearMonth(context, firstOfMonth.getTimeInMillis());
longName = DateStrings.getYearMonth(firstOfMonth.getTimeInMillis());
}
return longName;
}
Expand Down
Expand Up @@ -37,7 +37,6 @@
*/
class MonthsPagerAdapter extends RecyclerView.Adapter<MonthsPagerAdapter.ViewHolder> {

private final Context context;
@NonNull private final CalendarConstraints calendarConstraints;
private final DateSelector<?> dateSelector;
private final OnDayClickListener onDayClickListener;
Expand All @@ -63,7 +62,6 @@ class MonthsPagerAdapter extends RecyclerView.Adapter<MonthsPagerAdapter.ViewHol
int labelHeight =
MaterialDatePicker.isFullscreen(context) ? MaterialCalendar.getDayHeight(context) : 0;

this.context = context;
this.itemHeight = daysHeight + labelHeight;
this.calendarConstraints = calendarConstraints;
this.dateSelector = dateSelector;
Expand Down Expand Up @@ -106,7 +104,7 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType)
@Override
public void onBindViewHolder(@NonNull MonthsPagerAdapter.ViewHolder viewHolder, int position) {
Month month = calendarConstraints.getStart().monthsLater(position);
viewHolder.monthTitle.setText(month.getLongName(viewHolder.itemView.getContext()));
viewHolder.monthTitle.setText(month.getLongName());
final MaterialCalendarGridView monthGrid = viewHolder.monthGrid.findViewById(R.id.month_grid);

if (monthGrid.getAdapter() != null && month.equals(monthGrid.getAdapter().month)) {
Expand Down Expand Up @@ -141,7 +139,7 @@ public int getItemCount() {

@NonNull
CharSequence getPageTitle(int position) {
return getPageMonth(position).getLongName(context);
return getPageMonth(position).getLongName();
}

@NonNull
Expand Down
Expand Up @@ -126,10 +126,10 @@ public void pageTitles() {
.build(),
/* onDayClickListener= */ null);
assertEquals(
feb2016.getLongName(context), monthsAdapter.getPageTitle(/* position= */ 0).toString());
feb2016.getLongName(), monthsAdapter.getPageTitle(/* position= */ 0).toString());
assertEquals(
march2016.getLongName(context), monthsAdapter.getPageTitle(/* position= */ 1).toString());
march2016.getLongName(), monthsAdapter.getPageTitle(/* position= */ 1).toString());
assertEquals(
april2016.getLongName(context), monthsAdapter.getPageTitle(/* position= */ 2).toString());
april2016.getLongName(), monthsAdapter.getPageTitle(/* position= */ 2).toString());
}
}

0 comments on commit 62e8993

Please sign in to comment.