Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

318 rindas
7.9 KiB

  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. package model
  14. import (
  15. "encoding/json"
  16. "errors"
  17. "fmt"
  18. "math"
  19. "regexp"
  20. "strconv"
  21. "strings"
  22. "time"
  23. )
  24. const (
  25. // MinimumTick is the minimum supported time resolution. This has to be
  26. // at least time.Second in order for the code below to work.
  27. minimumTick = time.Millisecond
  28. // second is the Time duration equivalent to one second.
  29. second = int64(time.Second / minimumTick)
  30. // The number of nanoseconds per minimum tick.
  31. nanosPerTick = int64(minimumTick / time.Nanosecond)
  32. // Earliest is the earliest Time representable. Handy for
  33. // initializing a high watermark.
  34. Earliest = Time(math.MinInt64)
  35. // Latest is the latest Time representable. Handy for initializing
  36. // a low watermark.
  37. Latest = Time(math.MaxInt64)
  38. )
  39. // Time is the number of milliseconds since the epoch
  40. // (1970-01-01 00:00 UTC) excluding leap seconds.
  41. type Time int64
  42. // Interval describes an interval between two timestamps.
  43. type Interval struct {
  44. Start, End Time
  45. }
  46. // Now returns the current time as a Time.
  47. func Now() Time {
  48. return TimeFromUnixNano(time.Now().UnixNano())
  49. }
  50. // TimeFromUnix returns the Time equivalent to the Unix Time t
  51. // provided in seconds.
  52. func TimeFromUnix(t int64) Time {
  53. return Time(t * second)
  54. }
  55. // TimeFromUnixNano returns the Time equivalent to the Unix Time
  56. // t provided in nanoseconds.
  57. func TimeFromUnixNano(t int64) Time {
  58. return Time(t / nanosPerTick)
  59. }
  60. // Equal reports whether two Times represent the same instant.
  61. func (t Time) Equal(o Time) bool {
  62. return t == o
  63. }
  64. // Before reports whether the Time t is before o.
  65. func (t Time) Before(o Time) bool {
  66. return t < o
  67. }
  68. // After reports whether the Time t is after o.
  69. func (t Time) After(o Time) bool {
  70. return t > o
  71. }
  72. // Add returns the Time t + d.
  73. func (t Time) Add(d time.Duration) Time {
  74. return t + Time(d/minimumTick)
  75. }
  76. // Sub returns the Duration t - o.
  77. func (t Time) Sub(o Time) time.Duration {
  78. return time.Duration(t-o) * minimumTick
  79. }
  80. // Time returns the time.Time representation of t.
  81. func (t Time) Time() time.Time {
  82. return time.Unix(int64(t)/second, (int64(t)%second)*nanosPerTick)
  83. }
  84. // Unix returns t as a Unix time, the number of seconds elapsed
  85. // since January 1, 1970 UTC.
  86. func (t Time) Unix() int64 {
  87. return int64(t) / second
  88. }
  89. // UnixNano returns t as a Unix time, the number of nanoseconds elapsed
  90. // since January 1, 1970 UTC.
  91. func (t Time) UnixNano() int64 {
  92. return int64(t) * nanosPerTick
  93. }
  94. // The number of digits after the dot.
  95. var dotPrecision = int(math.Log10(float64(second)))
  96. // String returns a string representation of the Time.
  97. func (t Time) String() string {
  98. return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64)
  99. }
  100. // MarshalJSON implements the json.Marshaler interface.
  101. func (t Time) MarshalJSON() ([]byte, error) {
  102. return []byte(t.String()), nil
  103. }
  104. // UnmarshalJSON implements the json.Unmarshaler interface.
  105. func (t *Time) UnmarshalJSON(b []byte) error {
  106. p := strings.Split(string(b), ".")
  107. switch len(p) {
  108. case 1:
  109. v, err := strconv.ParseInt(string(p[0]), 10, 64)
  110. if err != nil {
  111. return err
  112. }
  113. *t = Time(v * second)
  114. case 2:
  115. v, err := strconv.ParseInt(string(p[0]), 10, 64)
  116. if err != nil {
  117. return err
  118. }
  119. v *= second
  120. prec := dotPrecision - len(p[1])
  121. if prec < 0 {
  122. p[1] = p[1][:dotPrecision]
  123. } else if prec > 0 {
  124. p[1] = p[1] + strings.Repeat("0", prec)
  125. }
  126. va, err := strconv.ParseInt(p[1], 10, 32)
  127. if err != nil {
  128. return err
  129. }
  130. // If the value was something like -0.1 the negative is lost in the
  131. // parsing because of the leading zero, this ensures that we capture it.
  132. if len(p[0]) > 0 && p[0][0] == '-' && v+va > 0 {
  133. *t = Time(v+va) * -1
  134. } else {
  135. *t = Time(v + va)
  136. }
  137. default:
  138. return fmt.Errorf("invalid time %q", string(b))
  139. }
  140. return nil
  141. }
  142. // Duration wraps time.Duration. It is used to parse the custom duration format
  143. // from YAML.
  144. // This type should not propagate beyond the scope of input/output processing.
  145. type Duration time.Duration
  146. // Set implements pflag/flag.Value
  147. func (d *Duration) Set(s string) error {
  148. var err error
  149. *d, err = ParseDuration(s)
  150. return err
  151. }
  152. // Type implements pflag.Value
  153. func (d *Duration) Type() string {
  154. return "duration"
  155. }
  156. var durationRE = regexp.MustCompile("^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$")
  157. // ParseDuration parses a string into a time.Duration, assuming that a year
  158. // always has 365d, a week always has 7d, and a day always has 24h.
  159. func ParseDuration(durationStr string) (Duration, error) {
  160. switch durationStr {
  161. case "0":
  162. // Allow 0 without a unit.
  163. return 0, nil
  164. case "":
  165. return 0, errors.New("empty duration string")
  166. }
  167. matches := durationRE.FindStringSubmatch(durationStr)
  168. if matches == nil {
  169. return 0, fmt.Errorf("not a valid duration string: %q", durationStr)
  170. }
  171. var dur time.Duration
  172. // Parse the match at pos `pos` in the regex and use `mult` to turn that
  173. // into ms, then add that value to the total parsed duration.
  174. var overflowErr error
  175. m := func(pos int, mult time.Duration) {
  176. if matches[pos] == "" {
  177. return
  178. }
  179. n, _ := strconv.Atoi(matches[pos])
  180. // Check if the provided duration overflows time.Duration (> ~ 290years).
  181. if n > int((1<<63-1)/mult/time.Millisecond) {
  182. overflowErr = errors.New("duration out of range")
  183. }
  184. d := time.Duration(n) * time.Millisecond
  185. dur += d * mult
  186. if dur < 0 {
  187. overflowErr = errors.New("duration out of range")
  188. }
  189. }
  190. m(2, 1000*60*60*24*365) // y
  191. m(4, 1000*60*60*24*7) // w
  192. m(6, 1000*60*60*24) // d
  193. m(8, 1000*60*60) // h
  194. m(10, 1000*60) // m
  195. m(12, 1000) // s
  196. m(14, 1) // ms
  197. return Duration(dur), overflowErr
  198. }
  199. func (d Duration) String() string {
  200. var (
  201. ms = int64(time.Duration(d) / time.Millisecond)
  202. r = ""
  203. )
  204. if ms == 0 {
  205. return "0s"
  206. }
  207. f := func(unit string, mult int64, exact bool) {
  208. if exact && ms%mult != 0 {
  209. return
  210. }
  211. if v := ms / mult; v > 0 {
  212. r += fmt.Sprintf("%d%s", v, unit)
  213. ms -= v * mult
  214. }
  215. }
  216. // Only format years and weeks if the remainder is zero, as it is often
  217. // easier to read 90d than 12w6d.
  218. f("y", 1000*60*60*24*365, true)
  219. f("w", 1000*60*60*24*7, true)
  220. f("d", 1000*60*60*24, false)
  221. f("h", 1000*60*60, false)
  222. f("m", 1000*60, false)
  223. f("s", 1000, false)
  224. f("ms", 1, false)
  225. return r
  226. }
  227. // MarshalJSON implements the json.Marshaler interface.
  228. func (d Duration) MarshalJSON() ([]byte, error) {
  229. return json.Marshal(d.String())
  230. }
  231. // UnmarshalJSON implements the json.Unmarshaler interface.
  232. func (d *Duration) UnmarshalJSON(bytes []byte) error {
  233. var s string
  234. if err := json.Unmarshal(bytes, &s); err != nil {
  235. return err
  236. }
  237. dur, err := ParseDuration(s)
  238. if err != nil {
  239. return err
  240. }
  241. *d = dur
  242. return nil
  243. }
  244. // MarshalText implements the encoding.TextMarshaler interface.
  245. func (d *Duration) MarshalText() ([]byte, error) {
  246. return []byte(d.String()), nil
  247. }
  248. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  249. func (d *Duration) UnmarshalText(text []byte) error {
  250. var err error
  251. *d, err = ParseDuration(string(text))
  252. return err
  253. }
  254. // MarshalYAML implements the yaml.Marshaler interface.
  255. func (d Duration) MarshalYAML() (interface{}, error) {
  256. return d.String(), nil
  257. }
  258. // UnmarshalYAML implements the yaml.Unmarshaler interface.
  259. func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
  260. var s string
  261. if err := unmarshal(&s); err != nil {
  262. return err
  263. }
  264. dur, err := ParseDuration(s)
  265. if err != nil {
  266. return err
  267. }
  268. *d = dur
  269. return nil
  270. }