Skip to content

[Android] Fix issue with minimumDate/maximumDate when using timeZoneOffsetInMinutes #519

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Dec 19, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

@SuppressLint("ValidFragment")
public class RNDatePickerDialogFragment extends DialogFragment {
Expand Down Expand Up @@ -125,6 +126,14 @@ static DatePickerDialog createDialog(

final DatePicker datePicker = dialog.getDatePicker();

Integer timeZoneOffsetInMilliseconds = null;
if (args != null && args.containsKey(RNConstants.ARG_TZOFFSET_MINS)) {
c.setTimeZone(TimeZone.getTimeZone("GMT"));
long timeZoneOffsetInMinutesFallback = args.getLong(RNConstants.ARG_TZOFFSET_MINS);
int timeZoneOffsetInMinutes = args.getInt(RNConstants.ARG_TZOFFSET_MINS, (int) timeZoneOffsetInMinutesFallback);
timeZoneOffsetInMilliseconds = timeZoneOffsetInMinutes * 60000;
}

if (args != null && args.containsKey(RNConstants.ARG_MINDATE)) {
// Set minDate to the beginning of the day. We need this because of clowniness in datepicker
// that causes it to throw an exception if minDate is greater than the internal timestamp
Expand All @@ -134,7 +143,13 @@ static DatePickerDialog createDialog(
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
datePicker.setMinDate(c.getTimeInMillis());

if (timeZoneOffsetInMilliseconds != null) {
int offset = TimeZone.getDefault().getOffset(c.getTimeInMillis()) - timeZoneOffsetInMilliseconds;
datePicker.setMinDate(c.getTimeInMillis() - offset);
} else {
datePicker.setMinDate(c.getTimeInMillis());
}
} else {
// This is to work around a bug in DatePickerDialog where it doesn't display a title showing
// the date under certain conditions.
Expand All @@ -147,7 +162,13 @@ static DatePickerDialog createDialog(
c.set(Calendar.MINUTE, 59);
c.set(Calendar.SECOND, 59);
c.set(Calendar.MILLISECOND, 999);
datePicker.setMaxDate(c.getTimeInMillis());

if (timeZoneOffsetInMilliseconds != null) {
int offset = TimeZone.getDefault().getOffset(c.getTimeInMillis()) - timeZoneOffsetInMilliseconds;
datePicker.setMaxDate(c.getTimeInMillis() - offset);
} else {
datePicker.setMaxDate(c.getTimeInMillis());
}
}

return dialog;
Expand Down
20 changes: 20 additions & 0 deletions example/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export const App = () => {
const [interval, setMinInterval] = useState(1);
const [neutralButtonLabel, setNeutralButtonLabel] = useState(undefined);
const [disabled, setDisabled] = useState(false);
const [minimumDate, setMinimumDate] = useState();
const [maximumDate, setMaximumDate] = useState();

// Windows-specific
const [time, setTime] = useState(undefined);
Expand Down Expand Up @@ -108,6 +110,12 @@ export const App = () => {
backgroundColor: isDarkMode ? Colors.dark : Colors.lighter,
};

const toggleMinMaxDate = () => {
const today = moment.utc().startOf('day');
setMaximumDate(maximumDate ? undefined : today.toDate());
setMinimumDate(minimumDate ? undefined : today.subtract(1, 'day').toDate());
};

if (Platform.OS !== 'windows') {
return (
<SafeAreaView style={[backgroundStyle, {flex: 1}]}>
Expand Down Expand Up @@ -252,11 +260,23 @@ export const App = () => {
title="setTzOffsetInMinutes to 60"
/>
</View>
<View style={styles.button}>
<Button
testID="setMinMax"
onPress={() => {
toggleMinMaxDate();
setShow(true);
}}
title="toggleMinMaxDate"
/>
</View>
{show && (
<DateTimePicker
testID="dateTimePicker"
timeZoneOffsetInMinutes={tzOffsetInMinutes}
minuteInterval={interval}
maximumDate={maximumDate}
minimumDate={minimumDate}
value={date}
mode={mode}
is24Hour
Expand Down