Timezone Handling
The Ellemment Stack provides robust timezone handling through client hints, ensuring accurate time display across server and client rendering.
Implementation
Server-Side Usage
Access timezone information in server code:
// In your loader import { getHints } from '#app/utils/client-hints' ,[object Object],
const formattedDate = getDateTimeFormat(timeZone).format(date) return json({ formattedDate }) }
Client-Side Usage
Access timezone information in components:
import { useHints } from '#app/utils/client-hints' ,[object Object],
return <time dateTime={date.toISOString()}> {formatter.format(date)} </time> }
DateTimeFormat Utility
The built-in getDateTimeFormat
utility provides consistent formatting:
import { getDateTimeFormat } from '#app/utils/misc.server'
function formatDateTime(date: Date, request: Request) { const hints = getHints(request) const formatter = getDateTimeFormat(hints.timeZone) return formatter.format(date) }
Best Practices
Date Storage
// Always store dates in UTC const storedDate = new Date().toISOString()
// Convert to user timezone for display const displayDate = format(parseISO(storedDate), 'PPpp', { timeZone: hints.timeZone })
Format Consistency
const dateFormatters = { short: getDateTimeFormat(timeZone, { dateStyle: 'short', timeStyle: 'short' }), full: getDateTimeFormat(timeZone, { dateStyle: 'full', timeStyle: 'long' }), date: getDateTimeFormat(timeZone, { dateStyle: 'medium' }), time: getDateTimeFormat(timeZone, { timeStyle: 'short' }) }
Relative Times
function RelativeTime({ date }: { date: Date }) { const hints = useHints() const formatter = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' })
// Implementation of relative time logic return <time dateTime={date.toISOString()}> {/* Formatted relative time */} </time> }
Error Handling
function safeDateFormat(date: Date, timeZone: string) { try { return new Intl.DateTimeFormat(undefined, { timeZone }).format(date) } catch (error) { console.error(`Invalid timezone: ${timeZone}`) return new Intl.DateTimeFormat(undefined, { timeZone: 'UTC' }).format(date) } }
Performance Considerations
Caching Formatters
const formatterCache = new Map<string, Intl.DateTimeFormat>()
function getCachedFormatter(timeZone: string) { const key = ,[object Object], if (!formatterCache.has(key)) { formatterCache.set( key, new Intl.DateTimeFormat(undefined, { timeZone }) ) } return formatterCache.get(key)! }
Batch Processing
function batchFormatDates(dates: Date[], timeZone: string) { const formatter = getCachedFormatter(timeZone) return dates.map(date => formatter.format(date)) }
For more information about client hints, see the client hints documentation. For performance considerations, refer to the performance documentation.