Skip to content

Commit 40e74b2

Browse files
authored
fix(android): min/max dates not always correct when timezoneOffsetInMinutes is set (#635)
1 parent 3799a37 commit 40e74b2

File tree

12 files changed

+85
-57
lines changed

12 files changed

+85
-57
lines changed

.maestro/timezone-offset-in-minutes.yml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ appId: com.rn069
33
- runFlow:
44
file: utils/set-timezone.yml
55
env:
6-
TIMEZONE: Sweden
6+
REGION: Sweden
77
GMT: GMT+01:00
8+
STATE: ''
89

910
- runFlow: utils/launch.yml
1011

@@ -53,8 +54,9 @@ appId: com.rn069
5354
- runFlow:
5455
file: utils/set-timezone.yml
5556
env:
56-
TIMEZONE: Sweden
57+
REGION: Sweden
5758
GMT: GMT+02:00
59+
STATE: ''
5860

5961
- runFlow: utils/launch.yml
6062

@@ -118,3 +120,24 @@ appId: com.rn069
118120
- assertVisible: 'Thu Jun 1101 AM '
119121

120122
- runFlow: utils/reset.yml
123+
124+
# test: timezoneOffsetInMinutes combined with maximumDate/minimumDate in another timezone than current device.
125+
# Bug was reported here: https://github.com/henninghall/react-native-date-picker/issues/613
126+
- runFlow:
127+
file: utils/set-timezone.yml
128+
env:
129+
REGION: 'United states'
130+
STATE: Phoenix
131+
GMT: GMT-07:00
132+
- runFlow: utils/launch.yml
133+
- runFlow:
134+
file: utils/change-prop.yml
135+
env:
136+
PROP: timeZoneOffsetInMinutes
137+
VALUE: 180
138+
- repeat:
139+
times: 5
140+
commands:
141+
- runFlow: utils/swipe-wheel-1.yml
142+
- runFlow: utils/swipe-wheel-4.yml
143+
- assertVisible: 'Thu Jan 61000 AM '

.maestro/utils/select-region.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
appId: com.android.settings
22
---
33
- tapOn: Region
4-
- inputText: ${TIMEZONE}
4+
- inputText: ${REGION}
5+
- tapOn:
6+
text: ${REGION}
7+
index: 1
8+
9+
- runFlow:
10+
when:
11+
true: ${REGION == 'United states'}
12+
file: tap.yml
13+
env:
14+
TEXT: ${STATE}

.maestro/utils/set-timezone-us.yml

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

.maestro/utils/set-timezone.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ appId: com.android.settings
2929
visible: Region
3030
file: select-region.yml
3131
env:
32-
TIMEZONE: ${TIMEZONE}
32+
REGION: ${REGION}
33+
STATE: ${STATE}

android/src/main/java/com/henninghall/date_picker/DatePickerManager.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
11
package com.henninghall.date_picker;
22

33

4-
import android.app.AlertDialog;
5-
import android.app.Dialog;
6-
import android.app.DialogFragment;
7-
import android.content.DialogInterface;
8-
import android.os.Bundle;
9-
import android.view.View;
104
import android.widget.LinearLayout;
115
import android.widget.RelativeLayout;
126

137
import com.facebook.react.bridge.Dynamic;
14-
import com.facebook.react.bridge.ReactApplicationContext;
15-
import com.facebook.react.bridge.ReactMethod;
168
import com.facebook.react.bridge.ReadableArray;
179
import com.facebook.react.common.MapBuilder;
1810
import com.facebook.react.uimanager.SimpleViewManager;
@@ -29,7 +21,7 @@
2921
import com.henninghall.date_picker.props.MinuteIntervalProp;
3022
import com.henninghall.date_picker.props.ModeProp;
3123
import com.henninghall.date_picker.props.TextColorProp;
32-
import com.henninghall.date_picker.props.UtcProp;
24+
import com.henninghall.date_picker.props.TimezoneOffsetInMinutesProp;
3325

3426

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

5648
@ReactPropGroup(names = { DateProp.name, ModeProp.name, LocaleProp.name, MaximumDateProp.name,
57-
MinimumDateProp.name, FadeToColorProp.name, TextColorProp.name, UtcProp.name, MinuteIntervalProp.name,
49+
MinimumDateProp.name, FadeToColorProp.name, TextColorProp.name, TimezoneOffsetInMinutesProp.name, MinuteIntervalProp.name,
5850
VariantProp.name, DividerHeightProp.name, Is24hourSourceProp.name
5951
})
6052
public void setProps(PickerView view, int index, Dynamic value) {

android/src/main/java/com/henninghall/date_picker/PickerView.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import com.henninghall.date_picker.props.MaximumDateProp;
1212
import com.henninghall.date_picker.props.MinimumDateProp;
1313
import com.henninghall.date_picker.props.MinuteIntervalProp;
14-
import com.henninghall.date_picker.props.UtcProp;
14+
import com.henninghall.date_picker.props.TimezoneOffsetInMinutesProp;
1515
import com.henninghall.date_picker.props.VariantProp;
1616
import com.henninghall.date_picker.props.DateProp;
1717
import com.henninghall.date_picker.props.FadeToColorProp;
@@ -77,7 +77,7 @@ public void update() {
7777

7878
if (didUpdate(DateProp.name, HeightProp.name, LocaleProp.name,
7979
MaximumDateProp.name, MinimumDateProp.name, MinuteIntervalProp.name, ModeProp.name,
80-
UtcProp.name, VariantProp.name
80+
TimezoneOffsetInMinutesProp.name, VariantProp.name
8181
)) {
8282
uiManager.updateDisplayValues();
8383
}

android/src/main/java/com/henninghall/date_picker/State.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
import com.henninghall.date_picker.props.ModeProp;
1818
import com.henninghall.date_picker.props.Prop;
1919
import com.henninghall.date_picker.props.TextColorProp;
20-
import com.henninghall.date_picker.props.UtcProp;
20+
import com.henninghall.date_picker.props.TimezoneOffsetInMinutesProp;
21+
22+
import net.time4j.tz.Timezone;
2123

2224
import java.util.Calendar;
2325
import java.util.HashMap;
@@ -35,7 +37,7 @@ public class State {
3537
private final MinuteIntervalProp minuteIntervalProp = new MinuteIntervalProp();
3638
private final MinimumDateProp minimumDateProp = new MinimumDateProp();
3739
private final MaximumDateProp maximumDateProp = new MaximumDateProp();
38-
private final UtcProp utcProp = new UtcProp();
40+
private final TimezoneOffsetInMinutesProp timezoneOffsetInMinutesProp = new TimezoneOffsetInMinutesProp();
3941
private final HeightProp heightProp = new HeightProp();
4042
private final VariantProp variantProp = new VariantProp();
4143
private final DividerHeightProp dividerHeightProp = new DividerHeightProp();
@@ -50,7 +52,7 @@ public class State {
5052
put(MinuteIntervalProp.name, minuteIntervalProp);
5153
put(MinimumDateProp.name, minimumDateProp);
5254
put(MaximumDateProp.name, maximumDateProp);
53-
put(UtcProp.name, utcProp);
55+
put(TimezoneOffsetInMinutesProp.name, timezoneOffsetInMinutesProp);
5456
put(HeightProp.name, heightProp);
5557
put(VariantProp.name, variantProp);
5658
put(DividerHeightProp.name, dividerHeightProp);
@@ -91,18 +93,23 @@ public Locale getLocale() {
9193
}
9294

9395
public Calendar getMinimumDate() {
94-
DateBoundary db = new DateBoundary(getTimeZone(), (String) minimumDateProp.getValue());
95-
return db.get();
96+
return Utils.isoToCalendar(minimumDateProp.getValue(), getTimeZone());
9697
}
9798

9899
public Calendar getMaximumDate() {
99-
DateBoundary db = new DateBoundary(getTimeZone(), (String) maximumDateProp.getValue());
100-
return db.get();
100+
return Utils.isoToCalendar(maximumDateProp.getValue(), getTimeZone());
101101
}
102102

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

108115
public String getIsoDate() {

android/src/main/java/com/henninghall/date_picker/Utils.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import net.time4j.PrettyTime;
1111

12+
import java.text.DecimalFormat;
1213
import java.text.ParseException;
1314
import java.text.SimpleDateFormat;
1415
import java.util.ArrayList;
@@ -110,4 +111,9 @@ public static String getLocalisedStringFromResources(Locale locale, String tagNa
110111
public static int toDp(int pixels){
111112
return (int) (pixels * DatePickerPackage.context.getResources().getDisplayMetrics().density);
112113
}
114+
115+
public static String toPaddedMinutes(int minutes){
116+
DecimalFormat df = new DecimalFormat("00");
117+
return df.format(minutes);
118+
}
113119
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.henninghall.date_picker.props;
2+
3+
import com.facebook.react.bridge.Dynamic;
4+
5+
public class TimezoneOffsetInMinutesProp extends Prop<Integer> {
6+
public static final String name = "timezoneOffsetInMinutes";
7+
8+
@Override
9+
Integer toValue(Dynamic value) {
10+
if(value.isNull()) return null;
11+
return value.asInt();
12+
}
13+
}

android/src/main/java/com/henninghall/date_picker/props/UtcProp.java

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

0 commit comments

Comments
 (0)