time.go 8.7 KB

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