Skip to content
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

fix(android): min/max dates not always correct when timezoneOffsetInMinutes is set #635

Merged
merged 38 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
58180ea
datepickerandroid
henninghall Apr 10, 2023
842338c
add hour fix
henninghall Apr 10, 2023
d01af89
maestro timezone test
henninghall Apr 10, 2023
f102d8a
Merge branch 'master' into fix/timezone-offset
henninghall Apr 10, 2023
78c002c
adding tests, changing offset calculation
henninghall Apr 10, 2023
db9a3ba
swipe wheel 4
henninghall Apr 10, 2023
1c5fb54
settings timezone fix
henninghall Apr 12, 2023
fcd078a
formatting
henninghall Apr 12, 2023
aa3094e
settings search navigation
henninghall Apr 12, 2023
bf33e36
try api level 33
henninghall Apr 12, 2023
ec1428d
tap utc
henninghall Apr 12, 2023
cc69401
set gmt-7
henninghall Apr 12, 2023
a5b444a
no native
henninghall Apr 12, 2023
02a5aff
gmt env
henninghall Apr 13, 2023
2bd4bb0
npm ignore maestro
henninghall Apr 13, 2023
97837bb
scroll
henninghall Apr 13, 2023
b02a241
cleanup
henninghall Apr 13, 2023
a7713df
gmt+1
henninghall Apr 13, 2023
0f5b485
maestro local
henninghall Apr 15, 2023
60ff1dc
bump
henninghall Apr 15, 2023
92b4af0
steps
henninghall Apr 15, 2023
caa68f2
all steps
henninghall Apr 15, 2023
676fb1f
working dir
henninghall Apr 15, 2023
104a723
java
henninghall Apr 15, 2023
48c3406
own avd
henninghall Apr 15, 2023
8d28bf4
maestro PATH
henninghall Apr 15, 2023
a3af6aa
path 2
henninghall Apr 15, 2023
01a2640
path
henninghall Apr 15, 2023
8bcef93
install maestro
henninghall Apr 15, 2023
ac3aad0
root
henninghall Apr 15, 2023
00bf43f
record video
henninghall Apr 16, 2023
8ed9a94
always
henninghall Apr 16, 2023
5b40d64
summertime
henninghall Apr 17, 2023
ac12848
rename
henninghall Apr 17, 2023
4f1807d
Merge remote-tracking branch 'refs/remotes/origin/master'
henninghall Apr 17, 2023
0bc2b6f
timezone -> region
henninghall Apr 17, 2023
2b91660
remove resetToMidnight
henninghall Apr 17, 2023
fd3628c
correct assert
henninghall Apr 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions .maestro/timezone-offset-in-minutes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ appId: com.rn069
- runFlow:
file: utils/set-timezone.yml
env:
TIMEZONE: Sweden
REGION: Sweden
GMT: GMT+01:00
STATE: ''

- runFlow: utils/launch.yml

Expand Down Expand Up @@ -53,8 +54,9 @@ appId: com.rn069
- runFlow:
file: utils/set-timezone.yml
env:
TIMEZONE: Sweden
REGION: Sweden
GMT: GMT+02:00
STATE: ''

- runFlow: utils/launch.yml

Expand Down Expand Up @@ -118,3 +120,24 @@ appId: com.rn069
- assertVisible: 'Thu Jun 1101 AM '

- runFlow: utils/reset.yml

# test: timezoneOffsetInMinutes combined with maximumDate/minimumDate in another timezone than current device.
# Bug was reported here: https://github.com/henninghall/react-native-date-picker/issues/613
- runFlow:
file: utils/set-timezone.yml
env:
REGION: 'United states'
STATE: Phoenix
GMT: GMT-07:00
- runFlow: utils/launch.yml
- runFlow:
file: utils/change-prop.yml
env:
PROP: timeZoneOffsetInMinutes
VALUE: 180
- repeat:
times: 5
commands:
- runFlow: utils/swipe-wheel-1.yml
- runFlow: utils/swipe-wheel-4.yml
- assertVisible: 'Thu Jan 61000 AM '
12 changes: 11 additions & 1 deletion .maestro/utils/select-region.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
appId: com.android.settings
---
- tapOn: Region
- inputText: ${TIMEZONE}
- inputText: ${REGION}
- tapOn:
text: ${REGION}
index: 1

- runFlow:
when:
true: ${REGION == 'United states'}
file: tap.yml
env:
TEXT: ${STATE}
8 changes: 0 additions & 8 deletions .maestro/utils/set-timezone-us.yml

