github.com/thanos-io/thanos@v0.32.5/internal/cortex/util/time.go (about) 1 // Copyright (c) The Cortex Authors. 2 // Licensed under the Apache License 2.0. 3 4 package util 5 6 import ( 7 "math" 8 "math/rand" 9 "net/http" 10 "strconv" 11 "time" 12 13 "github.com/prometheus/common/model" 14 "github.com/weaveworks/common/httpgrpc" 15 ) 16 17 const ( 18 nanosecondsInMillisecond = int64(time.Millisecond / time.Nanosecond) 19 ) 20 21 func TimeToMillis(t time.Time) int64 { 22 return t.UnixNano() / nanosecondsInMillisecond 23 } 24 25 // TimeFromMillis is a helper to turn milliseconds -> time.Time 26 func TimeFromMillis(ms int64) time.Time { 27 return time.Unix(0, ms*nanosecondsInMillisecond) 28 } 29 30 // FormatTimeMillis returns a human readable version of the input time (in milliseconds). 31 func FormatTimeMillis(ms int64) string { 32 return TimeFromMillis(ms).String() 33 } 34 35 // FormatTimeModel returns a human readable version of the input time. 36 func FormatTimeModel(t model.Time) string { 37 return TimeFromMillis(int64(t)).String() 38 } 39 40 // ParseTime parses the string into an int64, milliseconds since epoch. 41 func ParseTime(s string) (int64, error) { 42 if t, err := strconv.ParseFloat(s, 64); err == nil { 43 s, ns := math.Modf(t) 44 ns = math.Round(ns*1000) / 1000 45 tm := time.Unix(int64(s), int64(ns*float64(time.Second))) 46 return TimeToMillis(tm), nil 47 } 48 if t, err := time.Parse(time.RFC3339Nano, s); err == nil { 49 return TimeToMillis(t), nil 50 } 51 return 0, httpgrpc.Errorf(http.StatusBadRequest, "cannot parse %q to a valid timestamp", s) 52 } 53 54 // DurationWithJitter returns random duration from "input - input*variance" to "input + input*variance" interval. 55 func DurationWithJitter(input time.Duration, variancePerc float64) time.Duration { 56 // No duration? No jitter. 57 if input == 0 { 58 return 0 59 } 60 61 variance := int64(float64(input) * variancePerc) 62 jitter := rand.Int63n(variance*2) - variance 63 64 return input + time.Duration(jitter) 65 } 66 67 // DurationWithPositiveJitter returns random duration from "input" to "input + input*variance" interval. 68 func DurationWithPositiveJitter(input time.Duration, variancePerc float64) time.Duration { 69 // No duration? No jitter. 70 if input == 0 { 71 return 0 72 } 73 74 variance := int64(float64(input) * variancePerc) 75 jitter := rand.Int63n(variance) 76 77 return input + time.Duration(jitter) 78 } 79 80 // NewDisableableTicker essentially wraps NewTicker but allows the ticker to be disabled by passing 81 // zero duration as the interval. Returns a function for stopping the ticker, and the ticker channel. 82 func NewDisableableTicker(interval time.Duration) (func(), <-chan time.Time) { 83 if interval == 0 { 84 return func() {}, nil 85 } 86 87 tick := time.NewTicker(interval) 88 return func() { tick.Stop() }, tick.C 89 }