dayjs icon indicating copy to clipboard operation
dayjs copied to clipboard

fix: Fix timezone Date parsing for Hermes JS engine

Open milesingrams opened this issue 9 months ago β€’ 12 comments

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.

milesingrams avatar Mar 18 '25 17:03 milesingrams

Wow I've been needing this!

ndhunju avatar Mar 18 '25 17:03 ndhunju

Can we get this merged before another dev loses their mind trying to debug this? πŸš€πŸ”₯

AustinStehling avatar Mar 18 '25 17:03 AustinStehling

Similar to https://github.com/iamkun/dayjs/pull/2227 but I think simpler because it just uses dayjs itself to do the parsing here. Either works though!

milesingrams avatar Mar 18 '25 17:03 milesingrams

Also this Issue: https://github.com/facebook/hermes/issues/1519

milesingrams avatar Mar 18 '25 17:03 milesingrams

πŸ₯‡

WonKimGoRevel avatar Mar 18 '25 17:03 WonKimGoRevel

Holy smokes he solved it !

gabrielavoll avatar Mar 18 '25 17:03 gabrielavoll

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

sherikovic avatar Mar 23 '25 18:03 sherikovic

looks like this should fix https://github.com/iamkun/dayjs/issues/1377.

dlebedynskyi avatar Apr 22 '25 18:04 dlebedynskyi

@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!

anton-patrushev avatar Apr 23 '25 10:04 anton-patrushev

This is great!!!!! @milesingrams πŸš€

Coming here from @dlebedynskyi mention of this fix in https://github.com/iamkun/dayjs/issues/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!

kleviss avatar Apr 25 '25 21:04 kleviss

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

konradjg avatar Apr 30 '25 05:04 konradjg

@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 https://github.com/facebook/hermes/issues/1519#issuecomment-2350062331 - For now I just went ahead with the ployfills suggested in https://github.com/iamkun/dayjs/issues/1377#issuecomment-2831492964 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. https://github.com/facebook/hermes/issues/930 or https://github.com/facebook/hermes/issues/495 or hermes_very_slow_compared_to_jsc_with_big_data

kleviss avatar Apr 30 '25 08:04 kleviss