Skip to content

Commit 4285303

Browse files
feat(DatePicker): add possibility to select mode yearAndMonth
1 parent 1dcf1c1 commit 4285303

File tree

12 files changed

+82
-18
lines changed

12 files changed

+82
-18
lines changed

README.md

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
This is a React Native Date Picker with following main features:
44

55
📱&nbsp; Supports iOS, Android and Expo<br>
6-
🕑&nbsp; 3 different modes: Time, Date, DateTime<br>
6+
🕑&nbsp; 4 different modes: Time, Date, DateTime, YearAndMonth<br>
77
🌍&nbsp; Various languages<br>
88
🎨&nbsp; Customizable<br>
99
🖼&nbsp; Modal or Inlined<br>
@@ -181,7 +181,7 @@ export default () => {
181181
| `maximumDate` | Maximum selectable date. <br/> Example: `new Date("2021-12-31")` |
182182
| `minimumDate` | Minimum selectable date. <br/> Example: `new Date("2021-01-01")` |
183183
| `minuteInterval` | The interval at which minutes can be selected. | <img src="docs/minute-interval-ios.png" alt="Date picker minute interval IOS" height="120px" /> | <img src="docs/minute-interval-android.png" alt="Date picker minute interval Android" height="120px" /> |
184-
| `mode` | The date picker mode. `"datetime"`, `"date"`, `"time"` | <img src="docs/datetime-mode-ios.png" alt="React native date time picker" height="120px" /><img src="docs/date-mode-ios.png" alt="React native datepicker" height="120px" /><img src="docs/time-mode-ios.png" alt="React native time picker" height="120px" /> | <img src="docs/datetime-mode-android.png" alt="react native date time picker android" height="120px" /><img src="docs/date-mode-android.png" alt="react native datepicker android" height="120px" /><img src="docs/time-mode-android.png" alt="react native time picker android" height="120px" /> |
184+
| `mode` | The date picker mode. `"datetime"`, `"date"`, `"time"`, `"yearAndMonth"` | <img src="docs/datetime-mode-ios.png" alt="React native date time picker" height="120px" /><img src="docs/date-mode-ios.png" alt="React native datepicker" height="120px" /><img src="docs/time-mode-ios.png" alt="React native time picker" height="120px" /> | <img src="docs/datetime-mode-android.png" alt="react native date time picker android" height="120px" /><img src="docs/date-mode-android.png" alt="react native datepicker android" height="120px" /><img src="docs/time-mode-android.png" alt="react native time picker android" height="120px" /> |
185185
| `locale` | The locale for the date picker. Changes language, date order and am/pm preferences. Value needs to be a <a title="react native datepicker locale id" href="https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html">Locale ID.</a> | <img src="docs/locale-ios.png" alt="React Native Date picker locale language ios" height="120px" /> | <img src="docs/locale-android.png" alt="React Native Date picker locale language android" height="120px" /> |
186186
| `timeZoneOffsetInMinutes` | Timezone offset in minutes (default: device's timezone) |
187187
| `is24hourSource` | Change how the 24h mode (am/pm) should be determined, by device settings or by locale. {'locale', 'device'} (android only, default: 'device') |
@@ -227,7 +227,7 @@ On iOS the 12/24h preference is determined by the `locale` prop. Set for instanc
227227

228228
### Is it possible to show only month and year?
229229

230-
This is unfortunately not possible due to the limitation in DatePickerIOS. You should be able to create your own month-year picker with for instance https://github.com/TronNatthakorn/react-native-wheel-pick.
230+
Yes! You can use the `"yearAndMonth"` mode which displays only month and year selection on both platforms.
231231

232232
### Why does the Android app crash in production?
233233

@@ -253,9 +253,9 @@ const [state, setState] = useState("idle")
253253
<ConfirmButton disabled={state === "spinning"} />
254254
```
255255

256-
## Three different modes
256+
## Different picker modes
257257

258-
Here are some more info about the three different picker modes that are available.
258+
Here are some more info about the different picker modes that are available.
259259

260260
### Date time picker
261261

@@ -320,6 +320,23 @@ Set mode property to `time` to show the time picker:
320320
/>
321321
```
322322

323+
### Month Year picker
324+
325+
The yearAndMonth mode allows you to select only month and year, which is useful for selecting birth months, credit card expiration dates, or other month/year selections. This mode uses the native `UIDatePickerModeYearAndMonth`.
326+
327+
Set mode property to `yearAndMonth` to show the month year picker:
328+
329+
```jsx
330+
<DatePicker
331+
...
332+
mode="yearAndMonth"
333+
/>
334+
```
335+
336+
**Compatibility Notes:**
337+
- **iOS**: Displays the native year and month picker (`UIDatePickerModeYearAndMonth`)
338+
- **Android**: Displays year and month wheels (without the date wheel)
339+
323340
## About
324341

325342
React Native Date Picker is a cross platform component for iOS and Android. It uses native code from respective platform to get the genuine look and feel the users expect. A strong motivation for creating this picker was the datetime mode on Android. It's quite unique for the platform and avoids two different picker popups, which normally is necessary. Instead, this datetime mode requires fewer user actions and enables a great user-experience.

android/src/main/java/com/henninghall/date_picker/DerivedData.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ public ArrayList<WheelType> getVisibleWheels() {
3939
visibleWheels.add(WheelType.DATE);
4040
break;
4141
}
42+
case yearAndMonth: {
43+
visibleWheels.add(WheelType.YEAR);
44+
visibleWheels.add(WheelType.MONTH);
45+
break;
46+
}
4247
}
4348
if((mode == Mode.time || mode == Mode.datetime) && state.derived.usesAmPm()){
4449
visibleWheels.add(WheelType.AM_PM);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package com.henninghall.date_picker.models;
22

33
public enum Mode {
4-
date, time, datetime
4+
date, time, datetime, yearAndMonth
55
}

android/src/main/java/com/henninghall/date_picker/ui/Wheels.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,24 @@ private String getDateModeString(int daysToSubtract) {
100100
return sb.toString();
101101
}
102102

103+
private String getYearAndMonthString(int daysToSubtract) {
104+
ArrayList<Wheel> wheels = getOrderedVisibleWheels();
105+
StringBuilder sb = new StringBuilder();
106+
for (int i = 0; i < 2; i++) {
107+
if (i != 0) sb.append(" ");
108+
Wheel w = wheels.get(i);
109+
sb.append(w.getValue());
110+
}
111+
return sb.toString();
112+
}
113+
103114
private String getDateString(int daysToSubtract){
104115
if(state.getMode() == Mode.date ){
105116
return getDateModeString(daysToSubtract);
106117
}
118+
if(state.getMode() == Mode.yearAndMonth ){
119+
return getYearAndMonthString(daysToSubtract);
120+
}
107121
return dayWheel.getValue();
108122
}
109123

@@ -170,6 +184,10 @@ private String getDateFormatPattern(){
170184
+ wheels.get(1).getFormatPattern() + " "
171185
+ wheels.get(2).getFormatPattern();
172186
}
187+
if(state.getMode() == Mode.yearAndMonth){
188+
return wheels.get(0).getFormatPattern() + " "
189+
+ wheels.get(1).getFormatPattern();
190+
}
173191
return dayWheel.getFormatPattern();
174192
}
175193

android/src/main/java/com/henninghall/date_picker/wheels/HourWheel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public String toDisplayValue(String value) {
4343

4444
@Override
4545
public boolean visible() {
46-
return state.getMode() != Mode.date;
46+
return state.getMode() != Mode.date && state.getMode() != Mode.yearAndMonth;
4747
}
4848

4949
@Override

android/src/main/java/com/henninghall/date_picker/wheels/MinutesWheel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public ArrayList<String> getValues() {
3232

3333
@Override
3434
public boolean visible() {
35-
return state.getMode() != Mode.date;
35+
return state.getMode() != Mode.date && state.getMode() != Mode.yearAndMonth;
3636
}
3737

3838
@Override

android/src/main/java/com/henninghall/date_picker/wheels/MonthWheel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public ArrayList<String> getValues() {
2828

2929
@Override
3030
public boolean visible() {
31-
return state.getMode() == Mode.date;
31+
return state.getMode() == Mode.date || state.getMode() == Mode.yearAndMonth;
3232
}
3333

3434
@Override

android/src/main/java/com/henninghall/date_picker/wheels/YearWheel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ private int getStartYear() {
5656

5757
@Override
5858
public boolean visible() {
59-
return state.getMode() == Mode.date;
59+
return state.getMode() == Mode.date || state.getMode() == Mode.yearAndMonth;
6060
}
6161

6262
@Override

index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export interface DatePickerProps extends ViewProps {
3434
/**
3535
* The date picker mode.
3636
*/
37-
mode?: 'date' | 'time' | 'datetime'
37+
mode?: 'date' | 'time' | 'datetime' | 'yearAndMonth'
3838

3939
/**
4040
* Date change handler.

ios/RNDatePicker.mm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
135135
if(newViewProps.mode == RNDatePickerMode::Time) [_picker setDatePickerMode:UIDatePickerModeTime];
136136
if(newViewProps.mode == RNDatePickerMode::Date) [_picker setDatePickerMode:UIDatePickerModeDate];
137137
if(newViewProps.mode == RNDatePickerMode::Datetime) [_picker setDatePickerMode:UIDatePickerModeDateAndTime];
138+
if(newViewProps.mode == RNDatePickerMode::YearAndMonth) {
139+
if (@available(iOS 17.4, *)) {
140+
[_picker setDatePickerMode:UIDatePickerModeYearAndMonth];
141+
} else {
142+
[_picker setDatePickerMode:(UIDatePickerMode)4269]; // magic number from iOS team
143+
}
144+
}
138145
// We need to set minuteInterval after setting datePickerMode, otherwise minuteInterval is invalid in time mode.
139146
_picker.minuteInterval = _reactMinuteInterval;
140147
}

0 commit comments

Comments
 (0)