Skip to content

Commit 85c40a6

Browse files
paulfthomasleticiarossi
authored andcommitted
[MaterialDatePicker] Internal change
PiperOrigin-RevId: 448042520
1 parent 86b512a commit 85c40a6

File tree

10 files changed

+152
-38
lines changed

10 files changed

+152
-38
lines changed

catalog/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ dependencies {
3131

3232
testImplementation "androidx.test:core:${project.rootProject.ext.testRunnerVersion}"
3333
testImplementation "androidx.test:runner:${project.rootProject.ext.testRunnerVersion}"
34-
testImplementation "junit:junit:4.12"
34+
testImplementation "junit:junit:4.13.2"
3535
testImplementation "com.google.truth:truth:${project.rootProject.ext.truthVersion}"
3636
testImplementation "org.mockito:mockito-core:${project.rootProject.ext.mockitoCoreVersion}"
3737
testImplementation "org.robolectric:robolectric:${project.rootProject.ext.robolectricVersion}"

lib/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ dependencies {
2424

2525
testImplementation "androidx.test:core:${testRunnerVersion}"
2626
testImplementation "androidx.test:runner:${testRunnerVersion}"
27-
testImplementation "junit:junit:4.12"
27+
testImplementation "junit:junit:4.13.2"
2828
testImplementation "com.google.truth:truth:${truthVersion}"
2929
testImplementation "org.mockito:mockito-core:${mockitoCoreVersion}"
3030
testImplementation "org.robolectric:robolectric:${robolectricVersion}"

lib/java/com/google/android/material/datepicker/CalendarConstraints.java

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515
*/
1616
package com.google.android.material.datepicker;
1717

18+
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
19+
1820
import android.os.Bundle;
1921
import android.os.Parcel;
2022
import android.os.Parcelable;
2123
import androidx.annotation.NonNull;
2224
import androidx.annotation.Nullable;
25+
import androidx.annotation.RestrictTo;
2326
import androidx.core.util.ObjectsCompat;
2427
import java.util.Arrays;
2528
import java.util.Calendar;
@@ -37,6 +40,7 @@ public final class CalendarConstraints implements Parcelable {
3740
@NonNull private final DateValidator validator;
3841

3942
@Nullable private Month openAt;
43+
private final int firstDayOfWeek;
4044

4145
private final int yearSpan;
4246
private final int monthSpan;
@@ -57,17 +61,23 @@ private CalendarConstraints(
5761
@NonNull Month start,
5862
@NonNull Month end,
5963
@NonNull DateValidator validator,
60-
@Nullable Month openAt) {
64+
@Nullable Month openAt,
65+
int firstDayOfWeek) {
6166
this.start = start;
6267
this.end = end;
6368
this.openAt = openAt;
69+
this.firstDayOfWeek = firstDayOfWeek;
6470
this.validator = validator;
6571
if (openAt != null && start.compareTo(openAt) > 0) {
6672
throw new IllegalArgumentException("start Month cannot be after current Month");
6773
}
6874
if (openAt != null && openAt.compareTo(end) > 0) {
6975
throw new IllegalArgumentException("current Month cannot be after end Month");
7076
}
77+
if (firstDayOfWeek < 0
78+
|| firstDayOfWeek > UtcDates.getUtcCalendar().getMaximum(Calendar.DAY_OF_WEEK)) {
79+
throw new IllegalArgumentException("firstDayOfWeek is not valid");
80+
}
7181
monthSpan = start.monthsUntil(end) + 1;
7282
yearSpan = end.year - start.year + 1;
7383
}
@@ -106,6 +116,11 @@ void setOpenAt(@Nullable Month openAt) {
106116
this.openAt = openAt;
107117
}
108118

119+
/** Returns the firstDayOfWeek. */
120+
int getFirstDayOfWeek() {
121+
return firstDayOfWeek;
122+
}
123+
109124
/**
110125
* Returns the total number of {@link java.util.Calendar#MONTH} included in {@code start} to
111126
* {@code end}.
@@ -134,12 +149,13 @@ public boolean equals(Object o) {
134149
return start.equals(that.start)
135150
&& end.equals(that.end)
136151
&& ObjectsCompat.equals(openAt, that.openAt)
152+
&& firstDayOfWeek == that.firstDayOfWeek
137153
&& validator.equals(that.validator);
138154
}
139155

140156
@Override
141157
public int hashCode() {
142-
Object[] hashedFields = {start, end, openAt, validator};
158+
Object[] hashedFields = {start, end, openAt, firstDayOfWeek, validator};
143159
return Arrays.hashCode(hashedFields);
144160
}
145161

@@ -155,7 +171,8 @@ public CalendarConstraints createFromParcel(@NonNull Parcel source) {
155171
Month end = source.readParcelable(Month.class.getClassLoader());
156172
Month openAt = source.readParcelable(Month.class.getClassLoader());
157173
DateValidator validator = source.readParcelable(DateValidator.class.getClassLoader());
158-
return new CalendarConstraints(start, end, validator, openAt);
174+
int firstDayOfWeek = source.readInt();
175+
return new CalendarConstraints(start, end, validator, openAt, firstDayOfWeek);
159176
}
160177

161178
@NonNull
@@ -176,6 +193,7 @@ public void writeToParcel(Parcel dest, int flags) {
176193
dest.writeParcelable(end, /* parcelableFlags= */ 0);
177194
dest.writeParcelable(openAt, /* parcelableFlags= */ 0);
178195
dest.writeParcelable(validator, /* parcelableFlags = */ 0);
196+
dest.writeInt(firstDayOfWeek);
179197
}
180198

181199
/**
@@ -214,6 +232,7 @@ public static final class Builder {
214232
private long start = DEFAULT_START;
215233
private long end = DEFAULT_END;
216234
private Long openAt;
235+
private int firstDayOfWeek;
217236
private DateValidator validator = DateValidatorPointForward.from(Long.MIN_VALUE);
218237

219238
public Builder() {}
@@ -222,6 +241,7 @@ public Builder() {}
222241
start = clone.start.timeInMillis;
223242
end = clone.end.timeInMillis;
224243
openAt = clone.openAt.timeInMillis;
244+
firstDayOfWeek = clone.firstDayOfWeek;
225245
validator = clone.validator;
226246
}
227247

@@ -306,6 +326,19 @@ public Builder setOpenAt(long month) {
306326
return this;
307327
}
308328

329+
/**
330+
* Sets what the first day of the week is; e.g., <code>Calendar.SUNDAY</code> in the U.S.,
331+
* <code>Calendar.MONDAY</code> in France.
332+
*
333+
* @hide
334+
*/
335+
@RestrictTo(LIBRARY_GROUP)
336+
@NonNull
337+
public Builder setFirstDayOfWeek(int firstDayOfWeek) {
338+
this.firstDayOfWeek = firstDayOfWeek;
339+
return this;
340+
}
341+
309342
/**
310343
* Limits valid dates to those for which {@link DateValidator#isValid(long)} is true. Defaults
311344
* to all dates as valid.
@@ -325,7 +358,8 @@ public CalendarConstraints build() {
325358
Month.create(start),
326359
Month.create(end),
327360
(DateValidator) deepCopyBundle.getParcelable(DEEP_COPY_VALIDATOR_KEY),
328-
openAt == null ? null : Month.create(openAt));
361+
openAt == null ? null : Month.create(openAt),
362+
firstDayOfWeek);
329363
}
330364
}
331365
}

lib/java/com/google/android/material/datepicker/DaysOfWeekAdapter.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,31 @@
3333
/**
3434
* A single row adapter representing the days of the week for {@link Calendar}.
3535
*
36-
* <p>This {@link android.widget.Adapter} respects the {@link Calendar#getFirstDayOfWeek()}
37-
* determined by {@link Locale#getDefault()}.
38-
*
3936
* @hide
4037
*/
4138
class DaysOfWeekAdapter extends BaseAdapter {
4239

43-
@NonNull private final Calendar calendar;
44-
private final int daysInWeek;
40+
@NonNull private final Calendar calendar = UtcDates.getUtcCalendar();
41+
private final int daysInWeek = calendar.getMaximum(Calendar.DAY_OF_WEEK);
4542
private final int firstDayOfWeek;
4643
/** Style value from Calendar.NARROW_FORMAT unavailable before 1.8 */
4744
private static final int NARROW_FORMAT = 4;
4845

4946
private static final int CALENDAR_DAY_STYLE =
5047
VERSION.SDK_INT >= VERSION_CODES.O ? NARROW_FORMAT : Calendar.SHORT;
5148

49+
/**
50+
* <p>This {@link android.widget.Adapter} respects the {@link Calendar#getFirstDayOfWeek()}
51+
* determined by {@link Locale#getDefault()}.
52+
*/
5253
public DaysOfWeekAdapter() {
53-
calendar = UtcDates.getUtcCalendar();
54-
daysInWeek = calendar.getMaximum(Calendar.DAY_OF_WEEK);
5554
firstDayOfWeek = calendar.getFirstDayOfWeek();
5655
}
5756

57+
public DaysOfWeekAdapter(int firstDayOfWeek) {
58+
this.firstDayOfWeek = firstDayOfWeek;
59+
}
60+
5861
@Nullable
5962
@Override
6063
public Integer getItem(int position) {

lib/java/com/google/android/material/datepicker/MaterialCalendar.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ public void onInitializeAccessibilityNodeInfo(
161161
accessibilityNodeInfoCompat.setCollectionInfo(null);
162162
}
163163
});
164-
daysHeader.setAdapter(new DaysOfWeekAdapter());
164+
int firstDayOfWeek = calendarConstraints.getFirstDayOfWeek();
165+
daysHeader.setAdapter(
166+
firstDayOfWeek > 0 ? new DaysOfWeekAdapter(firstDayOfWeek) : new DaysOfWeekAdapter());
165167
daysHeader.setNumColumns(earliestMonth.daysInWeek);
166168
daysHeader.setEnabled(false);
167169

lib/java/com/google/android/material/datepicker/Month.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,10 @@ static Month current() {
102102
return new Month(UtcDates.getTodayCalendar());
103103
}
104104

105-
int daysFromStartOfWeekToFirstOfMonth() {
106-
int difference = firstOfMonth.get(Calendar.DAY_OF_WEEK) - firstOfMonth.getFirstDayOfWeek();
105+
int daysFromStartOfWeekToFirstOfMonth(int firstDayOfWeek) {
106+
int difference =
107+
firstOfMonth.get(Calendar.DAY_OF_WEEK)
108+
- (firstDayOfWeek > 0 ? firstDayOfWeek : firstOfMonth.getFirstDayOfWeek());
107109
if (difference < 0) {
108110
difference = difference + daysInWeek;
109111
}

lib/java/com/google/android/material/datepicker/MonthAdapter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ public boolean hasStableIds() {
7575
* Returns a {@link Long} object for the given grid position
7676
*
7777
* @param position Index for the item. 0 matches the {@link Calendar#getFirstDayOfWeek()} for the
78-
* first week of the month represented by {@link Month}.
78+
* first week of the month represented by {@link Month} or {@link
79+
* CalendarConstraints#getFirstDayOfWeek()} if set.
7980
* @return A {@link Long} representing the day at the position or null if the position does not
8081
* represent a valid day in the month.
8182
*/
@@ -214,7 +215,7 @@ private void initializeStyles(Context context) {
214215
* be greater than 0.
215216
*/
216217
int firstPositionInMonth() {
217-
return month.daysFromStartOfWeekToFirstOfMonth();
218+
return month.daysFromStartOfWeekToFirstOfMonth(calendarConstraints.getFirstDayOfWeek());
218219
}
219220

220221
/**

lib/javatests/com/google/android/material/datepicker/CalendarConstraintsTest.java

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
package com.google.android.material.datepicker;
1717

1818
import static com.google.common.truth.Truth.assertThat;
19+
import static java.util.Calendar.SATURDAY;
20+
import static java.util.Calendar.SUNDAY;
1921
import static org.junit.Assert.assertEquals;
22+
import static org.junit.Assert.assertNull;
23+
import static org.junit.Assert.assertThrows;
2024

2125
import com.google.android.material.internal.ParcelableTestUtils;
2226
import java.util.Calendar;
23-
import org.junit.Rule;
2427
import org.junit.Test;
25-
import org.junit.rules.ExpectedException;
2628
import org.junit.runner.RunWith;
2729
import org.robolectric.RobolectricTestRunner;
2830

@@ -34,8 +36,6 @@ public class CalendarConstraintsTest {
3436
private static final long MARCH_2016 = Month.create(2016, Calendar.MARCH).timeInMillis;
3537
private static final long APRIL_2016 = Month.create(2016, Calendar.APRIL).timeInMillis;
3638

37-
@Rule public final ExpectedException exceptionRule = ExpectedException.none();
38-
3939
@Test
4040
public void equalAfterParceling() {
4141
CalendarConstraints originalBounds =
@@ -96,26 +96,67 @@ public void currentDefaultsToStartIfTodayIsInvalid() {
9696
CalendarConstraints calendarConstraints =
9797
new CalendarConstraints.Builder().setStart(FEB_2016).setEnd(APRIL_2016).build();
9898

99-
assertEquals(null, calendarConstraints.getOpenAt());
99+
assertNull(calendarConstraints.getOpenAt());
100100
}
101101

102102
@Test
103103
public void illegalCurrentMonthFails() {
104-
exceptionRule.expect(IllegalArgumentException.class);
105-
new CalendarConstraints.Builder()
106-
.setStart(FEB_2016)
107-
.setEnd(MARCH_2016)
108-
.setOpenAt(APRIL_2016)
109-
.build();
104+
assertThrows(
105+
IllegalArgumentException.class,
106+
() ->
107+
new CalendarConstraints.Builder()
108+
.setStart(FEB_2016)
109+
.setEnd(MARCH_2016)
110+
.setOpenAt(APRIL_2016)
111+
.build());
110112
}
111113

112114
@Test
113115
public void illegalEndMonthFails() {
114-
exceptionRule.expect(IllegalArgumentException.class);
115-
new CalendarConstraints.Builder()
116-
.setStart(MARCH_2016)
117-
.setEnd(FEB_2016)
118-
.setOpenAt(MARCH_2016)
119-
.build();
116+
assertThrows(
117+
IllegalArgumentException.class,
118+
() ->
119+
new CalendarConstraints.Builder()
120+
.setStart(MARCH_2016)
121+
.setEnd(FEB_2016)
122+
.setOpenAt(MARCH_2016)
123+
.build());
124+
}
125+
126+
@Test
127+
public void firstDayOfWeek_sunday() {
128+
CalendarConstraints calendarConstraints =
129+
new CalendarConstraints.Builder().setFirstDayOfWeek(SUNDAY).build();
130+
131+
assertThat(calendarConstraints.getFirstDayOfWeek()).isEqualTo(SUNDAY);
132+
}
133+
134+
@Test
135+
public void firstDayOfWeek_saturday() {
136+
CalendarConstraints calendarConstraints =
137+
new CalendarConstraints.Builder().setFirstDayOfWeek(SATURDAY).build();
138+
139+
assertThat(calendarConstraints.getFirstDayOfWeek()).isEqualTo(SATURDAY);
140+
}
141+
142+
@Test
143+
public void firstDayOfWeek_notSet() {
144+
CalendarConstraints calendarConstraints = new CalendarConstraints.Builder().build();
145+
146+
assertThat(calendarConstraints.getFirstDayOfWeek()).isEqualTo(0);
147+
}
148+
149+
@Test
150+
public void firstDayOfWeek_invalidBelowRange() {
151+
assertThrows(
152+
IllegalArgumentException.class,
153+
() -> new CalendarConstraints.Builder().setFirstDayOfWeek(-1).build());
154+
}
155+
156+
@Test
157+
public void firstDayOfWeek_invalidAboveRange() {
158+
assertThrows(
159+
IllegalArgumentException.class,
160+
() -> new CalendarConstraints.Builder().setFirstDayOfWeek(SATURDAY + 1).build());
120161
}
121162
}

lib/javatests/com/google/android/material/datepicker/MaterialDatePickerTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import static java.util.Calendar.APRIL;
2121
import static java.util.Calendar.FEBRUARY;
2222
import static java.util.Calendar.MARCH;
23+
import static java.util.Calendar.MONDAY;
24+
import static java.util.Calendar.SUNDAY;
2325
import static org.junit.Assert.assertEquals;
2426

2527
import java.time.Duration;
@@ -147,4 +149,33 @@ public void testThisMonthInUtcMilliseconds() {
147149
testThisMonthInUtcMillisecondsForLocalTime(
148150
NEW_ZEALAND_TIME_2020_01_11_09_00_00_AM, TimeZone.getTimeZone("NZ"));
149151
}
152+
153+
@Test
154+
public void testFirstDayOfWeekAsSunday() {
155+
MaterialDatePicker.Builder<Long> datePickerBuilder = MaterialDatePicker.Builder.datePicker();
156+
CalendarConstraints calendarConstraints =
157+
new CalendarConstraints.Builder().setFirstDayOfWeek(SUNDAY).build();
158+
datePickerBuilder.setCalendarConstraints(calendarConstraints);
159+
datePickerBuilder.build();
160+
assertEquals(SUNDAY, calendarConstraints.getFirstDayOfWeek());
161+
}
162+
163+
@Test
164+
public void testFirstDayOfWeekAsMonday() {
165+
MaterialDatePicker.Builder<Long> datePickerBuilder = MaterialDatePicker.Builder.datePicker();
166+
CalendarConstraints calendarConstraints =
167+
new CalendarConstraints.Builder().setFirstDayOfWeek(MONDAY).build();
168+
datePickerBuilder.setCalendarConstraints(calendarConstraints);
169+
datePickerBuilder.build();
170+
assertEquals(MONDAY, calendarConstraints.getFirstDayOfWeek());
171+
}
172+
173+
@Test
174+
public void testFirstDayOfWeekAsDefault() {
175+
MaterialDatePicker.Builder<Long> datePickerBuilder = MaterialDatePicker.Builder.datePicker();
176+
CalendarConstraints calendarConstraints = new CalendarConstraints.Builder().build();
177+
datePickerBuilder.setCalendarConstraints(calendarConstraints);
178+
datePickerBuilder.build();
179+
assertEquals(0, calendarConstraints.getFirstDayOfWeek());
180+
}
150181
}

0 commit comments

Comments
 (0)