diff --git a/DatePickerAndroid.js b/DatePickerAndroid.js index 3e45fc1..b0f9012 100644 --- a/DatePickerAndroid.js +++ b/DatePickerAndroid.js @@ -20,13 +20,13 @@ class DatePickerAndroid extends React.Component { maximumDate={this._maximumDate()} onChange={this._onChange} style={[styles.picker, this.props.style]} + utc={this.props.timeZoneOffsetInMinutes !== undefined} /> ) } _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) } @@ -35,11 +35,20 @@ class DatePickerAndroid extends React.Component { _minimumDate = () => this._toIsoWithTimeZoneOffset(this.props.minimumDate); _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() + } } diff --git a/android/src/main/java/com/henninghall/date_picker/DatePickerManager.java b/android/src/main/java/com/henninghall/date_picker/DatePickerManager.java index 45b6d68..5a21a10 100644 --- a/android/src/main/java/com/henninghall/date_picker/DatePickerManager.java +++ b/android/src/main/java/com/henninghall/date_picker/DatePickerManager.java @@ -11,12 +11,16 @@ import net.time4j.android.ApplicationStarter; import org.apache.commons.lang3.LocaleUtils; import java.util.Map; +import java.util.TimeZone; public class DatePickerManager extends SimpleViewManager { public static final String REACT_CLASS = "DatePickerManager"; public static ThemedReactContext context; private String date; + private String minimumDate; + private String maximumDate; + private boolean utc; @Override public String getName() { @@ -43,7 +47,7 @@ public class DatePickerManager extends SimpleViewManager { @ReactProp(name = "date") public void setDate(PickerView view, @Nullable String date) { - this.date = date; + this.date = date; } @ReactProp(name = "locale") @@ -53,12 +57,12 @@ public class DatePickerManager extends SimpleViewManager { @ReactProp(name = "minimumDate") public void setMinimumDate(PickerView view, @Nullable String date) { - view.setMinimumDate(Utils.isoToDate(date)); + this.minimumDate = date; } @ReactProp(name = "maximumDate") public void setMaximumDate(PickerView view, @Nullable String date) { - view.setMaximumDate(Utils.isoToDate(date)); + this.maximumDate = date; } @ReactProp(name = "fadeToColor") @@ -77,11 +81,25 @@ public class DatePickerManager extends SimpleViewManager { view.setMinuteInterval(interval); } + @ReactProp(name = "utc") + public void setUtc(PickerView view, @Nullable boolean utc) throws Exception { + this.utc = utc; + } + + + @Override 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() { diff --git a/android/src/main/java/com/henninghall/date_picker/PickerView.java b/android/src/main/java/com/henninghall/date_picker/PickerView.java index 5e89e22..fd019b0 100644 --- a/android/src/main/java/com/henninghall/date_picker/PickerView.java +++ b/android/src/main/java/com/henninghall/date_picker/PickerView.java @@ -1,5 +1,6 @@ package com.henninghall.date_picker; +import android.os.Build; import android.view.View; 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.YearWheel; -import org.apache.commons.lang3.time.DateUtils; - import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -31,6 +30,7 @@ import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.TimeZone; import cn.carbswang.android.numberpickerview.library.NumberPickerView; @@ -49,11 +49,12 @@ public class PickerView extends RelativeLayout { public DateWheel dateWheel; public MonthWheel monthWheel; public YearWheel yearWheel; - public Date maxDate; - public Date minDate; + public Calendar maxDate; + public Calendar minDate; private WheelOrderUpdater wheelOrderUpdater; public boolean isInitialized = false; public boolean requireDisplayValueUpdate = true; + public TimeZone timeZone; public PickerView() { @@ -65,7 +66,7 @@ public class PickerView extends RelativeLayout { RelativeLayout wheelsWrapper = (RelativeLayout) rootView.findViewById(R.id.wheelsWrapper); 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); monthWheel = new MonthWheel( this, R.id.month); @@ -85,7 +86,10 @@ public class PickerView extends RelativeLayout { public void onChange(Wheel wheel) { WritableMap event = Arguments.createMap(); 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)); else if (maxDate != null && date.after(maxDate)) applyOnVisibleWheels(new AnimateToDate(maxDate)); 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; } - public void setMaximumDate(Date date) { - maxDate = Utils.getTruncatedDateOrNull(date); + public void setMaximumDate(Calendar cal) { + maxDate = Utils.getTruncatedCalendarOrNull(cal); 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) { @@ -228,4 +232,12 @@ public class PickerView extends RelativeLayout { requireDisplayValueUpdate = false; } } + + public void setTimeZone(TimeZone timeZone) { + this.timeZone = timeZone; + } + + public TimeZone getTimeZone() { + return timeZone; + } } diff --git a/android/src/main/java/com/henninghall/date_picker/Utils.java b/android/src/main/java/com/henninghall/date_picker/Utils.java index 967dd2f..635cbb8 100644 --- a/android/src/main/java/com/henninghall/date_picker/Utils.java +++ b/android/src/main/java/com/henninghall/date_picker/Utils.java @@ -25,18 +25,20 @@ public class Utils { 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 { - return getIsoUTCFormat().parse(date); + Calendar calendar = Calendar.getInstance(timeZone); + calendar.setTime(getIsoUTCFormat().parse(dateString)); + return calendar; } catch (ParseException e) { e.printStackTrace(); 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) { @@ -58,9 +60,9 @@ public class Utils { return DateUtils.isToday(cal.getTimeInMillis()); } - public static Date getTruncatedDateOrNull(Date date) { + public static Calendar getTruncatedCalendarOrNull(Calendar cal) { 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){ return null; } @@ -69,6 +71,7 @@ public class Utils { private static SimpleDateFormat getIsoUTCFormat(){ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); format.setTimeZone(TimeZone.getTimeZone("UTC")); + return format; } diff --git a/android/src/main/java/com/henninghall/date_picker/wheelFunctions/AnimateToDate.java b/android/src/main/java/com/henninghall/date_picker/wheelFunctions/AnimateToDate.java index e3741df..1daf17c 100644 --- a/android/src/main/java/com/henninghall/date_picker/wheelFunctions/AnimateToDate.java +++ b/android/src/main/java/com/henninghall/date_picker/wheelFunctions/AnimateToDate.java @@ -2,13 +2,14 @@ package com.henninghall.date_picker.wheelFunctions; import com.henninghall.date_picker.wheels.Wheel; +import java.util.Calendar; import java.util.Date; public class AnimateToDate implements WheelFunction { - private Date date; + private Calendar date; - public AnimateToDate(Date date) { + public AnimateToDate(Calendar date) { this.date = date; } diff --git a/android/src/main/java/com/henninghall/date_picker/wheelFunctions/SetDate.java b/android/src/main/java/com/henninghall/date_picker/wheelFunctions/SetDate.java index f588acc..80fd19a 100644 --- a/android/src/main/java/com/henninghall/date_picker/wheelFunctions/SetDate.java +++ b/android/src/main/java/com/henninghall/date_picker/wheelFunctions/SetDate.java @@ -2,13 +2,14 @@ package com.henninghall.date_picker.wheelFunctions; import com.henninghall.date_picker.wheels.Wheel; +import java.util.Calendar; import java.util.Date; public class SetDate implements WheelFunction { - private Date date; + private Calendar date; - public SetDate(Date date) { + public SetDate(Calendar date) { this.date = date; } diff --git a/android/src/main/java/com/henninghall/date_picker/wheels/DayWheel.java b/android/src/main/java/com/henninghall/date_picker/wheels/DayWheel.java index 5a98d62..bc3881c 100644 --- a/android/src/main/java/com/henninghall/date_picker/wheels/DayWheel.java +++ b/android/src/main/java/com/henninghall/date_picker/wheels/DayWheel.java @@ -6,6 +6,7 @@ import com.henninghall.date_picker.Utils; import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.Date; public class DayWheel extends Wheel { @@ -33,22 +34,27 @@ public class DayWheel extends Wheel { } private Calendar getStartCal(){ - Calendar cal = pickerView.getInitialDate(); + Calendar cal; if (pickerView.minDate != null) { - cal.setTime(pickerView.minDate); + cal = (Calendar) pickerView.minDate.clone(); resetToMidnight(cal); + } else { + cal = (Calendar) pickerView.getInitialDate().clone(); + cal.add(Calendar.DATE, -defaultNumberOfDays / 2); } - else cal.add(Calendar.DATE, -defaultNumberOfDays / 2); return cal; } private Calendar getEndCal(){ - Calendar cal = Calendar.getInstance(); + Calendar cal; if (pickerView.maxDate != null) { - cal.setTime(pickerView.maxDate); + cal = (Calendar) pickerView.maxDate.clone(); 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; } diff --git a/android/src/main/java/com/henninghall/date_picker/wheels/Wheel.java b/android/src/main/java/com/henninghall/date_picker/wheels/Wheel.java index 891374d..ec219a3 100644 --- a/android/src/main/java/com/henninghall/date_picker/wheels/Wheel.java +++ b/android/src/main/java/com/henninghall/date_picker/wheels/Wheel.java @@ -7,6 +7,7 @@ import com.henninghall.date_picker.R; import org.apache.commons.lang3.LocaleUtils; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; import cn.carbswang.android.numberpickerview.library.NumberPickerView; @@ -49,11 +50,12 @@ public abstract class Wheel { 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)); } @@ -70,8 +72,9 @@ public abstract class Wheel { 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); if(index > -1) { diff --git a/android/src/main/java/com/henninghall/date_picker/wheels/YearWheel.java b/android/src/main/java/com/henninghall/date_picker/wheels/YearWheel.java index f4e099d..db4e674 100644 --- a/android/src/main/java/com/henninghall/date_picker/wheels/YearWheel.java +++ b/android/src/main/java/com/henninghall/date_picker/wheels/YearWheel.java @@ -37,18 +37,14 @@ public class YearWheel extends Wheel if (this.pickerView.maxDate == null) { 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() { - 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