react-native-datepicker
react-native-datepicker copied to clipboard
Select one day, but selected one day +1. IOS
Select 28 october 1985, but selected 29 october 1985 Platform: IOS. How rule this problem? Thanks.
I'm having the same issue. Using:
<DatePicker style={[styles.inputField, styles.inputDatePicker]}
mode="date"
format="MMMM Do YYYY"
date={this.state.birth_date}
confirmBtnText="Confirm"
cancelBtnText="Cancel"
showIcon={false}
onDateChange={(strDate, date) => this.setState({'birth_date': date})} />
where the initial birth_date in state is moment().utc().toDate(). I have this happen without setting an initial date too.
On debug builds, everything is fine. The value selected in the DatePicker is the value I see when I hit "Confirm".
On Release builds, hitting "Confirm", the value returned isn't always the value in the DatePicker.
Sometimes it is, sometimes it's off by one year, sometimes it's off by one day. I haven't had this happen on an Android ever, but I've had this happen on Release mode in iOS simulators and iPhones (a 6s running iOS 10).
If I select March 14, 1992, value displayed in the DatePicker after I hit "confirm" is March 15, 1992, alongside the value passed to the DatePicker's onDateChange. This doesn't happen on every release build, nor does it occur for every date. But when it occurs, it's consistently off by one.
For now I'm switching over to using DatePickerIOS manually on my iOS builds, but this library works great for me on Android.
i am having the same problem. it is minus one day for me on IOS.
I was having similar problems trying to use "MMMM Do YYYY" on iOS. Trying to set 'Jan 1 2000' returns 'Jan 4 2000' or 'Jan 1 2001' for example. The built-in "YYYY-MM-DD" format seemed to work fine.
I found if I explicitly set minDate and maxDate props in "MMMM Do YYYY" format it would work correctly.
var localizedFormat = "MMMM Do YYYY";
var maxDateString = moment().format(localizedFormat); //Today
var minDateString = moment('19000101','YYYYMMDD').format(localizedFormat); //Jan 1 1900
...
<DatePicker
format={localizedFormat}
maxDate={maxDateString}
minDate={minDateString}
...
/>
I can confirm @Proberts suggestion above appears to be a solution. Explicitly setting the minDate/maxDate in the format of the picker seems to fix this problem.
@Proberts' solution didn't work for me, I fixed it by setting up the timeZoneOffsetInHours prop.
__constructor(props) {
super(props)
this.state = {
timeZoneOffsetInHours: (-1) * (new Date()).getTimezoneOffset() / 60,
birthdate: props.birthdate
}
}
render() {
...
<DatePicker
date={this.state.birthdate}
mode='date'
format={localizedFormat}
maxDate={maxDateString}
minDate={minDateString}
timeZoneOffsetInMinutes={this.state.timeZoneOffsetInHours * 60}
...
/>
...
}
I am still having the same issues on both iOS and Android after implementing @Proberts and @andruxnet 's solutions. The observation is that this issue will trigger for dates equals or earlier than year 1981.
Does anyone else has a solution ?
I fixed it by creating a new date object using .getUTC...() and including time
Example:
const date = new Date();
const dateForPicker = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
via https://stackoverflow.com/a/14006555/7569308
@andruxnet Thank you! This is such a bizarre issue, and still affecting the latest version of react-native. Your hack fixed it for me.
I can confirm that even with @andruxnet's fix, it's still happening on some random dates.
@andruxnet You solution is correct but it only work for iOS. This issue is also for android but android date picker doesn't support timeZoneOffsetInMinutes prop. now!
onDateChange={date => this.setState({ birth_date: new Date(date) }) }
to
onDateChange={date => this.setState({ birth_date: moment(date) }) }
did the trick for me.
@Proberts' solution didn't work for me, I fixed it by setting up the timeZoneOffsetInHours prop.
__constructor(props) { super(props) this.state = { timeZoneOffsetInHours: (-1) * (new Date()).getTimezoneOffset() / 60, birthdate: props.birthdate } } render() { ... <DatePicker date={this.state.birthdate} mode='date' format={localizedFormat} maxDate={maxDateString} minDate={minDateString} timeZoneOffsetInMinutes={this.state.timeZoneOffsetInHours * 60} ... /> ... }
@Proberts seems to be onto the right track. However; there is a caveat here that i found that might be the reason why it doesn't work for everyone.
Daylight savings time. and how you are calculating the offset.
First, if you set the offset as a static value you are going to run into problems. The gist of what happens here. Is that when you change from dates that go across a daylight savings time. The offset of the internal datepicker object changes. from in my case -7 to -6, and if you dont update your calculated offset based on that change (IE the internal state of the datepicker) then you are going to go from -7 to -6 which would cross a date barrier in my case.
you can see this in action on the snack that i have linked below. There is a toggle option that uses the compenents date value to calculate the offset vs the date set by the DatePikcerIOS date.
its an odd problem to be sure.
timeZoneOffsetInMinutes={
( (-1) * (new Date(this.props.date)).getTimezoneOffset() / 60 ) * 60
}
Heres is a snack of what i tested. although the offset sometimes doenst register maybe the emulated device is in a DST free zone?
It is very important here to set the initialDate of the internal iOS component to the internal state of the your wrapping component, and make sure your offset matches the initial date set on the compeonent. otherwise you will see odd things happen when the picker mounts in one offset but you set it to another. use the snack below and change the initial date from this.state.date to this.props.date and you will see what i mean.
https://snack.expo.io/ByceqT-6V
I don't understand only one thing. What is the purpose of dividing minutes by 60 to get hours and then multiplying by 60 to get minutes back.
Instead of
timeZoneOffsetInMinutes={
( (-1) * (new Date(this.props.date)).getTimezoneOffset() / 60 ) * 60
}
You could simply use
timeZoneOffsetInMinutes={
-1 * new Date(this.props.date).getTimezoneOffset()
}
@Proberts' solution didn't work for me, I fixed it by setting up the timeZoneOffsetInHours prop.
__constructor(props) { super(props) this.state = { timeZoneOffsetInHours: (-1) * (new Date()).getTimezoneOffset() / 60, birthdate: props.birthdate } } render() { ... <DatePicker date={this.state.birthdate} mode='date' format={localizedFormat} maxDate={maxDateString} minDate={minDateString} timeZoneOffsetInMinutes={this.state.timeZoneOffsetInHours * 60} ... /> ... }
i don't know why but when i add a very large number it works. Can you explain what this : timeZoneOffsetInMinutes? does?