timezone-abbreviations.ts5.5 KBView on GitHub
/**
 * Timezone abbreviation to IANA timezone identifier mapping.
 * 
 * Note: Timezone abbreviations are ambiguous (e.g., CST can mean Central Standard Time US,
 * China Standard Time, or Cuba Standard Time). This mapping defaults to the most common
 * interpretation, prioritizing US timezones for ambiguous cases.
 * 
 * For DST-aware timezones, both standard and daylight abbreviations map to the same IANA
 * identifier (e.g., EST and EDT both map to America/New_York), which automatically handles
 * daylight saving time transitions.
 */
export const TIMEZONE_ABBREVIATIONS: Record<string, string> = {
  // US Timezones (prioritize these for ambiguous cases)
  'EST': 'America/New_York',
  'EDT': 'America/New_York',
  'ET': 'America/New_York',
  'EASTERN': 'America/New_York',
  
  'CST': 'America/Chicago',
  'CDT': 'America/Chicago',
  'CT': 'America/Chicago',
  'CENTRAL': 'America/Chicago',
  
  'MST': 'America/Denver',
  'MDT': 'America/Denver',
  'MT': 'America/Denver',
  'MOUNTAIN': 'America/Denver',
  
  'PST': 'America/Los_Angeles',
  'PDT': 'America/Los_Angeles',
  'PT': 'America/Los_Angeles',
  'PACIFIC': 'America/Los_Angeles',
  
  'AKST': 'America/Anchorage',
  'AKDT': 'America/Anchorage',
  'AKT': 'America/Anchorage',
  'ALASKA': 'America/Anchorage',
  
  'HST': 'Pacific/Honolulu',
  'HAST': 'Pacific/Honolulu',
  'HADT': 'Pacific/Honolulu',
  'HAWAII': 'Pacific/Honolulu',
  
  'AST': 'America/Halifax',
  'ADT': 'America/Halifax',
  'ATLANTIC': 'America/Halifax',
  
  'NST': 'America/St_Johns',
  'NDT': 'America/St_Johns',
  'NEWFOUNDLAND': 'America/St_Johns',
  
  // Europe
  'GMT': 'Europe/London',
  'BST': 'Europe/London',
  'LONDON': 'Europe/London',
  
  'CET': 'Europe/Paris',
  'CEST': 'Europe/Paris',
  'PARIS': 'Europe/Paris',
  
  'EET': 'Europe/Athens',
  'EEST': 'Europe/Athens',
  
  'WET': 'Europe/Lisbon',
  'WEST': 'Europe/Lisbon',
  
  'IST': 'Europe/Dublin',  // Irish Standard Time (ambiguous with India/Israel)
  'DUBLIN': 'Europe/Dublin',
  
  'MSK': 'Europe/Moscow',
  'MOSCOW': 'Europe/Moscow',
  
  // Asia
  'JST': 'Asia/Tokyo',
  'TOKYO': 'Asia/Tokyo',
  'JAPAN': 'Asia/Tokyo',
  
  'KST': 'Asia/Seoul',
  'SEOUL': 'Asia/Seoul',
  'KOREA': 'Asia/Seoul',
  
  'SGT': 'Asia/Singapore',
  'SINGAPORE': 'Asia/Singapore',
  
  'HKT': 'Asia/Hong_Kong',
  'HONGKONG': 'Asia/Hong_Kong',
  
  'CHINA': 'Asia/Shanghai',
  'SHANGHAI': 'Asia/Shanghai',
  
  'INDIA': 'Asia/Kolkata',
  'KOLKATA': 'Asia/Kolkata',
  'MUMBAI': 'Asia/Kolkata',
  'DELHI': 'Asia/Kolkata',
  
  'BANGKOK': 'Asia/Bangkok',
  'ICT': 'Asia/Bangkok',
  
  'WIB': 'Asia/Jakarta',
  'JAKARTA': 'Asia/Jakarta',
  
  'MANILA': 'Asia/Manila',
  'PHT': 'Asia/Manila',
  
  'DUBAI': 'Asia/Dubai',
  'GST': 'Asia/Dubai',
  
  'ISRAEL': 'Asia/Jerusalem',
  'JERUSALEM': 'Asia/Jerusalem',
  
  // Australia & Pacific
  'AEST': 'Australia/Sydney',
  'AEDT': 'Australia/Sydney',
  'SYDNEY': 'Australia/Sydney',
  
  'ACST': 'Australia/Adelaide',
  'ACDT': 'Australia/Adelaide',
  'ADELAIDE': 'Australia/Adelaide',
  
  'AWST': 'Australia/Perth',
  'PERTH': 'Australia/Perth',
  
  'NZST': 'Pacific/Auckland',
  'NZDT': 'Pacific/Auckland',
  'AUCKLAND': 'Pacific/Auckland',
  'NEWZEALAND': 'Pacific/Auckland',
  
  // South America
  'BRT': 'America/Sao_Paulo',
  'BRST': 'America/Sao_Paulo',
  'BRAZIL': 'America/Sao_Paulo',
  'SAOPAULO': 'America/Sao_Paulo',
  
  'ART': 'America/Argentina/Buenos_Aires',
  'ARGENTINA': 'America/Argentina/Buenos_Aires',
  'BUENOSAIRES': 'America/Argentina/Buenos_Aires',
  
  'CLT': 'America/Santiago',
  'CLST': 'America/Santiago',
  'SANTIAGO': 'America/Santiago',
  
  // Africa
  'SAST': 'Africa/Johannesburg',
  'JOHANNESBURG': 'Africa/Johannesburg',
  'SOUTHAFRICA': 'Africa/Johannesburg',
  
  'CAT': 'Africa/Maputo',
  
  'EAT': 'Africa/Nairobi',
  'NAIROBI': 'Africa/Nairobi',
  
  'WAT': 'Africa/Lagos',
  'LAGOS': 'Africa/Lagos',
  
  // UTC variants
  'UTC': 'UTC',
  'Z': 'UTC',
  'ZULU': 'UTC',
  'GMT+0': 'UTC',
  'GMT-0': 'UTC',
};

