a tool for shared writing and social publishing
at main 2.1 kB view raw
1"use client"; 2import { useContext, useMemo } from "react"; 3import { DateTime } from "luxon"; 4import { RequestHeadersContext } from "components/Providers/RequestHeadersProvider"; 5import { useHasPageLoaded } from "components/InitialPageLoadProvider"; 6 7/** 8 * Hook that formats a date string using Luxon with timezone and locale from request headers. 9 * On initial page load, uses the timezone from request headers. After hydration, uses the system timezone. 10 * 11 * @param dateString - ISO date string to format 12 * @param options - Intl.DateTimeFormatOptions for formatting 13 * @returns Formatted date string 14 * 15 * @example 16 * const formatted = useLocalizedDate("2024-01-15T10:30:00Z", { dateStyle: 'full', timeStyle: 'short' }); 17 */ 18export function useLocalizedDate( 19 dateString: string, 20 options?: Intl.DateTimeFormatOptions, 21): string { 22 const { timezone, language } = useContext(RequestHeadersContext); 23 const hasPageLoaded = useHasPageLoaded(); 24 25 return useMemo(() => { 26 // Parse the date string to Luxon DateTime 27 let dateTime = DateTime.fromISO(dateString); 28 29 // On initial page load, use header timezone. After hydration, use system timezone 30 const effectiveTimezone = !hasPageLoaded 31 ? timezone || "UTC" 32 : Intl.DateTimeFormat().resolvedOptions().timeZone; 33 34 console.log("tz", effectiveTimezone); 35 36 // Apply timezone if available 37 if (effectiveTimezone) { 38 dateTime = dateTime.setZone(effectiveTimezone); 39 } 40 41 // On initial page load, use header locale. After hydration, use system locale 42 // Parse locale from accept-language header (take first locale) 43 // accept-language format: "en-US,en;q=0.9,es;q=0.8" 44 const effectiveLocale = !hasPageLoaded 45 ? language?.split(",")[0]?.split(";")[0]?.trim() || "en-US" 46 : Intl.DateTimeFormat().resolvedOptions().locale; 47 48 try { 49 return dateTime.toLocaleString(options, { locale: effectiveLocale }); 50 } catch (error) { 51 // Fallback to en-US if locale is invalid 52 return dateTime.toLocaleString(options, { locale: "en-US" }); 53 } 54 }, [dateString, options, timezone, language, hasPageLoaded]); 55}