React Native and the jumping datepicker

Florian Hirsch
Feb 17, 2019 · 2 min read

If you’re working with React Native you might have seen this:

Image for post
Image for post

Why is that? The React Native datepicker accepts a JS Date object as input which is maybe not the best idea. A JS Date marks a specific point in time. What a datepicker displays is a date without time and timezone.

What happens if you pass a Date object to the picker? React Native uses Calendar.getInstance() so it uses the local timezone of your device. When you construct a JS Date with less then two parameters JavaScript uses UTC. new Date('1978-08-07').toISOString() results in 1978-08-07T00:00:00.000Z with the timestamp 271296000000. In a timezone west of UTC it was August 6 at this point in time.

How can we fix that? We could add the timezone offset manually:

const date = new Date('1978-08-07');
const offset = -1 * date.getTimezoneOffset() * 60 * 1000;
const localDate = new Date(date.getTime() - offset);
// we could also use the more params constructor which uses the local timezone
new Date(1978, 7, 7);

This works quite well. Most of the time. For given date it’s still broken. Why? I’m currently in timezone “Europe/Berlin” and new Date('1978-08-07').getTimezoneOffset() returns -120. This is not correct. The same evaluated in the Chrome developer console on my MacBook outputs -60 which is correct. Berlin is GMT+01:00 (The JS result is inverted because it’s the difference, in minutes, from local time to UTC). Seems like the React Native JS Engine knows that I’m in Berlin, knows that in August we have DST and a offset of 2 hours but does not know that DST was introduced 1980 in Germany. The Android datepicker knows more and so you can find a lot of dates where these two are inconsistent. To make it even worse: If your simulator is attached to a debugger you can’t reproduce this as the JavaScript is evaluated via a browser engine on your host system and not the JS engine used by the device.

The easiest way to fix it is to rely on the timezone knowledge of moment.js:'1978-08-07', 'Europe/Berlin').toDate()'1978-08-07', 'Europe/Berlin').utcOffset() // 60

You can determine the local timezone via but react-native-device-info may be more reliable.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store