Skip to content

fix: Fix timezone Date parsing for Hermes JS engine #2843

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

milesingrams
Copy link

When using the Hermes engine in the newer versions of React Native the timezone plugin doesn't work because there are a few places where the Date constructor is used to parse a en locale formatted date string and Hermes doesn't support that format of parsing (i.e. new Date('8/20/1999, 5:00:15 AM')). This issue results in the timezone plugin always returning GMT and UTC times when used in newer Expo and React Native apps. In order to work around this we can use dayjs itself to parse these dates instead of the native Date constructor. This PR allows dayjs to work in Expo and React Native with the timezone plugin.

@ndhunju
Copy link

ndhunju commented Mar 18, 2025

Wow I've been needing this!

@AustinStehling
Copy link

Can we get this merged before another dev loses their mind trying to debug this? 🚀🔥

Copy link

@ivashi ivashi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧠 !!!

@milesingrams
Copy link
Author

Similar to #2227 but I think simpler because it just uses dayjs itself to do the parsing here. Either works though!

@milesingrams
Copy link
Author

Also this Issue:
facebook/hermes#1519

@WonKimGoRevel
Copy link

🥇

@gabrielavoll
Copy link

Holy smokes he solved it !

@sherikovic
Copy link

oh boy I came to look for this exact issue, it's been driving me nuts for a day here. Hopefully this gets merged soon, thank you

@dlebedynskyi
Copy link

looks like this should fix #1377.

@anton-patrushev
Copy link

@iamkun can you please take a look and merge it in?

if it fixes a tz support for React-Native with Hermes — it would be a huge win!

@kleviss
Copy link

kleviss commented Apr 25, 2025

This is great!!!!! @milesingrams 🚀

Coming here from @dlebedynskyi mention of this fix in #1377

Maybe this isn’t the right place to ask for help about this issue, but I thought I’d share my experience in case anyone else is trying the same thing.

I tried using this branch as the reference for dayjs in my React Native project (with Hermes), and I wanted to share what I ran into when attempted to use this branch (with the fix). I cloned and built the repo using this branch, verified the fix was present in the code before building, and:

mkdir dayjs-tz-patch-milesingrams
cd dayjs-tz-patch-milesingrams 
git clone --single-branch --branch fix-timezone-date-parsing-for-hermes-js-engine https://github.com/milesingrams/dayjs.git
cd dayjs
npm install
export NODE_OPTIONS=--openssl-legacy-provider
npm run build
npm pack

This created the file dayjs-0.0.0-development.tgz, which I installed in my React Native project like so:

npm install /absolute/path/to/dayjs-tz-patch-milesingrams/dayjs/dayjs-0.0.0-development.tgz

Despite this, the timezone behavior was still broken when running with Hermes — it was as if the fix wasn’t applied.

I was hoping that anyone here can confirm — if this is the correct way to apply and test a patch in a project? Just want to make sure I didn’t miss something!

@konradjg
Copy link

This update does improve the timezone plugin using hermes although the test suite still shows some problems.

For reference I had to build a custom version of hermes to include support for Intl since that is not included by default (?). The support for Intl is currently a 'WIP'. It does look like dayjs only makes use of DateTimeFormat which appears to have good support in hermes.

set(HERMES_ENABLE_INTL OFF CACHE BOOL
  "Enable JS Intl support (WIP)")

Then I used the the exodus-test module to run tests using hermes engine

npx exodus-test --jest --engine hermes:bundle test/plugin/timezone.test.js

npx exodus-test --jest --engine hermes:bundle test/plugin/timezone.test.js
hermes:bundle engine is experimental and may not work an expected
# test/plugin/timezone.test.js
✔ PASS Guess > return string
✔ PASS Parse > parse target time string
✔ PASS Parse > parse timestamp, js Date, Day.js object
✔ PASS Parse > parse and convert between timezones
✔ PASS Parse > preserve milliseconds
✔ PASS Convert > convert to target time
✔ PASS Convert > convert to target time
✔ PASS Convert > convert from time with timezone to target time
✔ PASS Convert > DST
✔ PASS Convert > format Z
✔ PASS DST, a time that never existed Spring Forward > 2012-03-11 01:59:59
✔ PASS DST, a time that never existed Spring Forward > 2012-03-11 02:00:00
✔ PASS DST, a time that never existed Spring Forward > 2012-03-11 02:59:59
✔ PASS DST, a time that never existed Spring Forward > 2012-03-11 03:00:00
✔ PASS DST, a time that never existed Fall Back > 2012-11-04 00:59:59
✔ PASS DST, a time that never existed Fall Back > 2012-11-04 00:59:59
✔ PASS DST, a time that never existed Fall Back > 2012-11-04 02:00:00
✔ PASS DST valueOf
✔ PASS set Default > default timezone
✔ PASS set Default > empty timezone means local timezone
✖ FAIL set Default > change default timezone
  Error: expect(received).toBe(expected) // Object.is equality

Expected: "2014-06-01T12:00:00+09:00"
Received: "2014-06-01T12:09:00+08:48"

✖ FAIL set Default > override default timezone in proto.tz
  Error: expect(received).toBe(expected) // Object.is equality

Expected: "2014-06-01T12:00:00+09:00"
Received: "2014-06-01T12:09:00+08:48"

✖ FAIL set Default > override default timezone in d.tz
  Error: expect(received).toBe(expected) // Object.is equality

Expected: "2014-06-01T12:00:00+09:00"
Received: "2014-06-01T12:09:00+08:48"

✔ PASS keepLocalTime > keepLocalTime
✔ PASS Get offsetName > short
✖ FAIL Get offsetName > long
  Error: expect(received).toBe(expected) // Object.is equality

Expected: "Eastern Standard Time"
Received: "Eastern"
✔ PASS CustomPraseFormat > normal
✔ PASS CustomPraseFormat > custom
✔ PASS startOf and endOf > corrects for timezone offset in startOf
✔ PASS startOf and endOf > corrects for timezone offset in endOf
✔ PASS startOf and endOf > preserves locality when tz is called
✔ PASS UTC timezone > TZ with UTC with Locale
✔ PASS UTC timezone > TZ with UTC

@kleviss
Copy link

kleviss commented Apr 30, 2025

@konradjg Been following this thread closely and been looking at a lot of other threads and I think that nothing will get merged soon due to the fact that this is not a dayjs issue at all. It is mostly hermes issue and the main maintainer there have considered it super low priority facebook/hermes#1519 (comment) - For now I just went ahead with the ployfills suggested in #1377 (comment) and I think there is nothing wrong with that. At least for me it is doing the job it needs to. I may try in the following days to switch the engine to JSC or v8 as there are speculations online that it may make the app faster due to date manipulation e.g. facebook/hermes#930 or facebook/hermes#495 or hermes_very_slow_compared_to_jsc_with_big_data

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.