This file was deleted.

3 changes: 2 additions & 1 deletion .maestro/utils/set-timezone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ appId: com.android.settings
visible: Region
file: select-region.yml
env:
TIMEZONE: ${TIMEZONE}
REGION: ${REGION}
STATE: ${STATE}
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
package com.henninghall.date_picker;


import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.SimpleViewManager;
Expand All @@ -29,7 +21,7 @@
import com.henninghall.date_picker.props.MinuteIntervalProp;
import com.henninghall.date_picker.props.ModeProp;
import com.henninghall.date_picker.props.TextColorProp;
import com.henninghall.date_picker.props.UtcProp;
import com.henninghall.date_picker.props.TimezoneOffsetInMinutesProp;


import java.lang.reflect.Method;
Expand All @@ -54,7 +46,7 @@ public PickerView createViewInstance(ThemedReactContext context) {
}

@ReactPropGroup(names = { DateProp.name, ModeProp.name, LocaleProp.name, MaximumDateProp.name,
MinimumDateProp.name, FadeToColorProp.name, TextColorProp.name, UtcProp.name, MinuteIntervalProp.name,
MinimumDateProp.name, FadeToColorProp.name, TextColorProp.name, TimezoneOffsetInMinutesProp.name, MinuteIntervalProp.name,
VariantProp.name, DividerHeightProp.name, Is24hourSourceProp.name
})
public void setProps(PickerView view, int index, Dynamic value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import com.henninghall.date_picker.props.MaximumDateProp;
import com.henninghall.date_picker.props.MinimumDateProp;
import com.henninghall.date_picker.props.MinuteIntervalProp;
import com.henninghall.date_picker.props.UtcProp;
import com.henninghall.date_picker.props.TimezoneOffsetInMinutesProp;
import com.henninghall.date_picker.props.VariantProp;
import com.henninghall.date_picker.props.DateProp;
import com.henninghall.date_picker.props.FadeToColorProp;
Expand Down Expand Up @@ -77,7 +77,7 @@ public void update() {

if (didUpdate(DateProp.name, HeightProp.name, LocaleProp.name,
MaximumDateProp.name, MinimumDateProp.name, MinuteIntervalProp.name, ModeProp.name,
UtcProp.name, VariantProp.name
TimezoneOffsetInMinutesProp.name, VariantProp.name
)) {
uiManager.updateDisplayValues();
}
Expand Down
25 changes: 16 additions & 9 deletions android/src/main/java/com/henninghall/date_picker/State.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import com.henninghall.date_picker.props.ModeProp;
import com.henninghall.date_picker.props.Prop;
import com.henninghall.date_picker.props.TextColorProp;
import com.henninghall.date_picker.props.UtcProp;
import com.henninghall.date_picker.props.TimezoneOffsetInMinutesProp;

import net.time4j.tz.Timezone;

import java.util.Calendar;
import java.util.HashMap;
Expand All @@ -35,7 +37,7 @@ public class State {
private final MinuteIntervalProp minuteIntervalProp = new MinuteIntervalProp();
private final MinimumDateProp minimumDateProp = new MinimumDateProp();
private final MaximumDateProp maximumDateProp = new MaximumDateProp();
private final UtcProp utcProp = new UtcProp();
private final TimezoneOffsetInMinutesProp timezoneOffsetInMinutesProp = new TimezoneOffsetInMinutesProp();
private final HeightProp heightProp = new HeightProp();
private final VariantProp variantProp = new VariantProp();
private final DividerHeightProp dividerHeightProp = new DividerHeightProp();
Expand All @@ -50,7 +52,7 @@ public class State {
put(MinuteIntervalProp.name, minuteIntervalProp);
put(MinimumDateProp.name, minimumDateProp);
put(MaximumDateProp.name, maximumDateProp);
put(UtcProp.name, utcProp);
put(TimezoneOffsetInMinutesProp.name, timezoneOffsetInMinutesProp);
put(HeightProp.name, heightProp);
put(VariantProp.name, variantProp);
put(DividerHeightProp.name, dividerHeightProp);
Expand Down Expand Up @@ -91,18 +93,23 @@ public Locale getLocale() {
}

public Calendar getMinimumDate() {
DateBoundary db = new DateBoundary(getTimeZone(), (String) minimumDateProp.getValue());
return db.get();
return Utils.isoToCalendar(minimumDateProp.getValue(), getTimeZone());
}

public Calendar getMaximumDate() {
DateBoundary db = new DateBoundary(getTimeZone(), (String) maximumDateProp.getValue());
return db.get();
return Utils.isoToCalendar(maximumDateProp.getValue(), getTimeZone());
}

public TimeZone getTimeZone() {
boolean utc = (boolean) utcProp.getValue();
return utc ? TimeZone.getTimeZone("UTC") : TimeZone.getDefault();
Integer offset = timezoneOffsetInMinutesProp.getValue();
if(offset == null) return TimeZone.getDefault();
int totalOffsetMinutes = Math.abs(offset);
char offsetDirection = offset < 0 ? '-' : '+';
int offsetHours = (int) Math.floor(totalOffsetMinutes / 60f);
int offsetMinutes = totalOffsetMinutes - offsetHours * 60;
String timeZoneId = "GMT" + offsetDirection + offsetHours + ":" + Utils.toPaddedMinutes(offsetMinutes);
TimeZone zone = TimeZone.getTimeZone(timeZoneId);
return zone;
}

public String getIsoDate() {
Expand Down
6 changes: 6 additions & 0 deletions android/src/main/java/com/henninghall/date_picker/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import net.time4j.PrettyTime;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
Expand Down Expand Up @@ -110,4 +111,9 @@ public static String getLocalisedStringFromResources(Locale locale, String tagNa
public static int toDp(int pixels){
return (int) (pixels * DatePickerPackage.context.getResources().getDisplayMetrics().density);
}

public static String toPaddedMinutes(int minutes){
DecimalFormat df = new DecimalFormat("00");
return df.format(minutes);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.henninghall.date_picker.props;

import com.facebook.react.bridge.Dynamic;

public class TimezoneOffsetInMinutesProp extends Prop<Integer> {
public static final String name = "timezoneOffsetInMinutes";

@Override
Integer toValue(Dynamic value) {
if(value.isNull()) return null;
return value.asInt();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ private Calendar getStartCal(){
Calendar min = state.getMinimumDate();
if (min != null) {
cal = (Calendar) min.clone();
resetToMidnight(cal);
} else if (max != null) {
cal = (Calendar) max.clone();
resetToMidnight(cal);
cal.add(Calendar.DATE, -cal.getActualMaximum(Calendar.DAY_OF_YEAR) / 2);
} else {
cal = (Calendar) getInitialDate().clone();
Expand All @@ -68,10 +66,8 @@ private Calendar getEndCal(){
Calendar min = state.getMinimumDate();
if (max != null) {
cal = (Calendar) max.clone();
resetToMidnight(cal);
} else if (min != null) {
cal = (Calendar) min.clone();
resetToMidnight(cal);
cal.add(Calendar.DATE, cal.getActualMaximum(Calendar.DAY_OF_YEAR) / 2);
} else {
cal = (Calendar) getInitialDate().clone();
Expand Down
16 changes: 8 additions & 8 deletions src/DatePickerAndroid.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,15 @@ class DatePickerAndroid extends React.PureComponent {
date: this._date(),
minimumDate: this._minimumDate(),
maximumDate: this._maximumDate(),
utc: this.props.timeZoneOffsetInMinutes !== undefined,
timezoneOffsetInMinutes: this._getTimezoneOffsetInMinutes(),
style: this._getStyle(),
})

_getTimezoneOffsetInMinutes = () => {
if (this.props.timeZoneOffsetInMinutes == undefined) return undefined
return this.props.timeZoneOffsetInMinutes
}

_getStyle = () => {
const width = this.props.mode === 'time' ? timeModeWidth : defaultWidth
return [{ width, height }, this.props.style]
Expand All @@ -74,16 +79,11 @@ class DatePickerAndroid extends React.PureComponent {
_date = () => this._toIsoWithTimeZoneOffset(this.props.date)

_fromIsoWithTimeZoneOffset = (timestamp) => {
const date = new Date(timestamp)
if (this.props.timeZoneOffsetInMinutes === undefined) return date
return addMinutes(date, -this.props.timeZoneOffsetInMinutes)
return new Date(timestamp)
}

_toIsoWithTimeZoneOffset = (date) => {
if (this.props.timeZoneOffsetInMinutes === undefined)
return date.toISOString()

return addMinutes(date, this.props.timeZoneOffsetInMinutes).toISOString()
return date.toISOString()
}

_onConfirm = (isoDate) => {
Expand Down