github.com/haraldrudell/parl@v0.4.176/ptime/on-timer.go (about) 1 /* 2 © 2018–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package ptime 7 8 import ( 9 "time" 10 11 "github.com/haraldrudell/parl/perrors" 12 ) 13 14 // OnTimer returns a time.Timer that waits until the next period-multiple since zero time. 15 // - default starting time until the period multiple is now: time.Now(), optionally the absolute time t 16 // - t contains time zone that matters for periods over 1 hour, typically this is time.Local 17 // - the other time zone for Go is time.UTC 18 // - period must be greater than zero or panic 19 // - time.NewTimer does not offer the period calculation 20 func OnTimer(period time.Duration, t ...time.Time) (timer *time.Timer) { 21 var t0 time.Time 22 if len(t) > 0 { 23 t0 = t[0] 24 } 25 if t0.IsZero() { 26 t0 = time.Now() 27 } 28 return time.NewTimer(Duro(period, t0)) 29 } 30 31 // Duro returns the duration in nanoseconds until the next duration-multiple from zero time. 32 // - The period starts from atTime 33 // - time zone for multiple-calculation is defined by atTime, often time.Local 34 // - time zone matters for 24 h or longer durations 35 func Duro(period time.Duration, atTime time.Time) (d time.Duration) { 36 if period <= 0 { 37 panic(perrors.Errorf("Duro with non-positive period: %s", period)) 38 } 39 d = atTime.Add(period).Truncate(period).Sub(atTime) // value for UTC: 0 <= d < period 40 _, secondsEastofUTC := atTime.Zone() 41 toAdd := -time.Duration(secondsEastofUTC) * time.Second 42 d = (d + toAdd) % period // -period < d < period: may be negative 43 if d < 0 { 44 d += period // 0 <= d < period 45 } 46 if d == 0 { 47 d += period // 0 < d <= period 48 } 49 return // 0 < d <= period 50 }