package main import ( "time" ) type TimezoneConfig struct { StandardName string StandardOffset int DaylightName string DaylightOffset int ObservesUSDST bool } // Map timezone aliases to standard/daylight offsets var timezones = map[string]TimezoneConfig{ // Dynamic US zones (switch automatically between Standard and Daylight) "US/Eastern": {"EST", -5 * 3600, "EDT", -4 * 3600, true}, "ET": {"EST", -5 * 3600, "EDT", -4 * 3600, true}, "US/Central": {"CST", -6 * 3600, "CDT", -5 * 3600, true}, "CT": {"CST", -6 * 3600, "CDT", -5 * 3600, true}, "US/Mountain": {"MST", -7 * 3600, "MDT", -6 * 3600, true}, "MT": {"MST", -7 * 3600, "MDT", -6 * 3600, true}, "US/Pacific": {"PST", -8 * 3600, "PDT", -7 * 3600, true}, "PT": {"PST", -8 * 3600, "PDT", -7 * 3600, true}, // Fixed non-DST zones "UTC": {"UTC", 0, "UTC", 0, false}, "EST": {"EST", -5 * 3600, "EST", -5 * 3600, false}, "EDT": {"EDT", -4 * 3600, "EDT", -4 * 3600, false}, "CST": {"CST", -6 * 3600, "CST", -6 * 3600, false}, "CDT": {"CDT", -5 * 3600, "CDT", -5 * 3600, false}, "MST": {"MST", -7 * 3600, "MST", -7 * 3600, false}, "MDT": {"MDT", -6 * 3600, "MDT", -6 * 3600, false}, "PST": {"PST", -8 * 3600, "PST", -8 * 3600, false}, "PDT": {"PDT", -7 * 3600, "PDT", -7 * 3600, false}, } // IsUSDST checks if the given UTC time falls in US Daylight Saving Time // (Second Sunday in March at 02:00 local to first Sunday in November at 02:00 local). func IsUSDST(t time.Time, stdOffsetSec int) bool { month := t.Month() if month < time.March || month > time.November { return false // Dec, Jan, Feb } if month > time.March && month < time.November { return true // Apr through Oct } day := t.Day() weekday := int(t.Weekday()) if month == time.March { // Second Sunday in March is between 8th and 14th prevSunday := day - weekday if prevSunday < 8 { return false } if prevSunday >= 15 { return true } // Transition occurs at 2:00 AM standard local time -> (2 - stdOffsetHours) in UTC stdOffsetHours := stdOffsetSec / 3600 switchHourUTC := 2 - stdOffsetHours return weekday != int(time.Sunday) || t.Hour() >= switchHourUTC } // November: first Sunday is between 1st and 7th prevSunday := day - weekday if prevSunday < 1 { return true // Before first Sunday } // Fall-back occurs at 2:00 AM daylight local time -> (2 - (stdOffsetHours + 1)) in UTC stdOffsetHours := stdOffsetSec / 3600 switchHourUTC := 2 - (stdOffsetHours + 1) return weekday == int(time.Sunday) && t.Hour() < switchHourUTC } // ResolveTimezone dynamically determines the *time.Location and label // based on whether the zone observes DST at the given UTC time. func ResolveTimezone(name string, utcNow time.Time) (*time.Location, string) { cfg, ok := timezones[name] if !ok { return time.FixedZone("UTC", 0), "UTC" } if cfg.ObservesUSDST && IsUSDST(utcNow, cfg.StandardOffset) { return time.FixedZone(cfg.DaylightName, cfg.DaylightOffset), cfg.DaylightName } return time.FixedZone(cfg.StandardName, cfg.StandardOffset), cfg.StandardName }