diff --git a/README.md b/README.md
index f030f165..2812c845 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,7 @@ React Native date & time picker component for iOS, Android and Windows.
- [`value` (`required`)](#value-required)
- [`maximumDate` (`optional`)](#maximumdate-optional)
- [`minimumDate` (`optional`)](#minimumdate-optional)
- - [`timeZoneOffsetInMinutes` (`optional`, `iOS only`)](#timezoneoffsetinminutes-optional-ios-only)
+ - [`timeZoneOffsetInMinutes` (`optional`, `iOS or Android only`)](#timezoneoffsetinminutes-optional-ios-only)
- [`timeZoneOffsetInSeconds` (`optional`, `Windows only`)](#timezoneoffsetinsecond-optional-windows-only)
- [`dayOfWeekFormat` (`optional`, `Windows only`)](#dayOfWeekFormat-optional-windows-only)
- [`dateFormat` (`optional`, `Windows only`)](#dateFormat-optional-windows-only)
@@ -257,7 +257,7 @@ Defines the minimum date that can be selected. Note that on Android, this only w
```
-#### `timeZoneOffsetInMinutes` (`optional`, `iOS only`)
+#### `timeZoneOffsetInMinutes` (`optional`, `iOS and Android only`)
Allows changing of the timeZone of the date picker. By default it uses the device's time zone.
diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNConstants.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNConstants.java
index ee090fcc..5101bbef 100644
--- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNConstants.java
+++ b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNConstants.java
@@ -9,6 +9,7 @@ public final class RNConstants {
public static final String ARG_IS24HOUR = "is24Hour";
public static final String ARG_DISPLAY = "display";
public static final String ARG_NEUTRAL_BUTTON_LABEL = "neutralButtonLabel";
+ public static final String ARG_TZOFFSET_MIN = "timeZoneOffsetInMinutes";
public static final String ACTION_DATE_SET = "dateSetAction";
public static final String ACTION_TIME_SET = "timeSetAction";
public static final String ACTION_DISMISSED = "dismissedAction";
diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java
index a53a4e60..5ba52f3e 100644
--- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java
+++ b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java
@@ -1,6 +1,7 @@
package com.reactcommunity.rndatetimepicker;
import java.util.Calendar;
+import java.util.TimeZone;
import android.os.Bundle;
public class RNDate {
@@ -8,6 +9,11 @@ public class RNDate {
public RNDate(Bundle args) {
now = Calendar.getInstance();
+ if (args != null && args.containsKey(RNConstants.ARG_TZOFFSET_MIN)) {
+ now.setTimeZone(TimeZone.getTimeZone("GMT"));
+ Integer timeZoneOffsetInMinutes = args.getInt(RNConstants.ARG_TZOFFSET_MIN);
+ now.add(Calendar.MILLISECOND, timeZoneOffsetInMinutes * 60000);
+ }
if (args != null && args.containsKey(RNConstants.ARG_VALUE)) {
set(args.getLong(RNConstants.ARG_VALUE));
diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogModule.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogModule.java
index 05abbfc3..b8b5c860 100644
--- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogModule.java
+++ b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogModule.java
@@ -148,6 +148,9 @@ private Bundle createFragmentArguments(ReadableMap options) {
if (options.hasKey(RNConstants.ARG_INTERVAL) && !options.isNull(RNConstants.ARG_INTERVAL)) {
args.putInt(RNConstants.ARG_INTERVAL, options.getInt(RNConstants.ARG_INTERVAL));
}
+ if (options.hasKey(RNConstants.ARG_TZOFFSET_MIN) && !options.isNull(RNConstants.ARG_TZOFFSET_MIN)) {
+ args.putInt(RNConstants.ARG_TZOFFSET_MIN, options.getInt(RNConstants.ARG_TZOFFSET_MIN));
+ }
return args;
}
}
diff --git a/example/App.js b/example/App.js
index 07374a55..3908256c 100644
--- a/example/App.js
+++ b/example/App.js
@@ -60,6 +60,7 @@ const MINUTE_INTERVALS = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30];
export const App = () => {
const [date, setDate] = useState(new Date(1598051730000));
+ const [tzOffsetInMinutes, setTzOffsetInMinutes] = useState(0);
const [mode, setMode] = useState(MODE_VALUES[0]);
const [show, setShow] = useState(false);
const [color, setColor] = useState();
@@ -223,10 +224,20 @@ export const App = () => {
title="hide picker"
/>
+
+
{show && (
{
}
});
+ async function userOpensPickerTz({mode, display, interval}) {
+ await element(by.text(mode)).tap();
+ await element(by.text(display)).tap();
+ if (interval) {
+ await element(by.text(String(interval))).tap();
+ }
+ await element(by.id('setTz')).tap();
+ }
+
+ it('setTz should change time text when time changes 60 minutes', async () => {
+ await userOpensPickerTz({mode: 'time', display: 'default'});
+ const timeText = getTimeText();
+
+ if (isIOS()) {
+ const testElement = getDateTimePickerIOS();
+ await testElement.setColumnToValue(0, '2');
+ await testElement.setColumnToValue(1, '44');
+ await testElement.setColumnToValue(2, 'PM');
+
+ await expect(timeText).toHaveText('13:44');
+ } else {
+ await userChangesMinuteValue();
+ await userTapsOkButtonAndroid();
+
+ await expect(timeText).toHaveText('22:30');
+ }
+ });
+
it(':android: given we specify neutralButtonLabel, tapping the corresponding button sets date to the beginning of the unix time epoch', async () => {
await elementById('neutralButtonLabelTextInput').typeText('clear');
await userOpensPicker({mode: 'time', display: 'default'});
diff --git a/src/constants.js b/src/constants.js
index 8ae90536..6a921d3c 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -10,6 +10,7 @@ export const DISPLAY_DEFAULT = 'default';
export const DISPLAY_SPINNER = 'spinner';
export const DISPLAY_CLOCK = 'clock';
export const DISPLAY_CALENDAR = 'calendar';
+export const MIN_MS = 60000;
// TODO vonovak potentially replace the above string consts with this object
export const ANDROID_DISPLAY = Object.freeze({
diff --git a/src/datetimepicker.android.js b/src/datetimepicker.android.js
index 31ec934d..2b52f2de 100644
--- a/src/datetimepicker.android.js
+++ b/src/datetimepicker.android.js
@@ -12,6 +12,7 @@ import {
NEUTRAL_BUTTON_ACTION,
ANDROID_DISPLAY,
ANDROID_MODE,
+ MIN_MS,
} from './constants';
import pickers from './picker';
import invariant from 'invariant';
@@ -38,6 +39,7 @@ function getPicker({
maximumDate,
neutralButtonLabel,
minuteInterval,
+ timeZoneOffsetInMinutes,
}) {
switch (mode) {
case MODE_TIME:
@@ -47,6 +49,7 @@ function getPicker({
minuteInterval,
is24Hour,
neutralButtonLabel,
+ timeZoneOffsetInMinutes,
});
case MODE_DATE:
default:
@@ -72,6 +75,7 @@ export default function RNDateTimePicker(props: AndroidNativeProps) {
maximumDate,
neutralButtonLabel,
minuteInterval,
+ timeZoneOffsetInMinutes,
} = props;
const valueTimestamp = value.getTime();
@@ -92,11 +96,12 @@ export default function RNDateTimePicker(props: AndroidNativeProps) {
maximumDate,
neutralButtonLabel,
minuteInterval,
+ timeZoneOffsetInMinutes,
});
picker.then(
function resolve({action, day, month, year, minute, hour}) {
- const date = new Date(valueTimestamp);
+ let date = new Date(valueTimestamp);
const event: AndroidEvent = {
type: 'set',
nativeEvent: {},
@@ -109,7 +114,14 @@ export default function RNDateTimePicker(props: AndroidNativeProps) {
break;
case TIME_SET_ACTION:
- event.nativeEvent.timestamp = date.setHours(hour, minute);
+ date.setHours(hour, minute);
+ if (timeZoneOffsetInMinutes !== undefined) {
+ const offset =
+ date.getTimezoneOffset() * MIN_MS +
+ timeZoneOffsetInMinutes * MIN_MS;
+ date = new Date(date.getTime() - offset);
+ }
+ event.nativeEvent.timestamp = date;
onChange(event, date);
break;
diff --git a/src/types.js b/src/types.js
index 3d846342..752efece 100644
--- a/src/types.js
+++ b/src/types.js
@@ -136,6 +136,14 @@ export type AndroidNativeProps = $ReadOnly<{|
*/
display: Display,
+ /**
+ * Timezone offset in minutes.
+ *
+ * By default, the date picker will use the device's timezone. With this
+ * parameter, it is possible to force a certain timezone offset. For
+ * instance, to show times in Pacific Standard Time, pass -7 * 60.
+ */
+ timeZoneOffsetInMinutes?: ?number,
/**
* The interval at which minutes can be selected.
*/