package main import ( "fmt" "time" ) // https://yourbasic.org/golang/time-change-convert-location-timezone/ // https://sebest.github.io/post/create-a-small-docker-image-for-a-golang-binary/ // https://github.com/FKSE/docker-golang-base // tar cfz zoneinfo.tar.gz /usr/share/zoneinfo // git clone https://github.com/eggert/tz // grep '^Rule' -r tz/ | cut -f8-10 | egrep -iv 'Rule|SAVE' // egrep '\s0:30' -r tz/ func main() { // blacklist "", "Local" // UTC to TZ should always be correct // TZ to UTC may not be correct now := time.Now() fmt.Println("Now", now.Format(time.RFC3339)) loc, err := time.LoadLocation("America/Phoenix") if nil != err { panic(err) } fmt.Println("Loc", now.In(loc)) /* boundary checks */ CheckInput([]int{2019, 11, 10, 01, 02, 56, 0}) CheckInput([]int{2019, 11, 10, 01, 02, 60, 0}) CheckInput([]int{2019, 11, 10, 01, 60, 59, 0}) CheckInput([]int{2019, 11, 10, 24, 59, 59, 0}) CheckInput([]int{2019, 11, 10, 25, 59, 59, 0}) CheckInput([]int{2019, 11, 10, 23, 59, 59, 0}) CheckInput([]int{2019, 11, 31, 23, 0, 0, 0}) /* funky times */ tz := "America/Denver" fmt.Println("funky") CheckInput2([]int{2019, 3, 10, 01, 59, 00, 0}, tz) CheckInput2([]int{2019, 3, 10, 02, 00, 00, 0}, tz) CheckInput2([]int{2019, 3, 10, 02, 01, 00, 0}, tz) CheckInput2([]int{2019, 3, 10, 02, 59, 00, 0}, tz) CheckInput2([]int{2019, 3, 10, 03, 00, 00, 0}, tz) CheckInput2([]int{2019, 3, 10, 03, 01, 00, 0}, tz) CheckInput2([]int{2019, 11, 03, 0, 59, 00, 0}, tz) CheckInput2([]int{2019, 11, 03, 01, 59, 00, 0}, tz) CheckInput2([]int{2019, 11, 03, 02, 00, 00, 0}, tz) CheckInput2([]int{2019, 11, 03, 02, 01, 00, 0}, tz) CheckInput2([]int{2019, 11, 03, 02, 59, 00, 0}, tz) CheckInput2([]int{2019, 11, 03, 03, 00, 00, 0}, tz) CheckInput2([]int{2019, 11, 03, 03, 01, 00, 0}, tz) CheckInput2([]int{2019, 11, 03, 04, 01, 00, 0}, tz) CheckInput2([]int{2019, 11, 03, 05, 01, 00, 0}, tz) } func CheckInput2(st []int, tzstr string) { m := time.Month(st[1]) tz, err := time.LoadLocation(tzstr) if nil != err { fmt.Println("screwed the pooch") return } // Does the time exist t1 := time.Date(st[0], m, st[2], st[3], st[4], st[5], st[6], tz) if st[5] != t1.Second() { fmt.Println("Bad Second", st, t1) return } if st[4] != t1.Minute() { fmt.Println("Bad Minute", st, t1.Minute()) return } if st[3] != t1.Hour() { fmt.Println("Bad Hour", st, t1) return } if st[2] != t1.Day() { fmt.Println("Bad Day of Month", st, t1) return } if st[1] != int(t1.Month()) { fmt.Println("Bad Month", st, t1) return } if st[0] != t1.Year() { fmt.Println("Bad Year", st, t1) return } // Does the time exist twice? // (if I change the time in UTC, do I still get the same time) // Note: Some timezones change by half or quarter hour // However, it seems that DST always changes by one or two whole hours // Oh, and then there's Luthuania... // Rule LH 2008 max - Oct Sun>=1 2:00 0:30 - // // https://en.wikipedia.org/wiki/Daylight_saving_time_by_country // https://en.wikipedia.org/wiki/Winter_time_(clock_lag) // https://en.wikipedia.org/wiki/Summer_time_in_Europe // https://en.wikipedia.org/wiki/Daylight_saving_time_in_the_Americas // If I change the time iadd or subtract time in UTC, do I see the same difference in TZ? u1 := t1.UTC() // A better way to do this would probably be to parse the timezone database, but... yeah... for _, n := range []int{ /*-120, -60,*/ 30, 60, 120} { t2 := time.Date(st[0], m, st[2], st[3], st[4]+n, st[5], st[6], tz) u2 := t2.UTC() if u1.Equal(u2) { fmt.Println("Ambiguous Time") fmt.Printf("%s, %s, %+d\n", t1, u1, n) fmt.Printf("%s, %s, %+d\n", t2, u2, n) return } } //ta := } func CheckInput(st []int) { m := time.Month(st[1]) t1 := time.Date(st[0], m, st[2], st[3], st[4], st[5], st[6], time.UTC) if st[5] != t1.Second() { fmt.Println("Bad Second", st) return } if st[4] != t1.Minute() { fmt.Println("Bad Minute", st, t1.Minute()) return } if st[3] != t1.Hour() { fmt.Println("Bad Hour", st) return } if st[2] != t1.Day() { fmt.Println("Bad Day of Month", st) return } if st[1] != int(t1.Month()) { fmt.Println("Bad Month", st) return } if st[0] != t1.Year() { fmt.Println("Bad Year", st) return } } /* ////// ////// 9:01 twice ////// var d = new Date("3/10/2019, 01:59:00"); console.log("tzUTC:" + tzUTC(d, 'America/Denver')); // tzUTC:Sun, 10 Mar 2019 08:59:00 GMT var d = new Date("3/10/2019, 02:01:00"); console.log("tzUTC:" + tzUTC(d, 'America/Denver')); // tzUTC:Sun, 10 Mar 2019 09:01:00 GMT var d = new Date("3/10/2019, 02:59:00"); console.log("tzUTC:" + tzUTC(d, 'America/Denver')); // tzUTC:Sun, 10 Mar 2019 09:59:00 GMT var d = new Date("3/10/2019, 03:01:00"); console.log("tzUTC:" + tzUTC(d, 'America/Denver')); // tzUTC:Sun, 10 Mar 2019 09:01:00 GMT ////// ////// 8:01 never ////// var d = new Date("11/03/2019, 01:59:00"); console.log("tzUTC:" + tzUTC(d, 'America/Denver')); // tzUTC:Sun, 03 Nov 2019 07:59:00 GMT var d = new Date("11/03/2019, 02:01:00"); console.log("tzUTC:" + tzUTC(d, 'America/Denver')); // tzUTC:Sun, 03 Nov 2019 09:01:00 GMT var d = new Date("11/03/2019, 02:59:00"); console.log("tzUTC:" + tzUTC(d, 'America/Denver')); // tzUTC:Sun, 03 Nov 2019 09:59:00 GMT var d = new Date("11/03/2019, 03:01:00"); console.log("tzUTC:" + tzUTC(d, 'America/Denver')); tzUTC:Sun, 03 Nov 2019 10:01:00 GMT */