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  }