skip to Main Content

Let’s suppose i have a user who submitted a date in database like this: 2023-04-11T14:50||America/Managua. How may i be able to display the date that is coming from database based on each user’s timezone. Knowing that i already know its timezone.
I am using Javascript and React. This is my submit function.

  const handleOnBlur = useCallback(async (e, dirty) => {
  e.preventDefault();

  if (dirty) {
   if (test?.timeZone) {
    console.log(test.timeZone);
    const dateWithTimeZone = new Date(e.target.value); // Date object with local timezone
    const dateWithUTC = dateWithTimeZone.toISOString();
  
    await formValueSubmit(`${dateWithUTC}||${test.timeZone}`);
  } else {
  console.log('Timezone not available');
  }
 }
 }, [formValueSubmit, test]);

2

Answers


  1. You will need to calculate the offset based on the stored time zone to get the UTC date. Now, you can format the date in a user’s local timezone.

    The America/Managua timezone has an offset of -6:00 hours or -360 minutes. The getOffset function below correctly calculates -360 as the offset. It is the same offset as Central Standard Time (CST).

    Note: Usually we add the offset to the date, but since we are parsing a stored time-zoned date, we need to subtract the offset. In this case, we are adding 360 minutes to the Zulu date.

    It does not require any additional libraries. It uses built-in Intl.DateTimeFormat library.

    // Source: https://stackoverflow.com/a/68593283/1762224
    const getOffset = (timeZone = 'UTC', date = new Date()) => {
      const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' }));
      const tzDate = new Date(date.toLocaleString('en-US', { timeZone }));
      return (tzDate.getTime() - utcDate.getTime()) / 6e4;
    };
    
    // Process timestamp into a date and calculate offset
    const parseZonedTimestamp = (zonedTimestamp, izZulu = false) => {
      const [timestamp, timeZone] = zonedTimestamp.split('||');
      const date = new Date(timestamp + (!izZulu ? ':00Z' : ''));
      const offset = getOffset(timeZone, date);
      date.setUTCMinutes(date.getUTCMinutes() - offset); // Restore date
      return date;
    };
    
    const response = '2023-04-11T14:50||America/Managua'; // 2:50 PM (CST)
    const date = parseZonedTimestamp(response);
    
    const formatOptions = {
      weekday: 'long', year: 'numeric', month: 'long', day: '2-digit',
      hour: '2-digit', minute: '2-digit', second: '2-digit',
      timeZoneName: 'long'
    };
    
    // Tuesday, April 11, 2023 at 02:50:00 PM Central Standard Time
    console.log(date.toLocaleString('en-US', {
      ...formatOptions,
      timeZone: 'America/Managua'
    }));
    
    // Tuesday, April 11, 2023 at 01:50:00 PM Pacific Daylight Time
    console.log(date.toLocaleString('en-US', {
      ...formatOptions,
      timeZone: 'America/Los_Angeles'
    }));
    
    // Tuesday, April 11, 2023 at 08:50:00 PM Coordinated Universal Time
    console.log(date.toLocaleString('en-US', {
      ...formatOptions,
      timeZone: 'UTC'
    }));

    Output

    Tuesday, April 11, 2023 at 02:50:00 PM Central Standard Time
    Tuesday, April 11, 2023 at 01:50:00 PM Pacific Daylight Time
    Tuesday, April 11, 2023 at 08:50:00 PM Coordinated Universal Time
    
    Login or Signup to reply.
  2. As pointed out here, Javascript is able to convert from UTC to date and time for a given time zone, but not vice versa. You can use a date/time library for that or a "bisection method" like the following.

    The stringify function uses the Hungarian locale to produce the format YYYY. MM. DD. HH:MM:SS, which can be lexicographically compared to the given local time.

    function stringify(date, timeZone) {
      return date.toLocaleString("hu", {timeZone, dateStyle: "short", timeStyle: "medium"})
        .replace(/ (d):/, " 0$1:");
    }
    function parseTime(localTime, timeZone) {
      var x = Math.floor(new Date(localTime.substring(0, 10)) / 1000) - 86400;
      var y = x + 2 * 86400;
      localTime = stringify(new Date(localTime));
      for (; ;) {
        var m = Math.floor((x + y) / 2);
        if (m === x) return new Date(m * 1000);
        else if (stringify(new Date(m * 1000), timeZone) <= localTime) x = m;
        else y = m;
      }
    }
    console.log(parseTime("2023-04-11T14:50", "America/Managua"),
                parseTime("2023-03-12T08:00", "America/Los_Angeles"),
                parseTime("2023-03-26T02:30", "Europe/Berlin"));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search