-
Notifications
You must be signed in to change notification settings - Fork 453
/
timing.go
100 lines (88 loc) · 3.37 KB
/
timing.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package util
import (
"fmt"
"math"
"strconv"
"time"
xerrors "github.com/m3db/m3/src/x/errors"
"github.com/prometheus/common/model"
)
var (
minTime = time.Unix(math.MinInt64/1000+62135596801, 0).UTC()
maxTime = time.Unix(math.MaxInt64/1000-62135596801, 999999999).UTC()
minTimeFormatted = minTime.Format(time.RFC3339Nano)
maxTimeFormatted = maxTime.Format(time.RFC3339Nano)
)
// ParseTimeString parses a time string into time.Time.
func ParseTimeString(s string) (time.Time, error) {
if t, err := strconv.ParseFloat(s, 64); err == nil {
s, ns := math.Modf(t)
ns = math.Round(ns*1000) / 1000
return time.Unix(int64(s), int64(ns*float64(time.Second))), nil
}
if t, err := time.Parse(time.RFC3339Nano, s); err == nil {
return t, nil
}
// Stdlib's time parser can only handle 4 digit years. As a workaround until
// that is fixed we want to at least support our own boundary times.
// Context: https://github.com/prometheus/client_golang/issues/614
// Upstream issue: https://github.com/golang/go/issues/20555
switch s {
case minTimeFormatted:
return time.Unix(0, 0), nil
case maxTimeFormatted:
return time.Now(), nil
}
return time.Time{}, xerrors.NewInvalidParamsError(
fmt.Errorf("invalid timestamp for %s", s))
}
// ParseTimeStringWithDefault parses a time string into time.Time.
func ParseTimeStringWithDefault(
s string,
defaultTime time.Time,
) (time.Time, error) {
if s != "" {
return ParseTimeString(s)
}
return defaultTime, nil
}
// ParseDurationString parses a string duration allows for
// float seconds and also time strings such as 7d5h, etc.
func ParseDurationString(s string) (time.Duration, error) {
if d, err := strconv.ParseFloat(s, 64); err == nil {
ts := d * float64(time.Second)
if ts > float64(math.MaxInt64) || ts < float64(math.MinInt64) {
return 0, xerrors.NewInvalidParamsError(
fmt.Errorf("cannot parse %q to a valid duration. It overflows int64", s))
}
return time.Duration(ts), nil
}
if d, err := model.ParseDuration(s); err == nil {
return time.Duration(d), nil
}
return 0, xerrors.NewInvalidParamsError(
fmt.Errorf("cannot parse %q to a valid duration", s))
}
// DurationToMS converts a duration into milliseconds
func DurationToMS(duration time.Duration) int64 {
return duration.Nanoseconds() / int64(time.Millisecond)
}