Skip to content

Commit 47b3b08

Browse files
committed
WIP
1 parent 17c28e7 commit 47b3b08

23 files changed

+2158
-4152
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,5 @@ buck-out/
5959

6060
# CocoaPods
6161
example/ios/Pods/
62+
63+
.xcode.env

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
See this [issue](https://github.com/react-native-datetimepicker/datetimepicker/issues/313).
44

5-
### Backers
5+
### Financial backers
66

7-
Support us with a monthly donation and help us continue our activities. [Become a backer on OpenCollective](https://opencollective.com/react-native-datetimepicker) or [sponsor us on GitHub Sponsors](https://github.com/sponsors/react-native-datetimepicker).
7+
Support us with a monthly donation to help us keep the module maintained. [Become a backer on OpenCollective](https://opencollective.com/react-native-datetimepicker) or [sponsor us on GitHub Sponsors](https://github.com/sponsors/react-native-datetimepicker).
88

99
<a href="https://opencollective.com/react-native-datetimepicker/donate" target="_blank">
1010
<img src="https://opencollective.com/react-native-datetimepicker/backers.svg?width=890" width=890 />

android/src/main/java/com/reactcommunity/rndatetimepicker/Common.java

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@
1818
import androidx.fragment.app.FragmentManager;
1919

2020
import com.facebook.react.bridge.Promise;
21+
import com.facebook.react.bridge.ReadableMap;
2122

23+
import java.util.Arrays;
24+
import java.util.Calendar;
25+
import java.util.HashSet;
2226
import java.util.Locale;
27+
import java.util.TimeZone;
2328

2429
public class Common {
2530

@@ -28,6 +33,7 @@ public class Common {
2833
public static final String NEGATIVE = "negative";
2934
public static final String LABEL = "label";
3035
public static final String TEXT_COLOR = "textColor";
36+
private static final HashSet TIMEZONE_IDS = new HashSet<>(Arrays.asList(TimeZone.getAvailableIDs()));
3137

3238
public static void dismissDialog(FragmentActivity activity, String fragmentTag, Promise promise) {
3339
if (activity == null) {
@@ -63,21 +69,18 @@ public static int getDefaultDialogButtonTextColor(@NonNull Context activity) {
6369

6470
@NonNull
6571
public static DialogInterface.OnShowListener setButtonTextColor(@NonNull final Context activityContext, final AlertDialog dialog, final Bundle args, final boolean needsColorOverride) {
66-
return new DialogInterface.OnShowListener() {
67-
@Override
68-
public void onShow(DialogInterface dialogInterface) {
69-
// change text color only if custom color is set or if spinner mode is set
70-
// because spinner suffers from https://github.com/react-native-datetimepicker/datetimepicker/issues/543
71-
72-
Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
73-
Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
74-
Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
75-
76-
int textColorPrimary = getDefaultDialogButtonTextColor(activityContext);
77-
setTextColor(positiveButton, POSITIVE, args, needsColorOverride, textColorPrimary);
78-
setTextColor(negativeButton, NEGATIVE, args, needsColorOverride, textColorPrimary);
79-
setTextColor(neutralButton, NEUTRAL, args, needsColorOverride, textColorPrimary);
80-
}
72+
return dialogInterface -> {
73+
// change text color only if custom color is set or if spinner mode is set
74+
// because spinner suffers from https://github.com/react-native-datetimepicker/datetimepicker/issues/543
75+
76+
Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
77+
Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
78+
Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
79+
80+
int textColorPrimary = getDefaultDialogButtonTextColor(activityContext);
81+
setTextColor(positiveButton, POSITIVE, args, needsColorOverride, textColorPrimary);
82+
setTextColor(negativeButton, NEGATIVE, args, needsColorOverride, textColorPrimary);
83+
setTextColor(neutralButton, NEUTRAL, args, needsColorOverride, textColorPrimary);
8184
};
8285
}
8386

@@ -139,4 +142,67 @@ private static void setButtonLabel(Bundle buttonConfig, AlertDialog dialog, int
139142
}
140143
dialog.setButton(whichButton, buttonConfig.getString(LABEL), listener);
141144
}
145+
146+
public static TimeZone getTimeZone(Bundle args) {
147+
if (args != null && args.containsKey(RNConstants.ARG_TZOFFSET_MINS)) {
148+
final String[] ids = TimeZone.getAvailableIDs(args.getInt(RNConstants.ARG_TZOFFSET_MINS) * 60 * 1000);
149+
if (ids.length > 0) {
150+
return TimeZone.getTimeZone(ids[0]);
151+
}
152+
}
153+
154+
if (args != null && args.containsKey(RNConstants.ARG_TZ_NAME)) {
155+
String timeZoneName = args.getString(RNConstants.ARG_TZ_NAME);
156+
if (TIMEZONE_IDS.contains(timeZoneName)) {
157+
return TimeZone.getTimeZone(timeZoneName);
158+
}
159+
}
160+
161+
return TimeZone.getDefault();
162+
}
163+
164+
public static long clamp(final long value, final long min, final long max) {
165+
return Math.min(Math.max(value, min), max);
166+
}
167+
168+
public static long maxDateWithTimeZone(Bundle args) {
169+
if (!args.containsKey(RNConstants.ARG_MAXDATE)) {
170+
return Long.MAX_VALUE;
171+
}
172+
173+
Calendar maxDate = Calendar.getInstance(getTimeZone(args));
174+
maxDate.setTimeInMillis(args.getLong(RNConstants.ARG_MAXDATE));
175+
maxDate.set(Calendar.HOUR_OF_DAY, 23);
176+
maxDate.set(Calendar.MINUTE, 59);
177+
maxDate.set(Calendar.SECOND, 59);
178+
maxDate.set(Calendar.MILLISECOND, 999);
179+
return maxDate.getTimeInMillis();
180+
}
181+
182+
public static long minDateWithTimeZone(Bundle args) {
183+
if (!args.containsKey(RNConstants.ARG_MINDATE)) {
184+
return 0;
185+
}
186+
187+
Calendar minDate = Calendar.getInstance(getTimeZone(args));
188+
minDate.setTimeInMillis(args.getLong(RNConstants.ARG_MINDATE));
189+
minDate.set(Calendar.HOUR_OF_DAY, 0);
190+
minDate.set(Calendar.MINUTE, 0);
191+
minDate.set(Calendar.SECOND, 0);
192+
minDate.set(Calendar.MILLISECOND, 0);
193+
return minDate.getTimeInMillis();
194+
}
195+
196+
public static Bundle createFragmentArguments(ReadableMap options) {
197+
final Bundle args = new Bundle();
198+
199+
if (options.hasKey(RNConstants.ARG_VALUE) && !options.isNull(RNConstants.ARG_VALUE)) {
200+
args.putLong(RNConstants.ARG_VALUE, (long) options.getDouble(RNConstants.ARG_VALUE));
201+
}
202+
if (options.hasKey(RNConstants.ARG_TZ_NAME) && !options.isNull(RNConstants.ARG_TZ_NAME)) {
203+
args.putString(RNConstants.ARG_TZ_NAME, options.getString(RNConstants.ARG_TZ_NAME));
204+
}
205+
206+
return args;
207+
}
142208
}

android/src/main/java/com/reactcommunity/rndatetimepicker/DatePickerModule.java

Lines changed: 28 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
import com.facebook.react.module.annotations.ReactModule;
2323

2424
import static com.reactcommunity.rndatetimepicker.Common.dismissDialog;
25-
import static com.reactcommunity.rndatetimepicker.KeepDateInRangeListener.isDateAfterMaxDate;
26-
import static com.reactcommunity.rndatetimepicker.KeepDateInRangeListener.isDateBeforeMinDate;
2725

2826
import java.util.Calendar;
2927

@@ -41,8 +39,9 @@ public DatePickerModule(ReactApplicationContext reactContext) {
4139
super(reactContext);
4240
}
4341

42+
@NonNull
4443
@Override
45-
public @NonNull String getName() {
44+
public String getName() {
4645
return NAME;
4746
}
4847

@@ -60,38 +59,21 @@ public DatePickerDialogListener(final Promise promise, Bundle arguments) {
6059
@Override
6160
public void onDateSet(DatePicker view, int year, int month, int day) {
6261
if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) {
62+
final RNDate date = new RNDate(mArgs);
63+
Calendar calendar = Calendar.getInstance(Common.getTimeZone(mArgs));
64+
calendar.set(year, month, day, date.hour(), date.minute(), 0);
65+
calendar.set(Calendar.MILLISECOND, 0);
66+
6367
WritableMap result = new WritableNativeMap();
6468
result.putString("action", RNConstants.ACTION_DATE_SET);
65-
result.putInt("year", year);
66-
result.putInt("month", month);
67-
result.putInt("day", day);
68-
69-
// https://issuetracker.google.com/issues/169602180
70-
// TODO revisit day, month, year with timezoneoffset fixes
71-
if (isDateAfterMaxDate(mArgs, year, month, day)) {
72-
Calendar maxDate = Calendar.getInstance();
73-
maxDate.setTimeInMillis(mArgs.getLong(RNConstants.ARG_MAXDATE));
74-
75-
result.putInt("year", maxDate.get(Calendar.YEAR));
76-
result.putInt("month", maxDate.get(Calendar.MONTH) );
77-
result.putInt("day", maxDate.get(Calendar.DAY_OF_MONTH));
78-
}
79-
80-
if (isDateBeforeMinDate(mArgs, year, month, day)) {
81-
Calendar minDate = Calendar.getInstance();
82-
minDate.setTimeInMillis(mArgs.getLong(RNConstants.ARG_MINDATE));
83-
84-
result.putInt("year", minDate.get(Calendar.YEAR));
85-
result.putInt("month", minDate.get(Calendar.MONTH) );
86-
result.putInt("day", minDate.get(Calendar.DAY_OF_MONTH));
87-
}
69+
result.putDouble("timestamp", calendar.getTimeInMillis());
8870

8971
mPromise.resolve(result);
9072
mPromiseResolved = true;
9173
}
9274
}
9375

94-
@Override
76+
@Override
9577
public void onDismiss(DialogInterface dialog) {
9678
if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) {
9779
WritableMap result = new WritableNativeMap();
@@ -154,35 +136,32 @@ public void open(final ReadableMap options, final Promise promise) {
154136

155137
final FragmentManager fragmentManager = activity.getSupportFragmentManager();
156138

157-
UiThreadUtil.runOnUiThread(new Runnable() {
158-
@Override
159-
public void run() {
160-
RNDatePickerDialogFragment oldFragment =
161-
(RNDatePickerDialogFragment) fragmentManager.findFragmentByTag(NAME);
139+
UiThreadUtil.runOnUiThread(() -> {
140+
RNDatePickerDialogFragment oldFragment =
141+
(RNDatePickerDialogFragment) fragmentManager.findFragmentByTag(NAME);
162142

163-
if (oldFragment != null) {
164-
oldFragment.update(createFragmentArguments(options));
165-
return;
166-
}
143+
Bundle arguments = createFragmentArguments(options);
167144

168-
RNDatePickerDialogFragment fragment = new RNDatePickerDialogFragment();
145+
if (oldFragment != null) {
146+
oldFragment.update(arguments);
147+
return;
148+
}
169149

170-
fragment.setArguments(createFragmentArguments(options));
150+
RNDatePickerDialogFragment fragment = new RNDatePickerDialogFragment();
171151

172-
final DatePickerDialogListener listener = new DatePickerDialogListener(promise, createFragmentArguments(options));
173-
fragment.setOnDismissListener(listener);
174-
fragment.setOnDateSetListener(listener);
175-
fragment.setOnNeutralButtonActionListener(listener);
176-
fragment.show(fragmentManager, NAME);
177-
}
152+
fragment.setArguments(arguments);
153+
154+
final DatePickerDialogListener listener = new DatePickerDialogListener(promise, arguments);
155+
fragment.setOnDismissListener(listener);
156+
fragment.setOnDateSetListener(listener);
157+
fragment.setOnNeutralButtonActionListener(listener);
158+
fragment.show(fragmentManager, NAME);
178159
});
179160
}
180161

181162
private Bundle createFragmentArguments(ReadableMap options) {
182-
final Bundle args = new Bundle();
183-
if (options.hasKey(RNConstants.ARG_VALUE) && !options.isNull(RNConstants.ARG_VALUE)) {
184-
args.putLong(RNConstants.ARG_VALUE, (long) options.getDouble(RNConstants.ARG_VALUE));
185-
}
163+
final Bundle args = Common.createFragmentArguments(options);
164+
186165
if (options.hasKey(RNConstants.ARG_MINDATE) && !options.isNull(RNConstants.ARG_MINDATE)) {
187166
args.putLong(RNConstants.ARG_MINDATE, (long) options.getDouble(RNConstants.ARG_MINDATE));
188167
}
@@ -195,9 +174,7 @@ private Bundle createFragmentArguments(ReadableMap options) {
195174
if (options.hasKey(RNConstants.ARG_DIALOG_BUTTONS) && !options.isNull(RNConstants.ARG_DIALOG_BUTTONS)) {
196175
args.putBundle(RNConstants.ARG_DIALOG_BUTTONS, Arguments.toBundle(options.getMap(RNConstants.ARG_DIALOG_BUTTONS)));
197176
}
198-
if (options.hasKey(RNConstants.ARG_TZOFFSET_MINS) && !options.isNull(RNConstants.ARG_TZOFFSET_MINS)) {
199-
args.putLong(RNConstants.ARG_TZOFFSET_MINS, (long) options.getDouble(RNConstants.ARG_TZOFFSET_MINS));
200-
}
177+
201178
return args;
202179
}
203180
}

android/src/main/java/com/reactcommunity/rndatetimepicker/KeepDateInRangeListener.java

Lines changed: 0 additions & 65 deletions
This file was deleted.

android/src/main/java/com/reactcommunity/rndatetimepicker/RNConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public final class RNConstants {
1212
public static final String ARG_DISPLAY = "display";
1313
public static final String ARG_DIALOG_BUTTONS = "dialogButtons";
1414
public static final String ARG_TZOFFSET_MINS = "timeZoneOffsetInMinutes";
15+
public static final String ARG_TZ_NAME = "timeZoneName";
1516
public static final String ACTION_DATE_SET = "dateSetAction";
1617
public static final String ACTION_TIME_SET = "timeSetAction";
1718
public static final String ACTION_DISMISSED = "dismissedAction";

android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,14 @@ public RNDate(Bundle args) {
1111
now = Calendar.getInstance();
1212

1313
if (args != null && args.containsKey(RNConstants.ARG_VALUE)) {
14-
set(args.getLong(RNConstants.ARG_VALUE));
14+
now.setTimeInMillis((args.getLong(RNConstants.ARG_VALUE)));
1515
}
1616

17-
if (args != null && args.containsKey(RNConstants.ARG_TZOFFSET_MINS)) {
18-
now.setTimeZone(TimeZone.getTimeZone("GMT"));
19-
Long timeZoneOffsetInMinutesFallback = args.getLong(RNConstants.ARG_TZOFFSET_MINS);
20-
Integer timeZoneOffsetInMinutes = args.getInt(RNConstants.ARG_TZOFFSET_MINS, timeZoneOffsetInMinutesFallback.intValue());
21-
now.add(Calendar.MILLISECOND, timeZoneOffsetInMinutes * 60000);
17+
if (args != null && args.containsKey(RNConstants.ARG_TZ_NAME)) {
18+
now.setTimeZone(Common.getTimeZone(args));
2219
}
2320
}
2421

25-
public void set(long value) {
26-
now.setTimeInMillis(value);
27-
}
28-
2922
public int year() { return now.get(Calendar.YEAR); }
3023
public int month() { return now.get(Calendar.MONTH); }
3124
public int day() { return now.get(Calendar.DAY_OF_MONTH); }

0 commit comments

Comments
 (0)