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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | 608x 6119x 6119x 3297x 289x 15x 662x 23981x 634x 23936x 6x 103x 2823x 459x | import { useMemo, useSyncExternalStore } from "react";
import { getLocaleSnapshot, subscribeToLocale } from "shared/utils/setLocale";
import {
Time,
formatProgramItemDuration,
formatRelativeTime,
formattedCurrentTime,
getDate,
getDateAndTime,
getLocalDateAndTime,
getLocalTimezone,
getShortDate,
getShortWeekdayAndTime,
getTime,
getTimezone,
getWeekdayAndTime,
} from "shared/utils/timeFormatter";
import {
getFormattedInterval,
getFormattedTime,
} from "client/views/program-item/programItemUtils";
// The formatters, bound to the language the UI is currently in. Components take
// them from here rather than importing them directly, which a lint rule
// enforces: the active language lives in module state, which React cannot see,
// so a component formatting a time has nothing to re-render or recompute on when
// the language changes and keeps the string it first produced.
//
// Binding them here gives that dependency a place to live. The returned
// functions get a new identity on a switch, which invalidates every memoized
// expression that calls one, so call sites read exactly as they would if the
// language were not a concern at all.
export const useTimeFormatters = (): TimeFormatters => {
const locale = useSyncExternalStore(subscribeToLocale, getLocaleSnapshot);
return useMemo(
() => ({
getWeekdayAndTime: (time: Time) => getWeekdayAndTime(time, locale),
getDateAndTime: (time: Time) => getDateAndTime(time, locale),
getTime: (time: Time) => getTime(time, locale),
getShortWeekdayAndTime: (time: Time) =>
getShortWeekdayAndTime(time, locale),
getShortDate: (time: Time) => getShortDate(time, locale),
getDate: (time: Time) => getDate(time, locale),
getTimezone: (time: Time) => getTimezone(time, locale),
getLocalDateAndTime: (time: Time) => getLocalDateAndTime(time, locale),
getLocalTimezone: (time: Time) => getLocalTimezone(time, locale),
formattedCurrentTime: (currentTime: Date) =>
formattedCurrentTime(currentTime, locale),
formatRelativeTime: (from: Date, to: Date) =>
formatRelativeTime(from, to, locale),
// Carries no language of its own, and is here so that nothing in the
// client has a reason to reach for the formatter module directly
formatProgramItemDuration,
getFormattedTime: (time: Date, timeNow: Date) =>
getFormattedTime(time, timeNow, locale),
getFormattedInterval: (startTime: Date, endTime: Date, timeNow: Date) =>
getFormattedInterval(startTime, endTime, timeNow, locale),
}),
[locale],
);
};
interface TimeFormatters {
getWeekdayAndTime: (time: Time) => string;
getDateAndTime: (time: Time) => string;
getTime: (time: Time) => string;
getShortWeekdayAndTime: (time: Time) => string;
getShortDate: (time: Time) => string;
getDate: (time: Time) => string;
getTimezone: (time: Time) => string;
getLocalDateAndTime: (time: Time) => string;
getLocalTimezone: (time: Time) => string;
formattedCurrentTime: (currentTime: Date) => string;
formatRelativeTime: (from: Date, to: Date) => string;
formatProgramItemDuration: (mins: number) => string;
getFormattedTime: (time: Date, timeNow: Date) => string;
getFormattedInterval: (
startTime: Date,
endTime: Date,
timeNow: Date,
) => string;
}
|