How do I get the number of milliseconds to the next day of the local timezone using date-fns-tz?

235 Views Asked by At

Similar to Incrementing a date in JavaScript but I am looking for the number of milliseconds to the next day given a timezone.

This is so that I can trigger a subscription or React state change when the local time reaches midnight.

The function signature would be

function millisecondsBeforeNextDay(now: number| Date, timeZone: string) : number {
    
}

and used like

export function useDayClockState(): Date {
    const defaultCalendar = Localization.getCalendars()[0];
    const now =  useClockState(24 * 60 * 60 * 1000, millisecondsBeforeNextDay(Date.now(), defaultCalendar.timeZone!));
    return now;
}

It needs one caveat though, it should not return 24 hours. But 0 if the current instant is midnight.

2

There are 2 best solutions below

0
On
/**
 *
 * @param now now in UTC
 * @param timeZone time zone
 */
export function millisecondsBeforeNextDay(
  now: number | Date,
  timeZone: string
): number {
  const nowAtZone = utcToZonedTime(now, timeZone);
  const diff = differenceInMilliseconds(
    addDays(startOfDay(nowAtZone), 1),
    nowAtZone
  );
  return diff === 86400000 ? 0 : diff;
}

And tested as

import { parseISO } from "date-fns";
import { zonedTimeToUtc } from "date-fns-tz";
import { millisecondsBeforeNextDay } from "./useDayClockState";

it("23:59:00.000 should be 60000", () => {
  const specimen = zonedTimeToUtc(
    parseISO("2022-01-01T23:59:00.000"),
    "America/Toronto"
  );
  expect(millisecondsBeforeNextDay(specimen, "America/Toronto")).toBe(60000);
});

it("00:00:00.000 should be 0", () => {
  const specimen = zonedTimeToUtc(
    parseISO("2022-01-01T00:00:00.000"),
    "America/Toronto"
  );
  expect(millisecondsBeforeNextDay(specimen, "America/Toronto")).toBe(0);
});
0
On

Create a dateTime object, set it to 0. and subtract the time from that obect.

function millisecondsBeforeNextDay(now: number| Date, timeZone: string) : number {
  const date = new Date(now);
  date.setTimeZone(timeZone);
  date.setHours(0, 0, 0, 0);
  return date.getTime() - now;
}