web/src/utils/timezone.js
Rama main · réplica de lectura del repositorio original.
import { format as formatDate } from 'date-fns'
import { formatInTimeZone, toZonedTime } from 'date-fns-tz'
// Curated list of common timezones with friendly labels
export const TIMEZONE_OPTIONS = [
{ value: 'America/New_York', label: '(UTC-05:00) Eastern Time' },
{ value: 'America/Chicago', label: '(UTC-06:00) Central Time' },
{ value: 'America/Denver', label: '(UTC-07:00) Mountain Time' },
{ value: 'America/Los_Angeles', label: '(UTC-08:00) Pacific Time' },
{ value: 'America/Anchorage', label: '(UTC-09:00) Alaska' },
{ value: 'Pacific/Honolulu', label: '(UTC-10:00) Hawaii' },
{ value: 'Europe/London', label: '(UTC+00:00) London' },
{ value: 'Europe/Paris', label: '(UTC+01:00) Paris, Berlin' },
{ value: 'Europe/Moscow', label: '(UTC+03:00) Moscow' },
{ value: 'Asia/Dubai', label: '(UTC+04:00) Dubai' },
{ value: 'Asia/Kolkata', label: '(UTC+05:30) India' },
{ value: 'Asia/Singapore', label: '(UTC+08:00) Singapore' },
{ value: 'Asia/Tokyo', label: '(UTC+09:00) Tokyo' },
{ value: 'Australia/Sydney', label: '(UTC+10:00) Sydney' },
{ value: 'Pacific/Auckland', label: '(UTC+12:00) Auckland' },
{ value: 'UTC', label: '(UTC+00:00) UTC' },
]
/**
* Get the browser's detected timezone
* @returns {string} IANA timezone identifier
*/
export function getBrowserTimezone() {
try {
return Intl.DateTimeFormat().resolvedOptions().timeZone
} catch (e) {
console.warn('Could not detect browser timezone:', e)
return 'America/New_York'
}
}
/**
* Check if a timezone is in our curated list
* @param {string} timezone - IANA timezone identifier
* @returns {boolean}
*/
export function isTimezoneInList(timezone) {
return TIMEZONE_OPTIONS.some(opt => opt.value === timezone)
}
/**
* Get timezone options including browser timezone if not in list
* @returns {Array} Array of timezone options
*/
export function getTimezoneOptions() {
const browserTz = getBrowserTimezone()
if (isTimezoneInList(browserTz)) {
return TIMEZONE_OPTIONS
}
// Add browser timezone at the top if not in curated list
return [
{ value: browserTz, label: `(Browser) ${browserTz}` },
...TIMEZONE_OPTIONS
]
}
/**
* Format a date in a specific timezone
* @param {Date|string} date - Date to format
* @param {string} timezone - IANA timezone identifier
* @param {string} formatStr - date-fns format string (default: 'MMM d, yyyy')
* @returns {string} Formatted date string
*/
export function formatDateInTimezone(date, timezone, formatStr = 'MMM d, yyyy') {
if (!date) return ''
try {
const dateObj = typeof date === 'string' ? new Date(date) : date
return formatInTimeZone(dateObj, timezone, formatStr)
} catch (e) {
console.warn('Error formatting date in timezone:', e)
// Fallback to basic formatting
const dateObj = typeof date === 'string' ? new Date(date) : date
return formatDate(dateObj, formatStr)
}
}
/**
* Format a date with time in a specific timezone
* @param {Date|string} date - Date to format
* @param {string} timezone - IANA timezone identifier
* @param {string} formatStr - date-fns format string (default: 'MMM d, yyyy h:mm a')
* @returns {string} Formatted datetime string
*/
export function formatDateTimeInTimezone(date, timezone, formatStr = 'MMM d, yyyy h:mm a') {
return formatDateInTimezone(date, timezone, formatStr)
}
/**
* Get today's date in a specific timezone as YYYY-MM-DD
* @param {string} timezone - IANA timezone identifier
* @returns {string} Date string in YYYY-MM-DD format
*/
export function getTodayInTimezone(timezone) {
try {
const now = new Date()
return formatInTimeZone(now, timezone, 'yyyy-MM-dd')
} catch (e) {
console.warn('Error getting today in timezone:', e)
// Fallback to local date
return formatDate(new Date(), 'yyyy-MM-dd')
}
}
/**
* Get yesterday's date in a specific timezone as YYYY-MM-DD
* @param {string} timezone - IANA timezone identifier
* @returns {string} Date string in YYYY-MM-DD format
*/
export function getYesterdayInTimezone(timezone) {
try {
const now = new Date()
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000)
return formatInTimeZone(yesterday, timezone, 'yyyy-MM-dd')
} catch (e) {
console.warn('Error getting yesterday in timezone:', e)
const yesterday = new Date()
yesterday.setDate(yesterday.getDate() - 1)
return formatDate(yesterday, 'yyyy-MM-dd')
}
}
/**
* Convert a date to a specific timezone
* @param {Date|string} date - Date to convert
* @param {string} timezone - IANA timezone identifier
* @returns {Date} Date object adjusted to the timezone
*/
export function toTimezone(date, timezone) {
const dateObj = typeof date === 'string' ? new Date(date) : date
return toZonedTime(dateObj, timezone)
}
/**
* Get the timezone label for display
* @param {string} timezone - IANA timezone identifier
* @returns {string} Human-readable timezone label
*/
export function getTimezoneLabel(timezone) {
const option = TIMEZONE_OPTIONS.find(opt => opt.value === timezone)
return option ? option.label : timezone
}