Search code examples
javascriptnode.jsreactjsnext.jsvercel

The server and client components in Vercel Next JS have different timezones


In my Next.js 13.2.4 application, I have a helper function called getLocalTime(date) that returns the local time of the client machine in a specific format.

//Output format: 9:30PM
export function getLocalTime(date) {

  const localTime = new Date(date).toLocaleTimeString("en-US", {
    hour: "numeric",
    minute: "numeric",
    hour12: true,
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
  });

  return localTime;
}

When I run the application locally using npm run dev, the function returns the correct time relative to my local time. However, when I deployed the application to Vercel, I noticed that the server components are using the UTC timezone, while the client components are using the actual timezone of the user.

So I tried to hardcode the timezone like this.

//Output format: 9:30PM
export function getLocalTime(date) {
  const BucharestTimezone = "Europe/Bucharest";

  const localTime = new Date(date).toLocaleTimeString("en-US", {
    hour: "numeric",
    minute: "numeric",
    hour12: true,
    timezone: BucharestTimezone,
  });

  return localTime;
}

But the problem stayed the same.

My question is: how can I make sure that the server components in Next.js use the timezone of the client machine, rather than UTC?


Solution

  • I managed to solve this problem by using Luxon or date-fns-tz libraries.

    In the end, I opted to use date-fns-tz since it requires less code refactoring for me.

    Solution 1: using date-fns-tz

    import { utcToZonedTime } from "date-fns-tz";
        
    export function getLocalTime(date) {
          const localTime = utcToZonedTime(
            new Date(date),
            "Europe/Bucharest"
          ).toLocaleTimeString("en-US", {
            hour: "numeric",
            minute: "numeric",
            hour12: true,
          });
        
      return localTime;  //Output format: 9:30 PM
    }
    

    here I used utcToZonedTime to convert the time to UTC for both the client and server components, then for its second argument I would specify a timezone I would like the time to be in. ex: Europe/Bucharest

    Solution 2: using Luxon

    import { DateTime } from "luxon";
    
    export function getLocalTime(date) {
     
      const localTime =  DateTime.fromISO(date, { zone: "utc" }).setZone(
        "Europe/Bucharest"
      ).toFormat("h:mm a");
    
      return localTime; //Output format: 9:30 PM
    }