Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 681x 681x 27x 27x 681x 27x 27x 27x | import { TZDate } from "@date-fns/tz";
import { TIMEZONE } from "shared/utils/timezone";
const HOUR_MS = 60 * 60 * 1000;
// Whether an instant lands on exactly this wall-clock hour in the event timezone.
// Converting a known instant into a timezone is unambiguous, so this is the same
// answer on every host.
const rendersAtWallClockHour = (
instant: Date,
year: number,
month: number,
day: number,
hour: number,
): boolean => {
const zoned = new TZDate(instant, TIMEZONE);
return (
zoned.getFullYear() === year &&
zoned.getMonth() === month &&
zoned.getDate() === day &&
zoned.getHours() === hour
);
};
// The instant at a given wall-clock hour in the event timezone.
//
// The hour the autumn transition repeats occurs twice, and which of the two the
// TZDate constructor lands on depends on the host's own timezone - so a UTC
// server and a Finnish browser would disagree by an hour about the same
// configured time. The first occurrence is picked explicitly here, which is the
// same answer everywhere.
//
// The hour the spring transition skips does not exist at all; that resolves
// forward, to the same instant the wall clock an hour later would give.
export const atWallClockHourInEventTimezone = (
year: number,
month: number,
day: number,
hour: number,
): Date => {
const candidate = new TZDate(year, month, day, hour, 0, 0, TIMEZONE);
const hourEarlier = new Date(candidate.getTime() - HOUR_MS);
// Rendering the same wall clock an hour earlier means the constructor landed
// on the second occurrence of a repeated hour
return rendersAtWallClockHour(hourEarlier, year, month, day, hour)
? hourEarlier
: new Date(candidate);
};
|