Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / prometheus / common / model / time.go
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 }