/**
 * Parse a timezone abbreviation and return the corresponding IANA timezone identifier.
 * Returns null if the abbreviation is not recognized.
 * 
 * @param abbr - The timezone abbreviation (case-insensitive)
 * @returns The IANA timezone identifier, or null if not found
 * 
 * @example
 * parseTimezoneAbbreviation('EST') // 'America/New_York'
 * parseTimezoneAbbreviation('pst') // 'America/Los_Angeles'
 * parseTimezoneAbbreviation('XYZ') // null
 */
export function parseTimezoneAbbreviation(abbr: string): string | null {
  return TIMEZONE_ABBREVIATIONS[abbr.toUpperCase()] || null;
}

/**
 * Get a human-readable timezone name from an abbreviation.
 * 
 * @param abbr - The timezone abbreviation
 * @returns A formatted timezone name, or the original abbreviation if not found
 * 
 * @example
 * getTimezoneName('EST') // 'Eastern Time'
 * getTimezoneName('PST') // 'Pacific Time'
 */
export function getTimezoneName(abbr: string): string {
  const upper = abbr.toUpperCase();
  
  // Map common abbreviations to friendly names
  const names: Record<string, string> = {
    'EST': 'Eastern Time',
    'EDT': 'Eastern Time',
    'ET': 'Eastern Time',
    'CST': 'Central Time',
    'CDT': 'Central Time',
    'CT': 'Central Time',
    'MST': 'Mountain Time',
    'MDT': 'Mountain Time',
    'MT': 'Mountain Time',
    'PST': 'Pacific Time',
    'PDT': 'Pacific Time',
    'PT': 'Pacific Time',
    'GMT': 'GMT',
    'UTC': 'UTC',
    'JST': 'Japan Time',
    'KST': 'Korea Time',
    'AEST': 'Australian Eastern Time',
    'AEDT': 'Australian Eastern Time',
  };
  
  return names[upper] || abbr;
}