facebook / hermes

A JavaScript engine optimized for running React Native.
https://hermesengine.dev/
MIT License
9.68k stars 618 forks source link

Date getTime unexpected result #1491

Open alwex opened 3 weeks ago

alwex commented 3 weeks ago

Bug Description

There is a discrepency between how Hermes compute dates and how chrome V8 does it. The following code does not provide the same result: Code:

const testDate = new Date(0)
console.log('=====>', testDate.getTime())
testDate.setSeconds(0)
console.log('=====>', testDate.getTime())

Output with hermes:

image

Output in chrome console:

image

Hermes git revision (if applicable): React Native version: 0.74.0 OS: ios and android Platform (most likely one of arm64-v8a, armeabi-v7a, x86, x86_64):

Steps To Reproduce

NA

code example:

const testDate = new Date(0)
console.log('=====>', testDate.getTime())
testDate.setSeconds(0)
console.log('=====>', testDate.getTime())

The Expected Behavior

getTime should return 0

tmikov commented 3 weeks ago

Hi, can you reproduce this with the CLI? I just ran this in the Hermes CLI and it worked as expected:

$ cat date.js
const testDate = new Date(0)
print('=====>', testDate.getTime())
testDate.setSeconds(0)
print('=====>', testDate.getTime())

$ hermes date.js
=====> 0
=====> 0

It may be caused by polyfills that are active in your code. Also, what timezone are you using?

shubhamguptadream11 commented 3 weeks ago

I also tried with Hermes CLI it's not reproducible.

lavenzg commented 2 weeks ago

I can't reproduce it either. Could you provide the timezone? Or TZ environment variable if you ever set that.

alwex commented 2 weeks ago

Timezone is Pacific/Auckland

I reproduced with an expo project (expo@51.0.16):

  const testDate = new Date(0)
  console.log('=====>', testDate.getTime())
  testDate.setSeconds(0)
  console.log('=====>', testDate.getTime())

output

 LOG  =====> 0
 LOG  =====> -3600000

output of npx react-native info

System:
  OS: macOS 14.6.1
  CPU: (10) arm64 Apple M1 Pro
  Memory: 190.42 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.9.0
    path: ~/.nvm/versions/node/v20.9.0/bin/node
  Yarn:
    version: 1.22.19
    path: ~/.yarn/bin/yarn
  npm:
    version: 10.1.0
    path: ~/.nvm/versions/node/v20.9.0/bin/npm
  Watchman:
    version: 2024.06.24.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /Users/alexandre/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.4
      - iOS 17.4
      - macOS 14.4
      - tvOS 17.4
      - visionOS 1.1
      - watchOS 10.4
  Android SDK: Not Found
IDEs:
  Android Studio: 2022.1 AI-221.6008.13.2211.9514443
  Xcode:
    version: 15.3/15E204a
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.11
    path: /Users/alexandre/.jenv/shims/javac
  Ruby:
    version: 2.7.6
    path: /Users/alexandre/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.74.2
    wanted: 0.74.2
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

hermes engine used (from pod install):

hermes-engine (0.74.2)

dependencies from package.json

  "dependencies": {
    "@config-plugins/react-native-blob-util": "^8.0.0",
    "@config-plugins/react-native-pdf": "^8.0.0",
    "@expo/vector-icons": "^14.0.2",
    "@react-native-community/slider": "^4.5.2",
    "@react-native-firebase/analytics": "^20.1.0",
    "@react-native-firebase/app": "^20.1.0",
    "@react-native-firebase/crashlytics": "^20.1.0",
    "@react-navigation/native": "^6.0.2",
    "@realm/react": "^0.8.0",
    "@sentry/react-native": "~5.22.0",
    "@shopify/flash-list": "^1.7.1",
    "@shopify/react-native-skia": "^1.3.7",
    "@shopify/restyle": "^2.4.4",
    "date-fns": "^3.6.0",
    "dot-object": "^2.1.5",
    "expo": "~51.0.16",
    "expo-application": "~5.9.1",
    "expo-build-properties": "~0.12.3",
    "expo-clipboard": "~6.0.3",
    "expo-constants": "~16.0.2",
    "expo-dev-client": "~4.0.19",
    "expo-device": "~6.0.2",
    "expo-document-picker": "~12.0.2",
    "expo-file-system": "~17.0.1",
    "expo-font": "~12.0.7",
    "expo-image": "~1.12.12",
    "expo-keep-awake": "~13.0.2",
    "expo-linear-gradient": "~13.0.2",
    "expo-linking": "~6.3.1",
    "expo-local-authentication": "~14.0.1",
    "expo-localization": "~15.0.3",
    "expo-router": "~3.5.17",
    "expo-splash-screen": "~0.27.5",
    "expo-status-bar": "~1.12.1",
    "expo-system-ui": "~3.0.6",
    "expo-web-browser": "~13.0.3",
    "html-to-text": "^9.0.5",
    "i18next": "^23.12.1",
    "intl-pluralrules": "^2.0.1",
    "lodash": "^4.17.21",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-hook-form": "^7.52.0",
    "react-i18next": "^14.1.2",
    "react-native": "0.74.2",
    "react-native-blob-util": "^0.19.9",
    "react-native-color-matrix-image-filters": "^7.0.1",
    "react-native-drag-sort": "^2.4.4",
    "react-native-gesture-handler": "~2.16.1",
    "react-native-get-random-values": "^1.11.0",
    "react-native-mmkv": "^2.12.2",
    "react-native-paper": "^5.12.3",
    "react-native-pdf": "^6.7.5",
    "react-native-pdf-helpers": "^1.2.1",
    "react-native-pdf-page-image": "^0.1.7",
    "react-native-purchases": "^7.27.4",
    "react-native-purchases-ui": "^7.27.4",
    "react-native-reanimated": "~3.10.1",
    "react-native-redash": "^18.1.3",
    "react-native-root-toast": "^3.6.0",
    "react-native-safe-area-context": "^4.10.7",
    "react-native-screens": "3.31.1",
    "react-native-svg": "^15.3.0",
    "react-native-svg-transformer": "^1.4.0",
    "react-native-web": "~0.19.10",
    "react-native-zip-archive": "^7.0.0",
    "react-native-zoom-toolkit": "^2.1.4",
    "realm": "^12.11.1",
    "recoil": "^0.7.7"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@types/dot-object": "^2.1.6",
    "@types/jest": "^29.5.12",
    "@types/lodash": "^4.17.6",
    "@types/react": "~18.2.45",
    "@types/react-test-renderer": "^18.0.7",
    "jest": "^29.2.1",
    "jest-expo": "~51.0.3",
    "react-test-renderer": "18.2.0",
    "typescript": "~5.3.3"
  },
alwex commented 2 weeks ago

I reproduced using latest hermes release https://github.com/facebook/hermes/releases/download/v0.13.0/hermes-cli-darwin.tar.gz

script file:

const d = new Date(0)
d.setSeconds(0)
print(d.getTime())
➜  hermes-cli-darwin ./hermes script.js
-3600000

this is running on a Apple M1 Pro OS version 14.6.1

lavenzg commented 2 weeks ago

Thanks! I can reproduce with that timezone. We'll look into it.

lavenzg commented 5 days ago

I looked into it. The issue is that when we are computing UTC time from local time, we are offseting -1 hour to get the DST (this trick works really well in most cases). This results in a negative epoch value and an equivalent time is used, which has different DST (Auckland does not have DST transition in 1960-1973).

One solution is that we don't compute equivalent time on Linux/MacOS (AFAIK only Windows CRT can't handle negative time value), and finding alternative on Windows (it seems even Win32 API has issue handling this case).