datetimepicker icon indicating copy to clipboard operation
datetimepicker copied to clipboard

Date picker on iOS has different selected value then Date received in onChange callback

Open kumien opened this issue 5 years ago • 17 comments

Bug

DateTimePicker on iOS return in onChange method different then selected one. Different is one day.

Environment info

React native info output:

info Fetching system and libraries information...
System:
    OS: macOS 10.15.2
    CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
    Memory: 128.34 MB / 16.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 13.7.0 - /usr/local/bin/node
    Yarn: 1.21.1 - /usr/local/bin/yarn
    npm: 6.13.6 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
  IDEs:
    Android Studio: 3.5 AI-191.8026.42.35.6010548
    Xcode: 11.3.1/11C504 - /usr/bin/xcodebuild
  npmPackages:
    react: ^16.12.0 => 16.12.0 
    react-native: 0.61.4 => 0.61.4 
  npmGlobalPackages:
    create-react-native-app: 2.0.2
    react-native-cli: 2.0.1

Library version: 2.2.1

Steps To Reproduce

  1. Create simple app with DateTimePicker.
  2. Add item like this: <DateTimePicker testID="dateTimePicker" timeZoneOffsetInMinutes={0} value={parseDate(value)} mode={'date'} is24Hour={true} display="default" onChange={(event, date) => { debugger; console.log("Event: " + event.type); console.log("Selected date: " + date)); />
  3. Run it on iOS simulator. ...

Describe what you expected to happen:

  1. Date on picker should be the same as it is in onChange callback function

kumien avatar Feb 10 '20 13:02 kumien

+1

arnaudambro avatar Feb 19 '20 16:02 arnaudambro

Can it be due to timeZoneOffsetInMinutes={0}? It is date mode, but still try removing this timeZoneOffsetInMinutes={0} from props, and maybe it will work.

ghost avatar Feb 24 '20 14:02 ghost

I'm having the same issue. It seems that it's a timezone issue and that ios is automatically converting the time to utc from the devices selected time zone. This is problematic for us though since we are only interested in the actual date entered by the user. On Android the correct date always gets shown regardless of device timezone.

Is there any fix for this?

greatwitenorth avatar Mar 18 '20 20:03 greatwitenorth

I'm facing same Issue. But different is six days. Please help. Is there any solution for this?

mustakimkr avatar Apr 11 '20 16:04 mustakimkr

Hey guys...I am also having this issue. Any update here ? cc @kumien

elvispap avatar Apr 11 '20 18:04 elvispap

@elvispap I couldn't resolve that issue and I have switched current library to react-native-modal-datetime-picker. It hasn't that kind of issue.

kumien avatar Apr 15 '20 11:04 kumien

@kumien I was able to solve the issue by setting value from state. And setting state to the date value received in onChange callback.

Tayyaba3317 avatar Apr 21 '20 11:04 Tayyaba3317

Yes I did the same at the end, and it's working well like that.

arnaudambro avatar Apr 21 '20 11:04 arnaudambro

I am having this issue. I want to set the picker to automatically start at 7AM no matter what the time zone but it's adjusting itself, regardless of whether I use the timeZoneOffsetInMinutes prop or not. I could calculate timezone offset and then dynamically generate new time that is equivalent to 7AM in local time zone, but that seems a bit ridiculous if necessary. Any help appreciated.

shannonjensen avatar Apr 26 '20 21:04 shannonjensen

I am having the same issue both on android and ios the difference is one day. Edit: Solved the issue by using the toLocaleDateString() method

const onChange = (event, selectedDate) => {
    const currentDate = selectedDate || date;
    console.log(selectedDate.toLocaleDateString()); // Returns the correct date string you can convert it back to date if you need an date object.
    setModalVisible(Platform.OS === 'ios');
  };

It's a temporary fix the issue needs to be resolved since the timezone offset has no effect in the date picker.

ZE0TRON avatar Jun 01 '20 15:06 ZE0TRON

I had the same issue, my solutions was: const parserDate = date.replace(/-/g, '/') and then return it return new Date(parserDate) . when you use it on this way new Date('2017/06/15') you don't need to specify the timezone

bryanmnk avatar Jun 09 '20 22:06 bryanmnk

Hi -

We were also struggling with timezone related "date jumping" issues. Specifically, we had two issues:

  1. during selection in the picker, sometimes the date would jump back one
  2. after selection and clicking done, the date would change to back one

Because the DateTimePicker requires to receive the date in Date format, but our app generally deals with and stores the date as a string, our working assumption was that a lot of these issues were related to converting between strings and javascript Date(), and timezone related issues cropping up in the process.

In our original code, we wrote custom code to inject timezone into the string and pass to Date(). After a long struggle bus of debugging, we found this helpful article which led us to the fix: https://medium.com/@lefloh/react-native-and-the-jumping-datepicker-853070554fb4

Root cause - essentially it seems that the timezone handling within React Native Javascript core itself is unreliable (so doing things like new Date().getTimezoneOffset()) were producing unreliable results.

The fix - use moment js to injectTimezone if you have to convert between date strings and date objects. To give you a sense, in the end some key code in our component looks like this:

// This will format your date into a string e.g. "2020-08-11"
const getFormattedDate = (selectedDate) => {
    return `${selectedDate.getFullYear()}-${padDateValue(
        selectedDate.getMonth() + 1,
    )}-${padDateValue(selectedDate.getDate())}`;
};

// This will inject the current timezone into your dateString and return a date
const injectTimezone = (dateString) => {
    return moment.tz(dateString, moment.tz.guess()).toDate();
};

Hope this is helpful!

aligg avatar Jul 09 '20 19:07 aligg

there is a "timeZoneOffsetInMinutes" prop, setting it to the user's timezone offset solved this.

const offset = new Date().getTimezoneOffset() * -1;
<DateTimePicker
    timeZoneOffsetInMinutes={offset}

chrisid avatar Aug 24 '20 15:08 chrisid

this works for me @chrisid thanks!

ebnersilva avatar Sep 24 '20 21:09 ebnersilva

Workaround:

const onChange = (event, selectedDate) => {
    setShow(Platform.OS === 'ios');
    const dateStr = `${selectedDate.getFullYear()}-${('0' + (selectedDate.getMonth() + 1)).slice(-2)}-${('0' + selectedDate.getDate()).slice(-2)}`;
    const newDate = new Date(dateStr);
    setDate(newDate);
    console.log(newDate);
  }; 

date-fix

charitha95 avatar Jan 13 '21 20:01 charitha95

For Me onChange{} callback is never called when selecting a date from UI is IOS. Need help.

dhirajanand014 avatar Feb 04 '21 17:02 dhirajanand014

There are subtle problems as the default RN javascript engine lacks timezone information for DST. In my case with a device on GMT-5 (US CDT) i found 9 Mar 2003 and 30 Mar 2003 would work inconsistently. (1 works / 1 doesn't) . Thats probably a DST induced issue. The fix was to npm install moment-timezone and use moment for date/string conversions.

giantslogik avatar Apr 16 '21 13:04 giantslogik

:tada: This issue has been resolved in version 7.5.0 :tada:

If this package helps you, consider sponsoring us! :rocket:

vonovak avatar Aug 29 '23 13:08 vonovak