-
Notifications
You must be signed in to change notification settings - Fork 0
/
time.go
135 lines (102 loc) · 3.45 KB
/
time.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//go:build !windows
// +build !windows
package hrtime
// Central Standard Time (CST)
// https://www.timeanddate.com/time/zones/cst
// Coordinated Universal Time (UTC)
// Greenwich Mean Time (GMT)
import (
"sync/atomic"
"time"
"github.com/samber/lo"
"golang.org/x/sys/unix"
)
func NowIn(offset TimeZoneOffset) time.Time {
return time.Now().In(loadTZLocation(offset))
}
func NowInDefaultTZ() time.Time {
return NowIn(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset)))
}
func NowInUTC() time.Time {
return NowIn(TzUtc0Offset)
}
func MonotonicElapsed() time.Duration {
return time.Since(appStartTime)
}
func Since(beginTime time.Time) time.Duration {
return time.Since(beginTime)
}
var (
SdkClock = &sdkClockTime{}
GoMonotonicClock Clock = &goNonSysClockTime{}
goMonotonicStartTs int64
UnixMonotonicClock Clock = &unixNonSysClockTime{}
unixMonotonicStartTs int64
)
func ClockInit() {
appStartTime = time.Now().In(loadTZLocation(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset))))
goMonotonicStartTs = appStartTime.UnixNano()
ts := unix.Timespec{}
lo.Must0(unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts))
unixMonotonicStartTs = ts.Nano()
}
type goNonSysClockTime struct{}
func (g *goNonSysClockTime) now() time.Time {
nano := appStartTime.UnixNano() + g.MonotonicElapsed().Nanoseconds()
return time.UnixMilli(time.Duration(nano).Milliseconds())
}
func (g *goNonSysClockTime) NowIn(offset TimeZoneOffset) time.Time {
return g.now().In(loadTZLocation(offset))
}
func (g *goNonSysClockTime) NowInDefaultTZ() time.Time {
return g.NowIn(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset)))
}
func (g *goNonSysClockTime) NowInUTC() time.Time {
return g.NowIn(TzUtc0Offset)
}
func (g *goNonSysClockTime) MonotonicElapsed() time.Duration {
return time.Duration(time.Now().UnixNano() - goMonotonicStartTs)
}
func (g *goNonSysClockTime) Since(beginTime time.Time) time.Duration {
return time.Duration(time.Now().UnixNano() - beginTime.UnixNano())
}
type unixNonSysClockTime struct{}
func (u *unixNonSysClockTime) now() time.Time {
nano := appStartTime.UnixNano() + u.MonotonicElapsed().Nanoseconds()
return time.UnixMilli(time.Duration(nano).Milliseconds())
}
func (u *unixNonSysClockTime) NowIn(offset TimeZoneOffset) time.Time {
return u.now().In(loadTZLocation(offset))
}
func (u *unixNonSysClockTime) NowInDefaultTZ() time.Time {
return u.NowIn(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset)))
}
func (u *unixNonSysClockTime) NowInUTC() time.Time {
return u.NowIn(TzUtc0Offset)
}
func (u *unixNonSysClockTime) MonotonicElapsed() time.Duration {
ts := unix.Timespec{}
lo.Must0(unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts))
currentTs := ts.Nano()
return time.Duration(currentTs - unixMonotonicStartTs)
}
func (u *unixNonSysClockTime) Since(beginTime time.Time) time.Duration {
n := NowInDefaultTZ()
return time.Duration(n.Nanosecond() - beginTime.In(loadTZLocation(TimeZoneOffset(DefaultTimezoneOffset()))).Nanosecond())
}
type sdkClockTime struct{}
func (s *sdkClockTime) NowIn(offset TimeZoneOffset) time.Time {
return NowIn(offset)
}
func (s *sdkClockTime) NowInDefaultTZ() time.Time {
return s.NowIn(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset)))
}
func (s *sdkClockTime) NowInUTC() time.Time {
return s.NowIn(TzUtc0Offset)
}
func (s *sdkClockTime) MonotonicElapsed() time.Duration {
return MonotonicElapsed()
}
func (s *sdkClockTime) Since(beginTime time.Time) time.Duration {
return Since(beginTime)
}