Skip to content

Commit a0afd05

Browse files
committed
feat: add timeZoneName props
1 parent f265c43 commit a0afd05

28 files changed

+2236
-4220
lines changed

.gitignore

+2
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

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

+81-15
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,15 @@
1818
import androidx.fragment.app.FragmentManager;
1919

2020
import com.facebook.react.bridge.Promise;
21+
import com.facebook.react.bridge.ReadableMap;
22+
import com.facebook.react.util.RNLog;
2123

24+
import java.util.Arrays;
25+
import java.util.Calendar;
26+
import java.util.HashSet;
2227
import java.util.Locale;
28+
import java.util.SimpleTimeZone;
29+
import java.util.TimeZone;
2330

2431
public class Common {
2532

@@ -28,6 +35,7 @@ public class Common {
2835
public static final String NEGATIVE = "negative";
2936
public static final String LABEL = "label";
3037
public static final String TEXT_COLOR = "textColor";
38+
private static final HashSet TIMEZONE_IDS = new HashSet<>(Arrays.asList(TimeZone.getAvailableIDs()));
3139

3240
public static void dismissDialog(FragmentActivity activity, String fragmentTag, Promise promise) {
3341
if (activity == null) {
@@ -63,21 +71,18 @@ public static int getDefaultDialogButtonTextColor(@NonNull Context activity) {
6371

6472
@NonNull
6573
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-
}
74+
return dialogInterface -> {
75+
// change text color only if custom color is set or if spinner mode is set
76+
// because spinner suffers from https://github.com/react-native-datetimepicker/datetimepicker/issues/543
77+
78+
Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
79+
Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
80+
Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
81+
82+
int textColorPrimary = getDefaultDialogButtonTextColor(activityContext);
83+
setTextColor(positiveButton, POSITIVE, args, needsColorOverride, textColorPrimary);
84+
setTextColor(negativeButton, NEGATIVE, args, needsColorOverride, textColorPrimary);
85+
setTextColor(neutralButton, NEUTRAL, args, needsColorOverride, textColorPrimary);
8186
};
8287
}
8388

@@ -139,4 +144,65 @@ private static void setButtonLabel(Bundle buttonConfig, AlertDialog dialog, int
139144
}
140145
dialog.setButton(whichButton, buttonConfig.getString(LABEL), listener);
141146
}
147+
148+
public static TimeZone getTimeZone(Bundle args) {
149+
if (args != null && args.containsKey(RNConstants.ARG_TZOFFSET_MINS)) {
150+
return new SimpleTimeZone(args.getInt(RNConstants.ARG_TZOFFSET_MINS) * 60 * 1000, "GMT");
151+
}
152+
153+
if (args != null && args.containsKey(RNConstants.ARG_TZ_NAME)) {
154+
String timeZoneName = args.getString(RNConstants.ARG_TZ_NAME);
155+
if (TIMEZONE_IDS.contains(timeZoneName)) {
156+
return TimeZone.getTimeZone(timeZoneName);
157+
}
158+
RNLog.w(null, "'" + timeZoneName + "' does not exist in TimeZone.getAvailableIDs() fallback to TimeZone.getDefault()=" + TimeZone.getDefault().getID());
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

+28-50
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,31 +59,15 @@ 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());
70+
result.putDouble("utcOffset", calendar.getTimeZone().getRawOffset() / 1000 / 60);
8871

8972
mPromise.resolve(result);
9073
mPromiseResolved = true;
@@ -154,35 +137,32 @@ public void open(final ReadableMap options, final Promise promise) {
154137

155138
final FragmentManager fragmentManager = activity.getSupportFragmentManager();
156139

157-
UiThreadUtil.runOnUiThread(new Runnable() {
158-
@Override
159-
public void run() {
160-
RNDatePickerDialogFragment oldFragment =
161-
(RNDatePickerDialogFragment) fragmentManager.findFragmentByTag(NAME);
140+
UiThreadUtil.runOnUiThread(() -> {
141+
RNDatePickerDialogFragment oldFragment =
142+
(RNDatePickerDialogFragment) fragmentManager.findFragmentByTag(NAME);
143+
144+
Bundle arguments = createFragmentArguments(options);
162145

163-
if (oldFragment != null) {
164-
oldFragment.update(createFragmentArguments(options));
165-
return;
166-
}
146+
if (oldFragment != null) {
147+
oldFragment.update(arguments);
148+
return;
149+
}
167150

168-
RNDatePickerDialogFragment fragment = new RNDatePickerDialogFragment();
151+
RNDatePickerDialogFragment fragment = new RNDatePickerDialogFragment();
169152

170-
fragment.setArguments(createFragmentArguments(options));
153+
fragment.setArguments(arguments);
171154

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-
}
155+
final DatePickerDialogListener listener = new DatePickerDialogListener(promise, arguments);
156+
fragment.setOnDismissListener(listener);
157+
fragment.setOnDateSetListener(listener);
158+
fragment.setOnNeutralButtonActionListener(listener);
159+
fragment.show(fragmentManager, NAME);
178160
});
179161
}
180162

181163
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-
}
164+
final Bundle args = Common.createFragmentArguments(options);
165+
186166
if (options.hasKey(RNConstants.ARG_MINDATE) && !options.isNull(RNConstants.ARG_MINDATE)) {
187167
args.putLong(RNConstants.ARG_MINDATE, (long) options.getDouble(RNConstants.ARG_MINDATE));
188168
}
@@ -195,9 +175,7 @@ private Bundle createFragmentArguments(ReadableMap options) {
195175
if (options.hasKey(RNConstants.ARG_DIALOG_BUTTONS) && !options.isNull(RNConstants.ARG_DIALOG_BUTTONS)) {
196176
args.putBundle(RNConstants.ARG_DIALOG_BUTTONS, Arguments.toBundle(options.getMap(RNConstants.ARG_DIALOG_BUTTONS)));
197177
}
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-
}
178+
201179
return args;
202180
}
203181
}

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

-65
This file was deleted.

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

+1
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

+2-10
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,11 @@ 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);
22-
}
23-
}
2417

25-
public void set(long value) {
26-
now.setTimeInMillis(value);
18+
now.setTimeZone(Common.getTimeZone(args));
2719
}
2820

2921
public int year() { return now.get(Calendar.YEAR); }

0 commit comments

Comments
 (0)