Browse Source

Merge pull request #38 from ineentho/fix/tz-offset-android

Fix for timezone bug in android picker
master
Henning Hall 6 years ago
committed by GitHub
parent
commit
356b397d37
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 102 additions and 53 deletions
  1. +14
    -5
      DatePickerAndroid.js
  2. +24
    -6
      android/src/main/java/com/henninghall/date_picker/DatePickerManager.java
  3. +24
    -12
      android/src/main/java/com/henninghall/date_picker/PickerView.java
  4. +10
    -7
      android/src/main/java/com/henninghall/date_picker/Utils.java
  5. +3
    -2
      android/src/main/java/com/henninghall/date_picker/wheelFunctions/AnimateToDate.java
  6. +3
    -2
      android/src/main/java/com/henninghall/date_picker/wheelFunctions/SetDate.java
  7. +12
    -6
      android/src/main/java/com/henninghall/date_picker/wheels/DayWheel.java
  8. +8
    -5
      android/src/main/java/com/henninghall/date_picker/wheels/Wheel.java
  9. +4
    -8
      android/src/main/java/com/henninghall/date_picker/wheels/YearWheel.java

+ 14
- 5
DatePickerAndroid.js View File

@ -20,13 +20,13 @@ class DatePickerAndroid extends React.Component {
maximumDate={this._maximumDate()} maximumDate={this._maximumDate()}
onChange={this._onChange} onChange={this._onChange}
style={[styles.picker, this.props.style]} style={[styles.picker, this.props.style]}
utc={this.props.timeZoneOffsetInMinutes !== undefined}
/> />
) )
} }
_onChange = e => { _onChange = e => {
const momentDateWithOffset = moment(e.nativeEvent.date).add(this._getOffsetMinutes(), 'minutes')
const jsDate = momentDateWithOffset.toDate()
const jsDate = this._fromIsoWithTimeZoneOffset(e.nativeEvent.date).toDate()
this.props.onDateChange(jsDate) this.props.onDateChange(jsDate)
} }
@ -35,11 +35,20 @@ class DatePickerAndroid extends React.Component {
_minimumDate = () => this._toIsoWithTimeZoneOffset(this.props.minimumDate); _minimumDate = () => this._toIsoWithTimeZoneOffset(this.props.minimumDate);
_date = () => this._toIsoWithTimeZoneOffset(this.props.date); _date = () => this._toIsoWithTimeZoneOffset(this.props.date);
_fromIsoWithTimeZoneOffset = date => {
if (this.props.timeZoneOffsetInMinutes === undefined)
return moment(date)
return moment.utc(date).subtract(this.props.timeZoneOffsetInMinutes, 'minutes')
}
_toIsoWithTimeZoneOffset = date => date && moment(date).add( -this._getOffsetMinutes(), 'minutes').toISOString()
_toIsoWithTimeZoneOffset = date => {
if (this.props.timeZoneOffsetInMinutes === undefined)
return moment(date).toISOString()
_getOffsetMinutes = () => this.props.timeZoneOffsetInMinutes === undefined ? 0
: -(this.props.timeZoneOffsetInMinutes + new Date().getTimezoneOffset())
return moment.utc(date).add(this.props.timeZoneOffsetInMinutes, 'minutes').toISOString()
}
} }

+ 24
- 6
android/src/main/java/com/henninghall/date_picker/DatePickerManager.java View File

