DEV Community

Cover image for A timezone problem on react-native-paper-date (1day-off)
vatana7
vatana7

Posted on • Updated on

A timezone problem on react-native-paper-date (1day-off)

Today problem is that I encountered an issue while using react-native-paper-dates and the weekdays appear on the Calendar Modal was not correct. It was off by 1 day, for example today is 15th July 2024 and the 15th was supposed to appear on Monday column but instead it was on the Sunday column instead.

Eventually I figure out that the problem had something to do with Intl.DateTimeFormat because I’ve tried running the below code on 2 environment; mine and a Javascript runtime on Mozilla.dev (I know it’s so silly but I tried lol).

console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
//"UTC" on my local development env
//"Asia/Phnom_Penh" on Mozilla.dev
Enter fullscreen mode Exit fullscreen mode

Now I got my clue, so I whine to my co-worker and he mentioned that Javascript’s Intl isn’t stable for our app. So he sent me this formatjs link here that mentioned Javascript’s Engine does not expose default timezone so there’s no way to get default timezone from it; and our React native app is using Hermes Engine, which I assume it doesn’t expose anything about timezone to Javascript’s Intl so that’s why it always default to “UTC” when I try to run console.log(Intl.DateTimeFormat().resolvedOptions().timeZone) .

Now that I got my answer; I simply try the code below and the issue is resolved. By having a proper timezone, the weekdays are now correct on every column on the Calendar Modal.

import '@formatjs/intl-datetimeformat/polyfill'
import '@formatjs/intl-datetimeformat/add-all-tz.js'

//If this statement doesn't work, use expo-localization's getCalendar()
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone

if ('__setDefaultTimeZone' in Intl.DateTimeFormat) {
  Intl.DateTimeFormat.__setDefaultTimeZone('America/Los_Angeles')
}

//For my case, I have to use expo-localization
const timezone = Localization.getCalendars()[0].timezone
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
fawwazalkarmy profile image
Fawwaz Alkarmy

I'm having the same issue with react-native-paper-dates the day on the calendar is always 1 day off, i tried to implement your solution but it always gives me this error (Cannot read property 'prototype' of undefined, js engine: hermes)
this is my entry file code where i used it, if you could help with the exact steps i need to follow or if i'm missing something

import "@formatjs/intl-datetimeformat/polyfill";
import "@formatjs/intl-datetimeformat/add-all-tz";
import { getCalendars } from "expo-localization";
import React, { useCallback, useEffect } from "react";
import { PaperProvider } from "react-native-paper";
import {
  SafeAreaProvider,
  initialWindowMetrics,
} from "react-native-safe-area-context";
import Root from "./src/navigation/root/Root";
import { StatusBar } from "expo-status-bar";
import { useCustomFonts } from "./src/hooks/helpers/useCustomFonts";
import { Provider } from "react-redux";
import { persister, store } from "./src/redux/store";
import { PersistGate } from "redux-persist/integration/react";
import ToastManager from "toastify-react-native";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { GlobalStyle } from "./src/styles/globalStyles";
import { useAppSelector } from "./src/hooks/redux/reduxHook";
import { pxHp } from "./src/utilities/layout";
import { darkTheme, lightTheme, pinkTheme } from "./src/styles/themes/themes";
import { View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { I18nextProvider } from "react-i18next";
import i18n from "./src/locale/config";
import * as SplashScreen from "expo-splash-screen";
import useGoogleSignIn from "./src/hooks/helpers/useGoogleSignIn";
import useRtl from "./src/hooks/helpers/useRtl";
import * as Linking from "expo-linking";

const queryClient: QueryClient = new QueryClient();

function AppContent() {
  const { timeZone } = getCalendars()[0];

  const appActiveTheme = useAppSelector((state) => state.app.appActiveTheme);

  useGoogleSignIn();
  useRtl();

  const url = Linking.useURL();

  if (url) {
    const { hostname, path, queryParams } = Linking.parse(url);

    console.log(
      `Linked to app with hostname: ${hostname}, path: ${path} and data: ${JSON.stringify(
        queryParams
      )}`
    );
  }

  const paperTheme =
    appActiveTheme === "Light"
      ? { ...lightTheme }
      : appActiveTheme === "Dark"
      ? { ...darkTheme }
      : { ...pinkTheme };

  const globalStyle = GlobalStyle(paperTheme);

  useEffect(() => {
    if ("__setDefaultTimeZone" in Intl.DateTimeFormat) {
      //@ts-ignore
      Intl.DateTimeFormat.__setDefaultTimeZone(timeZone);
    }
  }, [timeZone]);

  return (
    <GestureHandlerRootView>
      <PaperProvider theme={paperTheme}>
        <SafeAreaProvider initialMetrics={initialWindowMetrics}>
          <StatusBar animated backgroundColor={"#000"} />
          <QueryClientProvider client={queryClient}>
            <Root />
          </QueryClientProvider>
        </SafeAreaProvider>

        <ToastManager
          textStyle={globalStyle.toastText}
          position="center"
          style={{ minHeight: pxHp(90), maxHeight: "auto" }}
        />
      </PaperProvider>
    </GestureHandlerRootView>
  );
}

SplashScreen.preventAutoHideAsync();

export default function App() {
  const { fontsLoaded } = useCustomFonts();

  const onLayoutRootView = useCallback(async () => {
    if (fontsLoaded) {
      await SplashScreen.hideAsync();
    }
  }, [fontsLoaded]);

  if (!fontsLoaded) {
    return null;
  }

  return (
    <Provider store={store}>
      <PersistGate persistor={persister} loading={<></>}>
        <View style={{ flex: 1 }} onLayout={onLayoutRootView}>
          <I18nextProvider i18n={i18n}>
            <AppContent />
          </I18nextProvider>
        </View>
      </PersistGate>
    </Provider>
  );
}

Enter fullscreen mode Exit fullscreen mode
Collapse
 
vatana7 profile image
vatana7 • Edited

Maybe you can try to set up Expo properly or something? I don't seem to encounter that error message of yours.