Files
cinny/src/app/hooks/useLocalTime.ts
T

60 lines
1.5 KiB
TypeScript
Raw Normal View History

import { useCallback, useEffect, useState } from 'react';
function formatLocalTime(timezone: string, hour12: boolean): string | undefined {
try {
return new Intl.DateTimeFormat('en', {
timeZone: timezone,
hour: 'numeric',
minute: '2-digit',
hour12,
}).format(new Date());
} catch {
return undefined;
}
}
function getTimezoneAbbr(timezone: string): string | undefined {
try {
return new Intl.DateTimeFormat('en', {
timeZone: timezone,
timeZoneName: 'short',
})
.formatToParts(new Date())
.find((p) => p.type === 'timeZoneName')?.value;
} catch {
return undefined;
}
}
export type LocalTimeInfo = {
time: string;
abbr: string | undefined;
};
/**
* Returns the current time (and timezone abbreviation) in the given IANA
* timezone, updated every minute. Returns undefined when timezone is
* undefined or invalid.
*/
export function useLocalTime(
timezone: string | undefined,
hour12: boolean = true,
): LocalTimeInfo | undefined {
const compute = useCallback((): LocalTimeInfo | undefined => {
if (!timezone) return undefined;
const time = formatLocalTime(timezone, hour12);
if (!time) return undefined;
return { time, abbr: getTimezoneAbbr(timezone) };
}, [timezone, hour12]);
const [info, setInfo] = useState<LocalTimeInfo | undefined>(compute);
useEffect(() => {
setInfo(compute());
const id = window.setInterval(() => setInfo(compute()), 60_000);
return () => window.clearInterval(id);
}, [compute]);
return info;
}