@ -11,12 +11,16 @@ import net.time4j.android.ApplicationStarter;
import org.apache.commons.lang3.LocaleUtils; import org.apache.commons.lang3.LocaleUtils;
import java.util.Map; import java.util.Map;
import java.util.TimeZone;
public class DatePickerManager extends SimpleViewManager<PickerView> { public class DatePickerManager extends SimpleViewManager<PickerView> {
public static final String REACT_CLASS = "DatePickerManager"; public static final String REACT_CLASS = "DatePickerManager";
public static ThemedReactContext context; public static ThemedReactContext context;
private String date; private String date;
private String minimumDate;
private String maximumDate;
private boolean utc;
@Override @Override
public String getName() { public String getName() {
@ -43,7 +47,7 @@ public class DatePickerManager extends SimpleViewManager {
@ReactProp(name = "date") @ReactProp(name = "date")
public void setDate(PickerView view, @Nullable String date) { public void setDate(PickerView view, @Nullable String date) {
this.date = date;
this.date = date;
} }
@ReactProp(name = "locale") @ReactProp(name = "locale")
@ -53,12 +57,12 @@ public class DatePickerManager extends SimpleViewManager {
@ReactProp(name = "minimumDate") @ReactProp(name = "minimumDate")
public void setMinimumDate(PickerView view, @Nullable String date) { public void setMinimumDate(PickerView view, @Nullable String date) {
view.setMinimumDate(Utils.isoToDate(date));
this.minimumDate = date;
} }
@ReactProp(name = "maximumDate") @ReactProp(name = "maximumDate")
public void setMaximumDate(PickerView view, @Nullable String date) { public void setMaximumDate(PickerView view, @Nullable String date) {
view.setMaximumDate(Utils.isoToDate(date));
this.maximumDate = date;
} }
@ReactProp(name = "fadeToColor") @ReactProp(name = "fadeToColor")
@ -77,11 +81,25 @@ public class DatePickerManager extends SimpleViewManager {
view.setMinuteInterval(interval); view.setMinuteInterval(interval);
} }
@ReactProp(name = "utc")
public void setUtc(PickerView view, @Nullable boolean utc) throws Exception {
this.utc = utc;
}
@Override @Override
protected void onAfterUpdateTransaction(PickerView view) { protected void onAfterUpdateTransaction(PickerView view) {
super.onAfterUpdateTransaction(view);
view.updateDisplayValuesIfNeeded();
view.setDate(Utils.isoToDate(date));
super.onAfterUpdateTransaction(view);
TimeZone timeZone = utc ? TimeZone.getTimeZone("UTC") : TimeZone.getDefault();
view.setTimeZone(timeZone);
view.setMinimumDate(Utils.isoToCalendar(minimumDate, timeZone));
view.setMaximumDate(Utils.isoToCalendar(maximumDate, timeZone));
// Refresh which options are available. Should happen before updating the date
view.updateDisplayValuesIfNeeded();
view.setDate(Utils.isoToCalendar(date, timeZone));
} }
public Map getExportedCustomBubblingEventTypeConstants() { public Map getExportedCustomBubblingEventTypeConstants() {

+ 24
- 12
android/src/main/java/com/henninghall/date_picker/PickerView.java View File

@ -1,5 +1,6 @@
package com.henninghall.date_picker; package com.henninghall.date_picker;
import android.os.Build;
import android.view.View; import android.view.View;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
@ -20,8 +21,6 @@ import com.henninghall.date_picker.wheels.MonthWheel;
import com.henninghall.date_picker.wheels.Wheel; import com.henninghall.date_picker.wheels.Wheel;
import com.henninghall.date_picker.wheels.YearWheel; import com.henninghall.date_picker.wheels.YearWheel;
import org.apache.commons.lang3.time.DateUtils;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
@ -31,6 +30,7 @@ import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone;
import cn.carbswang.android.numberpickerview.library.NumberPickerView; import cn.carbswang.android.numberpickerview.library.NumberPickerView;
@ -49,11 +49,12 @@ public class PickerView extends RelativeLayout {
public DateWheel dateWheel; public DateWheel dateWheel;
public MonthWheel monthWheel; public MonthWheel monthWheel;
public YearWheel yearWheel; public YearWheel yearWheel;
public Date maxDate;
public Date minDate;
public Calendar maxDate;
public Calendar minDate;
private WheelOrderUpdater wheelOrderUpdater; private WheelOrderUpdater wheelOrderUpdater;
public boolean isInitialized = false; public boolean isInitialized = false;
public boolean requireDisplayValueUpdate = true; public boolean requireDisplayValueUpdate = true;
public TimeZone timeZone;
public PickerView() { public PickerView() {
@ -65,7 +66,7 @@ public class PickerView extends RelativeLayout {
RelativeLayout wheelsWrapper = (RelativeLayout) rootView.findViewById(R.id.wheelsWrapper); RelativeLayout wheelsWrapper = (RelativeLayout) rootView.findViewById(R.id.wheelsWrapper);
wheelsWrapper.setWillNotDraw(false); wheelsWrapper.setWillNotDraw(false);
locale = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP ? Locale.forLanguageTag("en") : Locale.getDefault();
locale = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? Locale.forLanguageTag("en") : Locale.getDefault();
yearWheel = new YearWheel( this, R.id.year); yearWheel = new YearWheel( this, R.id.year);
monthWheel = new MonthWheel( this, R.id.month); monthWheel = new MonthWheel( this, R.id.month);
@ -85,7 +86,10 @@ public class PickerView extends RelativeLayout {
public void onChange(Wheel wheel) { public void onChange(Wheel wheel) {
WritableMap event = Arguments.createMap(); WritableMap event = Arguments.createMap();
try { try {
Date date = dateFormat.parse(getDateString());
dateFormat.setTimeZone(timeZone);
Calendar date = Calendar.getInstance(timeZone);
date.setTime(dateFormat.parse(getDateString()));
if (minDate != null && date.before(minDate)) applyOnVisibleWheels(new AnimateToDate(minDate)); if (minDate != null && date.before(minDate)) applyOnVisibleWheels(new AnimateToDate(minDate));
else if (maxDate != null && date.after(maxDate)) applyOnVisibleWheels(new AnimateToDate(maxDate)); else if (maxDate != null && date.after(maxDate)) applyOnVisibleWheels(new AnimateToDate(maxDate));
else { else {
@ -123,18 +127,18 @@ public class PickerView extends RelativeLayout {
}); });
} }
public void setMinimumDate(Date date) {
minDate = Utils.getTruncatedDateOrNull(date);
public void setMinimumDate(Calendar cal) {
minDate = Utils.getTruncatedCalendarOrNull(cal);
requireDisplayValueUpdate = true; requireDisplayValueUpdate = true;
} }
public void setMaximumDate(Date date) {
maxDate = Utils.getTruncatedDateOrNull(date);
public void setMaximumDate(Calendar cal) {
maxDate = Utils.getTruncatedCalendarOrNull(cal);
requireDisplayValueUpdate = true; requireDisplayValueUpdate = true;
} }
public void setDate(Date date) {
applyOnAllWheels(new SetDate(date));
public void setDate(Calendar cal) {
applyOnAllWheels(new SetDate(cal));
} }
public void setLocale(Locale locale) { public void setLocale(Locale locale) {
@ -228,4 +232,12 @@ public class PickerView extends RelativeLayout {
requireDisplayValueUpdate = false; requireDisplayValueUpdate = false;
} }
} }
public void setTimeZone(TimeZone timeZone) {
this.timeZone = timeZone;
}
public TimeZone getTimeZone() {
return timeZone;
}
} }

+ 10
- 7
android/src/main/java/com/henninghall/date_picker/Utils.java View File

@ -25,18 +25,20 @@ public class Utils {
return UnitPatterns.of(locale).getTodayWord(); return UnitPatterns.of(locale).getTodayWord();
} }
public static Date isoToDate(String date) {
if(date == null) return null;
public static Calendar isoToCalendar(String dateString, TimeZone timeZone) {
if(dateString == null) return null;
try { try {
return getIsoUTCFormat().parse(date);
Calendar calendar = Calendar.getInstance(timeZone);
calendar.setTime(getIsoUTCFormat().parse(dateString));
return calendar;
} catch (ParseException e) { } catch (ParseException e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
} }
public static String dateToIso(Date date) {
return getIsoUTCFormat().format(date);
public static String dateToIso(Calendar date) {
return getIsoUTCFormat().format(date.getTime());
} }
public static int getWheelHeight(View pickerView) { public static int getWheelHeight(View pickerView) {
@ -58,9 +60,9 @@ public class Utils {
return DateUtils.isToday(cal.getTimeInMillis()); return DateUtils.isToday(cal.getTimeInMillis());
} }
public static Date getTruncatedDateOrNull(Date date) {
public static Calendar getTruncatedCalendarOrNull(Calendar cal) {
try { try {
return org.apache.commons.lang3.time.DateUtils.truncate(date, Calendar.MINUTE);
return org.apache.commons.lang3.time.DateUtils.truncate(cal, Calendar.MINUTE);
} catch (Exception e){ } catch (Exception e){
return null; return null;
} }
@ -69,6 +71,7 @@ public class Utils {
private static SimpleDateFormat getIsoUTCFormat(){ private static SimpleDateFormat getIsoUTCFormat(){
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC")); format.setTimeZone(TimeZone.getTimeZone("UTC"));
return format; return format;
} }

+ 3
- 2
android/src/main/java/com/henninghall/date_picker/wheelFunctions/AnimateToDate.java View File

@ -2,13 +2,14 @@ package com.henninghall.date_picker.wheelFunctions;
import com.henninghall.date_picker.wheels.Wheel; import com.henninghall.date_picker.wheels.Wheel;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
public class AnimateToDate implements WheelFunction { public class AnimateToDate implements WheelFunction {
private Date date;
private Calendar date;
public AnimateToDate(Date date) {
public AnimateToDate(Calendar date) {
this.date = date; this.date = date;
} }

+ 3
- 2
android/src/main/java/com/henninghall/date_picker/wheelFunctions/SetDate.java View File

@ -2,13 +2,14 @@ package com.henninghall.date_picker.wheelFunctions;
import com.henninghall.date_picker.wheels.Wheel; import com.henninghall.date_picker.wheels.Wheel;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
public class SetDate implements WheelFunction { public class SetDate implements WheelFunction {
private Date date;
private Calendar date;
public SetDate(Date date) {
public SetDate(Calendar date) {
this.date = date; this.date = date;
} }

+ 12
- 6
android/src/main/java/com/henninghall/date_picker/wheels/DayWheel.java View File

@ -6,6 +6,7 @@ import com.henninghall.date_picker.Utils;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
public class DayWheel extends Wheel { public class DayWheel extends Wheel {
@ -33,22 +34,27 @@ public class DayWheel extends Wheel {
} }
private Calendar getStartCal(){ private Calendar getStartCal(){
Calendar cal = pickerView.getInitialDate();
Calendar cal;
if (pickerView.minDate != null) { if (pickerView.minDate != null) {
cal.setTime(pickerView.minDate);
cal = (Calendar) pickerView.minDate.clone();
resetToMidnight(cal); resetToMidnight(cal);
} else {
cal = (Calendar) pickerView.getInitialDate().clone();
cal.add(Calendar.DATE, -defaultNumberOfDays / 2);
} }
else cal.add(Calendar.DATE, -defaultNumberOfDays / 2);
return cal; return cal;
} }
private Calendar getEndCal(){ private Calendar getEndCal(){
Calendar cal = Calendar.getInstance();
Calendar cal;
if (pickerView.maxDate != null) { if (pickerView.maxDate != null) {
cal.setTime(pickerView.maxDate);
cal = (Calendar) pickerView.maxDate.clone();
resetToMidnight(cal); resetToMidnight(cal);
} else {
cal = (Calendar) pickerView.getInitialDate().clone();
cal.setTime(new Date());
cal.add(Calendar.DATE, defaultNumberOfDays / 2);
} }
else cal.add(Calendar.DATE, defaultNumberOfDays / 2);
return cal; return cal;
} }

+ 8
- 5
android/src/main/java/com/henninghall/date_picker/wheels/Wheel.java View File

@ -7,6 +7,7 @@ import com.henninghall.date_picker.R;
import org.apache.commons.lang3.LocaleUtils; import org.apache.commons.lang3.LocaleUtils;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import cn.carbswang.android.numberpickerview.library.NumberPickerView; import cn.carbswang.android.numberpickerview.library.NumberPickerView;
@ -49,11 +50,12 @@ public abstract class Wheel {
this.displayValues= new ArrayList<>(); this.displayValues= new ArrayList<>();
} }
public int getIndexOfDate(Date date){
return values.indexOf(format.format(date));
public int getIndexOfDate(Calendar date){
format.setTimeZone(pickerView.timeZone);
return values.indexOf(format.format(date.getTime()));
} }
public void animateToDate(Date date) {
public void animateToDate(Calendar date) {
picker.smoothScrollToValue(getIndexOfDate(date)); picker.smoothScrollToValue(getIndexOfDate(date));
} }
@ -70,8 +72,9 @@ public abstract class Wheel {
return values.get(index); return values.get(index);
} }
public void setValue(Date date) {
this.userSetValue = format.format(date);
public void setValue(Calendar date) {
format.setTimeZone(pickerView.timeZone);
this.userSetValue = format.format(date.getTime());
int index = getIndexOfDate(date); int index = getIndexOfDate(date);
if(index > -1) { if(index > -1) {

+ 4
- 8
android/src/main/java/com/henninghall/date_picker/wheels/YearWheel.java View File

@ -37,18 +37,14 @@ public class YearWheel extends Wheel
if (this.pickerView.maxDate == null) { if (this.pickerView.maxDate == null) {
return this.defaultEndYear; return this.defaultEndYear;
} }
final Calendar cal = pickerView.getInitialDate();
cal.setTime(this.pickerView.maxDate);
return cal.get(Calendar.YEAR);
return this.pickerView.maxDate.get(Calendar.YEAR);
} }
private int getStartYear() { private int getStartYear() {
if (this.pickerView.minDate != null) {
final Calendar cal = pickerView.getInitialDate();
cal.setTime(this.pickerView.minDate);
return cal.get(Calendar.YEAR);
if (this.pickerView.minDate == null) {
return this.defaultStartYear;
} }
return this.defaultStartYear;
return this.pickerView.minDate.get(Calendar.YEAR);
} }
@Override @Override

Loading…
Cancel
Save