All files / packages/app/hooks use-format.ts

83.33% Statements 10/12
100% Branches 5/5
66.66% Functions 4/6
83.33% Lines 10/12

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                  183x 5976x 5976x 5976x 5976x 5976x 5976x           5976x   5657x                     186x                      
import * as React from "react";
 
import { useBooleanState } from "~app/hooks/use-boolean-state";
import { useLocale } from "~app/hooks/use-locale";
import { useMountEffect } from "~app/hooks/use-mount-effect";
import { useSsrValue } from "~app/hooks/use-ssr-value";
import { TIMEZONE_STORE_NAME } from "~app/utils/store/timezone";
import type { TemporalMapping } from "~utils/temporal";
 
export const useFormat = () => {
	const [timezone, localTimezone] = useSsrValue(TIMEZONE_STORE_NAME);
	const [isMounted, { setTrue: setMounted }] = useBooleanState();
	useMountEffect(setMounted);
	const effectiveTimezone = isMounted ? localTimezone : timezone;
	const locale = useLocale();
	return React.useMemo<{
		[K in keyof TemporalMapping as `format${Capitalize<K>}`]: (
			date: TemporalMapping[K],
			options?: Intl.DateTimeFormatOptions,
		) => string;
	}>(
		() => ({
			formatPlainDate: (date, options) =>
				date.toLocaleString(locale, { dateStyle: "medium", ...options }),
			formatPlainTime: (date, options) =>
				date.toLocaleString(locale, { timeStyle: "short", ...options }),
			formatPlainDateTime: (date, options) =>
				date.toLocaleString(locale, {
					dateStyle: "medium",
					timeStyle: "short",
					...options,
				}),
			// `ZonedDateTime` carries its own time zone, so convert instead
			formatZonedDateTime: (date, { timeZone, ...rest } = {}) =>
				date
					.withTimeZone(timeZone ?? effectiveTimezone)
					.toLocaleString(locale, {
						dateStyle: "medium",
						timeStyle: "short",
						...rest,
					}),
		}),
		[effectiveTimezone, locale],
	);
};