github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/prometheus/common/model/time.go (about) 1 // Copyright 2013 The Prometheus Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package model 15 16 import ( 17 "fmt" 18 "math" 19 "regexp" 20 "strconv" 21 "strings" 22 "time" 23 ) 24 25 const ( 26 // MinimumTick is the minimum supported time resolution. This has to be 27 // at least time.Second in order for the code below to work. 28 minimumTick = time.Millisecond 29 // second is the Time duration equivalent to one second. 30 second = int64(time.Second / minimumTick) 31 // The number of nanoseconds per minimum tick. 32 nanosPerTick = int64(minimumTick / time.Nanosecond) 33 34 // Earliest is the earliest Time representable. Handy for 35 // initializing a high watermark. 36 Earliest = Time(math.MinInt64) 37 // Latest is the latest Time representable. Handy for initializing 38 // a low watermark. 39 Latest = Time(math.MaxInt64) 40 ) 41 42 // Time is the number of milliseconds since the epoch 43 // (1970-01-01 00:00 UTC) excluding leap seconds. 44 type Time int64 45 46 // Interval describes an interval between two timestamps. 47 type Interval struct { 48 Start, End Time 49 } 50 51 // Now returns the current time as a Time. 52 func Now() Time { 53 return TimeFromUnixNano(time.Now().UnixNano()) 54 } 55 56 // TimeFromUnix returns the Time equivalent to the Unix Time t 57 // provided in seconds. 58 func TimeFromUnix(t int64) Time { 59 return Time(t * second) 60 } 61 62 // TimeFromUnixNano returns the Time equivalent to the Unix Time 63 // t provided in nanoseconds. 64 func TimeFromUnixNano(t int64) Time { 65 return Time(t / nanosPerTick) 66 } 67 68 // Equal reports whether two Times represent the same instant. 69 func (t Time) Equal(o Time) bool { 70 return t == o 71 } 72 73 // Before reports whether the Time t is before o. 74 func (t Time) Before(o Time) bool { 75 return t < o 76 } 77 78 // After reports whether the Time t is after o. 79 func (t Time) After(o Time) bool { 80 return t > o 81 } 82 83 // Add returns the Time t + d. 84 func (t Time) Add(d time.Duration) Time { 85 return t + Time(d/minimumTick) 86 } 87 88 // Sub returns the Duration t - o. 89 func (t Time) Sub(o Time) time.Duration { 90 return time.Duration(t-o) * minimumTick 91 } 92 93 // Time returns the time.Time representation of t. 94 func (t Time) Time() time.Time { 95 return time.Unix(int64(t)/second, (int64(t)%second)*nanosPerTick) 96 } 97 98 // Unix returns t as a Unix time, the number of seconds elapsed 99 // since January 1, 1970 UTC. 100 func (t Time) Unix() int64 { 101 return int64(t) / second 102 } 103 104 // UnixNano returns t as a Unix time, the number of nanoseconds elapsed 105 // since January 1, 1970 UTC. 106 func (t Time) UnixNano() int64 { 107 return int64(t) * nanosPerTick 108 } 109 110 // The number of digits after the dot. 111 var dotPrecision = int(math.Log10(float64(second))) 112 113 // String returns a string representation of the Time. 114 func (t Time) String() string { 115 return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64) 116 } 117 118 // MarshalJSON implements the json.Marshaler interface. 119 func (t Time) MarshalJSON() ([]byte, error) { 120 return []byte(t.String()), nil 121 } 122 123 // UnmarshalJSON implements the json.Unmarshaler interface. 124 func (t *Time) UnmarshalJSON(b []byte) error { 125 p := strings.Split(string(b), ".") 126 switch len(p) { 127 case 1: 128 v, err := strconv.ParseInt(string(p[0]), 10, 64) 129 if err != nil { 130 return err 131 } 132 *t = Time(v * second) 133 134 case 2: 135 v, err := strconv.ParseInt(string(p[0]), 10, 64) 136 if err != nil { 137 return err 138 } 139 v *= second 140 141 prec := dotPrecision - len(p[1]) 142 if prec < 0 { 143 p[1] = p[1][:dotPrecision] 144 } else if prec > 0 { 145 p[1] = p[1] + strings.Repeat("0", prec) 146 } 147 148 va, err := strconv.ParseInt(p[1], 10, 32) 149 if err != nil { 150 return err 151 } 152 153 *t = Time(v + va) 154 155 default: 156 return fmt.Errorf("invalid time %q", string(b)) 157 } 158 return nil 159 } 160 161 // Duration wraps time.Duration. It is used to parse the custom duration format 162 // from YAML. 163 // This type should not propagate beyond the scope of input/output processing. 164 type Duration time.Duration 165 166 // Set implements pflag/flag.Value 167 func (d *Duration) Set(s string) error { 168 var err error 169 *d, err = ParseDuration(s) 170 return err 171 } 172 173 // Type implements pflag.Value 174 func (d *Duration) Type() string { 175 return "duration" 176 } 177 178 var durationRE = regexp.MustCompile("^([0-9]+)(y|w|d|h|m|s|ms)$") 179 180 // ParseDuration parses a string into a time.Duration, assuming that a year 181 // always has 365d, a week always has 7d, and a day always has 24h. 182 func ParseDuration(durationStr string) (Duration, error) { 183 matches := durationRE.FindStringSubmatch(durationStr) 184 if len(matches) != 3 { 185 return 0, fmt.Errorf("not a valid duration string: %q", durationStr) 186 } 187 var ( 188 n, _ = strconv.Atoi(matches[1]) 189 dur = time.Duration(n) * time.Millisecond 190 ) 191 switch unit := matches[2]; unit { 192 case "y": 193 dur *= 1000 * 60 * 60 * 24 * 365 194 case "w": 195 dur *= 1000 * 60 * 60 * 24 * 7 196 case "d": 197 dur *= 1000 * 60 * 60 * 24 198 case "h": 199 dur *= 1000 * 60 * 60 200 case "m": 201 dur *= 1000 * 60 202 case "s": 203 dur *= 1000 204 case "ms": 205 // Value already correct 206 default: 207 return 0, fmt.Errorf("invalid time unit in duration string: %q", unit) 208 } 209 return Duration(dur), nil 210 } 211 212 func (d Duration) String() string { 213 var ( 214 ms = int64(time.Duration(d) / time.Millisecond) 215 unit = "ms" 216 ) 217 if ms == 0 { 218 return "0s" 219 } 220 factors := map[string]int64{ 221 "y": 1000 * 60 * 60 * 24 * 365, 222 "w": 1000 * 60 * 60 * 24 * 7, 223 "d": 1000 * 60 * 60 * 24, 224 "h": 1000 * 60 * 60, 225 "m": 1000 * 60, 226 "s": 1000, 227 "ms": 1, 228 } 229 230 switch int64(0) { 231 case ms % factors["y"]: 232 unit = "y" 233 case ms % factors["w"]: 234 unit = "w" 235 case ms % factors["d"]: 236 unit = "d" 237 case ms % factors["h"]: 238 unit = "h" 239 case ms % factors["m"]: 240 unit = "m" 241 case ms % factors["s"]: 242 unit = "s" 243 } 244 return fmt.Sprintf("%v%v", ms/factors[unit], unit) 245 } 246 247 // MarshalYAML implements the yaml.Marshaler interface. 248 func (d Duration) MarshalYAML() (interface{}, error) { 249 return d.String(), nil 250 } 251 252 // UnmarshalYAML implements the yaml.Unmarshaler interface. 253 func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error { 254 var s string 255 if err := unmarshal(&s); err != nil { 256 return err 257 } 258 dur, err := ParseDuration(s) 259 if err != nil { 260 return err 261 } 262 *d = dur 263 return nil 264 }