// Principal cities sourced from https://en.wikipedia.org/wiki/List_of_UTC_offsets const PRINCIPAL_CITY_DATA = [ { name: 'Honolulu, United States', country: 'United States', timeZone: 'Pacific/Honolulu' }, { name: 'Anchorage, United States', country: 'United States', timeZone: 'America/Anchorage' }, { name: 'Los Angeles, United States', country: 'United States', timeZone: 'America/Los_Angeles' }, { name: 'Vancouver, Canada', country: 'Canada', timeZone: 'America/Vancouver' }, { name: 'Tijuana, Mexico', country: 'Mexico', timeZone: 'America/Tijuana' }, { name: 'Denver, United States', country: 'United States', timeZone: 'America/Denver' }, { name: 'Calgary, Canada', country: 'Canada', timeZone: 'America/Edmonton' }, { name: 'Ciudad Juárez, Mexico', country: 'Mexico', timeZone: 'America/Ciudad_Juarez' }, { name: 'Mexico City, Mexico', country: 'Mexico', timeZone: 'America/Mexico_City' }, { name: 'Chicago, United States', country: 'United States', timeZone: 'America/Chicago' }, { name: 'Guatemala City, Guatemala', country: 'Guatemala', timeZone: 'America/Guatemala' }, { name: 'Tegucigalpa, Honduras', country: 'Honduras', timeZone: 'America/Tegucigalpa' }, { name: 'Winnipeg, Canada', country: 'Canada', timeZone: 'America/Winnipeg' }, { name: 'San José, Costa Rica', country: 'Costa Rica', timeZone: 'America/Costa_Rica' }, { name: 'San Salvador, El Salvador', country: 'El Salvador', timeZone: 'America/El_Salvador' }, { name: 'New York, United States', country: 'United States', timeZone: 'America/New_York' }, { name: 'Toronto, Canada', country: 'Canada', timeZone: 'America/Toronto' }, { name: 'Havana, Cuba', country: 'Cuba', timeZone: 'America/Havana' }, { name: 'Lima, Peru', country: 'Peru', timeZone: 'America/Lima' }, { name: 'Bogotá, Colombia', country: 'Colombia', timeZone: 'America/Bogota' }, { name: 'Kingston, Jamaica', country: 'Jamaica', timeZone: 'America/Jamaica' }, { name: 'Quito, Ecuador', country: 'Ecuador', timeZone: 'America/Guayaquil' }, { name: 'Santiago, Chile', country: 'Chile', timeZone: 'America/Santiago' }, { name: 'Santo Domingo, Dominican Republic', country: 'Dominican Republic', timeZone: 'America/Santo_Domingo' }, { name: 'Manaus, Brazil', country: 'Brazil', timeZone: 'America/Manaus' }, { name: 'Caracas, Venezuela', country: 'Venezuela', timeZone: 'America/Caracas' }, { name: 'La Paz, Bolivia', country: 'Bolivia', timeZone: 'America/La_Paz' }, { name: 'Halifax, Canada', country: 'Canada', timeZone: 'America/Halifax' }, { name: 'St. John\'s, Canada', country: 'Canada', timeZone: 'America/St_Johns' }, { name: 'São Paulo, Brazil', country: 'Brazil', timeZone: 'America/Sao_Paulo' }, { name: 'Buenos Aires, Argentina', country: 'Argentina', timeZone: 'America/Argentina/Buenos_Aires' }, { name: 'Montevideo, Uruguay', country: 'Uruguay', timeZone: 'America/Montevideo' }, { name: 'London, United Kingdom', country: 'United Kingdom', timeZone: 'Europe/London' }, { name: 'Dublin, Ireland', country: 'Ireland', timeZone: 'Europe/Dublin' }, { name: 'Lisbon, Portugal', country: 'Portugal', timeZone: 'Europe/Lisbon' }, { name: 'Abidjan, Côte d\'Ivoire', country: 'Côte d\'Ivoire', timeZone: 'Africa/Abidjan' }, { name: 'Accra, Ghana', country: 'Ghana', timeZone: 'Africa/Accra' }, { name: 'Dakar, Senegal', country: 'Senegal', timeZone: 'Africa/Dakar' }, { name: 'Berlin, Germany', country: 'Germany', timeZone: 'Europe/Berlin' }, { name: 'Frankfurt, Germany', country: 'Germany', timeZone: 'Europe/Berlin' }, { name: 'Rome, Italy', country: 'Italy', timeZone: 'Europe/Rome' }, { name: 'Stockholm, Sweden', country: 'Sweden', timeZone: 'Europe/Stockholm' }, { name: 'Paris, France', country: 'France', timeZone: 'Europe/Paris' }, { name: 'Madrid, Spain', country: 'Spain', timeZone: 'Europe/Madrid' }, { name: 'Warsaw, Poland', country: 'Poland', timeZone: 'Europe/Warsaw' }, { name: 'Lagos, Nigeria', country: 'Nigeria', timeZone: 'Africa/Lagos' }, { name: 'Kinshasa, DR Congo', country: 'Democratic Republic of the Congo', timeZone: 'Africa/Kinshasa' }, { name: 'Algiers, Algeria', country: 'Algeria', timeZone: 'Africa/Algiers' }, { name: 'Casablanca, Morocco', country: 'Morocco', timeZone: 'Africa/Casablanca' }, { name: 'Athens, Greece', country: 'Greece', timeZone: 'Europe/Athens' }, { name: 'Bucharest, Romania', country: 'Romania', timeZone: 'Europe/Bucharest' }, { name: 'Cairo, Egypt', country: 'Egypt', timeZone: 'Africa/Cairo' }, { name: 'Helsinki, Finland', country: 'Finland', timeZone: 'Europe/Helsinki' }, { name: 'Jerusalem, Israel', country: 'Israel', timeZone: 'Asia/Jerusalem' }, { name: 'Johannesburg, South Africa', country: 'South Africa', timeZone: 'Africa/Johannesburg' }, { name: 'Khartoum, Sudan', country: 'Sudan', timeZone: 'Africa/Khartoum' }, { name: 'Kyiv, Ukraine', country: 'Ukraine', timeZone: 'Europe/Kyiv' }, { name: 'Riga, Latvia', country: 'Latvia', timeZone: 'Europe/Riga' }, { name: 'Sofia, Bulgaria', country: 'Bulgaria', timeZone: 'Europe/Sofia' }, { name: 'Moscow, Russia', country: 'Russia', timeZone: 'Europe/Moscow' }, { name: 'Istanbul, Türkiye', country: 'Türkiye', timeZone: 'Europe/Istanbul' }, { name: 'Riyadh, Saudi Arabia', country: 'Saudi Arabia', timeZone: 'Asia/Riyadh' }, { name: 'Baghdad, Iraq', country: 'Iraq', timeZone: 'Asia/Baghdad' }, { name: 'Addis Ababa, Ethiopia', country: 'Ethiopia', timeZone: 'Africa/Addis_Ababa' }, { name: 'Doha, Qatar', country: 'Qatar', timeZone: 'Asia/Qatar' }, { name: 'Nairobi, Kenya', country: 'Kenya', timeZone: 'Africa/Nairobi' }, { name: 'Kuwait City, Kuwait', country: 'Kuwait', timeZone: 'Asia/Kuwait' }, { name: 'Tehran, Iran', country: 'Iran', timeZone: 'Asia/Tehran' }, { name: 'Dubai, United Arab Emirates', country: 'United Arab Emirates', timeZone: 'Asia/Dubai' }, { name: 'Baku, Azerbaijan', country: 'Azerbaijan', timeZone: 'Asia/Baku' }, { name: 'Tbilisi, Georgia', country: 'Georgia', timeZone: 'Asia/Tbilisi' }, { name: 'Yerevan, Armenia', country: 'Armenia', timeZone: 'Asia/Yerevan' }, { name: 'Samara, Russia', country: 'Russia', timeZone: 'Europe/Samara' }, { name: 'Kabul, Afghanistan', country: 'Afghanistan', timeZone: 'Asia/Kabul' }, { name: 'Karachi, Pakistan', country: 'Pakistan', timeZone: 'Asia/Karachi' }, { name: 'Astana, Kazakhstan', country: 'Kazakhstan', timeZone: 'Asia/Almaty' }, { name: 'Tashkent, Uzbekistan', country: 'Uzbekistan', timeZone: 'Asia/Tashkent' }, { name: 'Yekaterinburg, Russia', country: 'Russia', timeZone: 'Asia/Yekaterinburg' }, { name: 'Delhi, India', country: 'India', timeZone: 'Asia/Kolkata' }, { name: 'Mumbai, India', country: 'India', timeZone: 'Asia/Kolkata' }, { name: 'Colombo, Sri Lanka', country: 'Sri Lanka', timeZone: 'Asia/Colombo' }, { name: 'Kathmandu, Nepal', country: 'Nepal', timeZone: 'Asia/Kathmandu' }, { name: 'Dhaka, Bangladesh', country: 'Bangladesh', timeZone: 'Asia/Dhaka' }, { name: 'Omsk, Russia', country: 'Russia', timeZone: 'Asia/Omsk' }, { name: 'Bishkek, Kyrgyzstan', country: 'Kyrgyzstan', timeZone: 'Asia/Bishkek' }, { name: 'Yangon, Myanmar', country: 'Myanmar', timeZone: 'Asia/Yangon' }, { name: 'Jakarta, Indonesia', country: 'Indonesia', timeZone: 'Asia/Jakarta' }, { name: 'Ho Chi Minh City, Vietnam', country: 'Vietnam', timeZone: 'Asia/Ho_Chi_Minh' }, { name: 'Bangkok, Thailand', country: 'Thailand', timeZone: 'Asia/Bangkok' }, { name: 'Krasnoyarsk, Russia', country: 'Russia', timeZone: 'Asia/Krasnoyarsk' }, { name: 'Shanghai, China', country: 'China', timeZone: 'Asia/Shanghai' }, { name: 'Taipei, Taiwan', country: 'Taiwan', timeZone: 'Asia/Taipei' }, { name: 'Hong Kong, China', country: 'China', timeZone: 'Asia/Hong_Kong' }, { name: 'Kuala Lumpur, Malaysia', country: 'Malaysia', timeZone: 'Asia/Kuala_Lumpur' }, { name: 'Singapore, Singapore', country: 'Singapore', timeZone: 'Asia/Singapore' }, { name: 'Perth, Australia', country: 'Australia', timeZone: 'Australia/Perth' }, { name: 'Manila, Philippines', country: 'Philippines', timeZone: 'Asia/Manila' }, { name: 'Makassar, Indonesia', country: 'Indonesia', timeZone: 'Asia/Makassar' }, { name: 'Irkutsk, Russia', country: 'Russia', timeZone: 'Asia/Irkutsk' }, { name: 'Tokyo, Japan', country: 'Japan', timeZone: 'Asia/Tokyo' }, { name: 'Seoul, South Korea', country: 'South Korea', timeZone: 'Asia/Seoul' }, { name: 'Pyongyang, North Korea', country: 'North Korea', timeZone: 'Asia/Pyongyang' }, { name: 'Jayapura, Indonesia', country: 'Indonesia', timeZone: 'Asia/Jayapura' }, { name: 'Chita, Russia', country: 'Russia', timeZone: 'Asia/Chita' }, { name: 'Adelaide, Australia', country: 'Australia', timeZone: 'Australia/Adelaide' }, { name: 'Sydney, Australia', country: 'Australia', timeZone: 'Australia/Sydney' }, { name: 'Melbourne, Australia', country: 'Australia', timeZone: 'Australia/Melbourne' }, { name: 'Brisbane, Australia', country: 'Australia', timeZone: 'Australia/Brisbane' }, { name: 'Port Moresby, Papua New Guinea', country: 'Papua New Guinea', timeZone: 'Pacific/Port_Moresby' }, { name: 'Vladivostok, Russia', country: 'Russia', timeZone: 'Asia/Vladivostok' }, { name: 'Nouméa, New Caledonia', country: 'New Caledonia', timeZone: 'Pacific/Noumea' }, { name: 'Auckland, New Zealand', country: 'New Zealand', timeZone: 'Pacific/Auckland' }, { name: 'Suva, Fiji', country: 'Fiji', timeZone: 'Pacific/Fiji' }, { name: 'Petropavlovsk-Kamchatsky, Russia', country: 'Russia', timeZone: 'Asia/Kamchatka' } ]; // Additional curated list to provide broader coverage beyond the principal cities list. const ADDITIONAL_CITY_DATA = [ { name: 'Amsterdam, Netherlands', country: 'Netherlands', timeZone: 'Europe/Amsterdam', keywords: ['ams', 'holland', 'nl'] }, { name: 'Auckland, New Zealand', country: 'New Zealand', timeZone: 'Pacific/Auckland' }, { name: 'Bangkok, Thailand', country: 'Thailand', timeZone: 'Asia/Bangkok', keywords: ['thai'] }, { name: 'Barcelona, Spain', country: 'Spain', timeZone: 'Europe/Madrid', keywords: ['catalonia', 'esp'] }, { name: 'Beijing, China', country: 'China', timeZone: 'Asia/Shanghai', keywords: ['cn'] }, { name: 'Berlin, Germany', country: 'Germany', timeZone: 'Europe/Berlin', keywords: ['de'] }, { name: 'Bogotá, Colombia', country: 'Colombia', timeZone: 'America/Bogota', keywords: ['co'] }, { name: 'Boston, United States', country: 'United States', timeZone: 'America/New_York', keywords: ['est'] }, { name: 'Cape Town, South Africa', country: 'South Africa', timeZone: 'Africa/Johannesburg', keywords: ['cpt'] }, { name: 'Copenhagen, Denmark', country: 'Denmark', timeZone: 'Europe/Copenhagen', keywords: ['dk'] }, { name: 'Dubai, United Arab Emirates', country: 'United Arab Emirates', timeZone: 'Asia/Dubai', keywords: ['uae'] }, { name: 'Dublin, Ireland', country: 'Ireland', timeZone: 'Europe/Dublin', keywords: ['ie'] }, { name: 'Frankfurt, Germany', country: 'Germany', timeZone: 'Europe/Berlin', keywords: ['fra'] }, { name: 'Hong Kong, China', country: 'China', timeZone: 'Asia/Hong_Kong', keywords: ['hk'] }, { name: 'Istanbul, Türkiye', country: 'Türkiye', timeZone: 'Europe/Istanbul', keywords: ['istanbul'] }, { name: 'Jakarta, Indonesia', country: 'Indonesia', timeZone: 'Asia/Jakarta', keywords: ['id'] }, { name: 'Johannesburg, South Africa', country: 'South Africa', timeZone: 'Africa/Johannesburg', keywords: ['za'] }, { name: 'Kuala Lumpur, Malaysia', country: 'Malaysia', timeZone: 'Asia/Kuala_Lumpur', keywords: ['my'] }, { name: 'Lisbon, Portugal', country: 'Portugal', timeZone: 'Europe/Lisbon', keywords: ['pt'] }, { name: 'London, United Kingdom', country: 'United Kingdom', timeZone: 'Europe/London', keywords: ['uk', 'gb', 'gmt'] }, { name: 'Los Angeles, United States', country: 'United States', timeZone: 'America/Los_Angeles', keywords: ['la', 'pst'] }, { name: 'Mexico City, Mexico', country: 'Mexico', timeZone: 'America/Mexico_City', keywords: ['mx', 'cdmx'] }, { name: 'Miami, United States', country: 'United States', timeZone: 'America/New_York', keywords: ['florida'] }, { name: 'Mumbai, India', country: 'India', timeZone: 'Asia/Kolkata', keywords: ['in', 'bombay'] }, { name: 'New York, United States', country: 'United States', timeZone: 'America/New_York', keywords: ['nyc'] }, { name: 'Oslo, Norway', country: 'Norway', timeZone: 'Europe/Oslo', keywords: ['no'] }, { name: 'Paris, France', country: 'France', timeZone: 'Europe/Paris', keywords: ['fr'] }, { name: 'Reykjavík, Iceland', country: 'Iceland', timeZone: 'Atlantic/Reykjavik', keywords: ['iceland'] }, { name: 'San Francisco, United States', country: 'United States', timeZone: 'America/Los_Angeles', keywords: ['sf', 'bay'] }, { name: 'São Paulo, Brazil', country: 'Brazil', timeZone: 'America/Sao_Paulo', keywords: ['br'] }, { name: 'Singapore, Singapore', country: 'Singapore', timeZone: 'Asia/Singapore', keywords: ['sg'] }, { name: 'Stockholm, Sweden', country: 'Sweden', timeZone: 'Europe/Stockholm', keywords: ['se'] }, { name: 'Sydney, Australia', country: 'Australia', timeZone: 'Australia/Sydney', keywords: ['au'] }, { name: 'Tokyo, Japan', country: 'Japan', timeZone: 'Asia/Tokyo', keywords: ['jp'] }, { name: 'Toronto, Canada', country: 'Canada', timeZone: 'America/Toronto', keywords: ['ca'] }, { name: 'Vienna, Austria', country: 'Austria', timeZone: 'Europe/Vienna', keywords: ['at'] }, { name: 'Warsaw, Poland', country: 'Poland', timeZone: 'Europe/Warsaw', keywords: ['pl'] }, { name: 'Zurich, Switzerland', country: 'Switzerland', timeZone: 'Europe/Zurich', keywords: ['ch'] } ]; function deduplicateByKey(list) { const map = new Map(); list.forEach((entry) => { const key = `${entry.name.toLowerCase()}|${entry.timeZone}`; const keywords = Array.isArray(entry.keywords) ? entry.keywords : []; if (!map.has(key)) { map.set(key, { ...entry, keywords }); } else { const existing = map.get(key); const mergedKeywords = new Set([...(existing.keywords || []), ...keywords]); existing.keywords = Array.from(mergedKeywords); if (!existing.country && entry.country) { existing.country = entry.country; } } }); return Array.from(map.values()); } const RAW_TIMEZONE_DATA = deduplicateByKey([...PRINCIPAL_CITY_DATA, ...ADDITIONAL_CITY_DATA]); const COUNTRY_TRANSLATIONS = { Afghanistan: 'Afghanistan', Algeria: 'Algerien', Argentina: 'Argentinien', Armenia: 'Armenien', Australia: 'Australien', Austria: 'Österreich', Azerbaijan: 'Aserbaidschan', Bangladesh: 'Bangladesch', Bolivia: 'Bolivien', Brazil: 'Brasilien', Bulgaria: 'Bulgarien', Canada: 'Kanada', Chile: 'Chile', China: 'China', Colombia: 'Kolumbien', 'Costa Rica': 'Costa Rica', Cuba: 'Kuba', "Côte d'Ivoire": 'Elfenbeinküste', 'Democratic Republic of the Congo': 'Demokratische Republik Kongo', Denmark: 'Dänemark', 'Dominican Republic': 'Dominikanische Republik', Ecuador: 'Ecuador', Egypt: 'Ägypten', 'El Salvador': 'El Salvador', Ethiopia: 'Äthiopien', Fiji: 'Fidschi', Finland: 'Finnland', France: 'Frankreich', Georgia: 'Georgien', Germany: 'Deutschland', Ghana: 'Ghana', Greece: 'Griechenland', Guatemala: 'Guatemala', Honduras: 'Honduras', Iceland: 'Island', India: 'Indien', Indonesia: 'Indonesien', Iran: 'Iran', Iraq: 'Irak', Ireland: 'Irland', Israel: 'Israel', Italy: 'Italien', Jamaica: 'Jamaika', Japan: 'Japan', Kazakhstan: 'Kasachstan', Kenya: 'Kenia', Kuwait: 'Kuwait', Kyrgyzstan: 'Kirgisistan', Latvia: 'Lettland', Malaysia: 'Malaysia', Mexico: 'Mexiko', Morocco: 'Marokko', Myanmar: 'Myanmar', Nepal: 'Nepal', Netherlands: 'Niederlande', 'New Caledonia': 'Neukaledonien', 'New Zealand': 'Neuseeland', Nigeria: 'Nigeria', 'North Korea': 'Nordkorea', Norway: 'Norwegen', Pakistan: 'Pakistan', 'Papua New Guinea': 'Papua-Neuguinea', Peru: 'Peru', Philippines: 'Philippinen', Poland: 'Polen', Portugal: 'Portugal', Qatar: 'Katar', Romania: 'Rumänien', Russia: 'Russland', 'Saudi Arabia': 'Saudi-Arabien', Senegal: 'Senegal', Singapore: 'Singapur', 'South Africa': 'Südafrika', 'South Korea': 'Südkorea', Spain: 'Spanien', 'Sri Lanka': 'Sri Lanka', Sudan: 'Sudan', Sweden: 'Schweden', Switzerland: 'Schweiz', Taiwan: 'Taiwan', Thailand: 'Thailand', Türkiye: 'Türkei', Ukraine: 'Ukraine', 'United Arab Emirates': 'Vereinigte Arabische Emirate', 'United Kingdom': 'Vereinigtes Königreich', 'United States': 'Vereinigte Staaten', Uruguay: 'Uruguay', Uzbekistan: 'Usbekistan', Venezuela: 'Venezuela', Vietnam: 'Vietnam' }; function translateCountry(country) { return COUNTRY_TRANSLATIONS[country] || country; } function addGermanKeywordVariants(keywords, germanValue) { const variants = new Set(keywords); const lower = germanValue.toLowerCase(); variants.add(lower); variants.add( lower .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') ); return Array.from(variants); } const TIMEZONE_DATA = RAW_TIMEZONE_DATA.map((entry) => { const translatedCountry = translateCountry(entry.country); const city = entry.name.split(',')[0].trim(); const baseKeywords = Array.isArray(entry.keywords) ? entry.keywords : []; const keywordsWithCountries = addGermanKeywordVariants( addGermanKeywordVariants(baseKeywords, entry.country), translatedCountry ); return { ...entry, name: `${city}, ${translatedCountry}`, country: translatedCountry, keywords: keywordsWithCountries }; }); // Provide a sorted copy for deterministic rendering. const SORTED_TIMEZONE_DATA = TIMEZONE_DATA.slice().sort((a, b) => a.name.localeCompare(b.name));