-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
time.go
237 lines (196 loc) · 5.34 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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package utils
import (
"context"
"strconv"
"sync"
"sync/atomic"
"time"
"github.com/Laisky/errors/v2"
)
const (
// TimeFormatDate "2006-01-02"
TimeFormatDate = "2006-01-02"
// Nano2Sec 1e9
Nano2Sec = 1e9
// BitSize64 64
BitSize64 = 64
// BaseHex 16
BaseHex = 16
)
// SleepWithContext sleep duration with context, if context is done, return
func SleepWithContext(ctx context.Context, duration time.Duration) {
ctx, cancel := context.WithTimeout(ctx, duration)
defer cancel()
<-ctx.Done()
}
// UTCNow get current time in utc
func UTCNow() time.Time {
return time.Now().UTC()
}
// ParseUnix2String can parse unix timestamp(int64) to string
func ParseUnix2String(ts int64, layout string) string {
return ParseUnix2UTC(ts).Format(layout)
}
// ParseUnix2UTC convert unix to UTC time
func ParseUnix2UTC(ts int64) time.Time {
return time.Unix(ts, 0).UTC()
}
var (
// ParseTs2UTC can parse unix timestamp(int64) to time.Time
ParseTs2UTC = ParseUnix2UTC
// ParseTs2String can parse unix timestamp(int64) to string
ParseTs2String = ParseUnix2String
)
// ParseUnixNano2UTC convert unixnano to UTC time
func ParseUnixNano2UTC(ts int64) time.Time {
return time.Unix(ts/Nano2Sec, ts%Nano2Sec).UTC()
}
// ParseHex2UTC parse hex to UTC time
func ParseHex2UTC(ts string) (t time.Time, err error) {
var ut int64
if ut, err = strconv.ParseInt(ts, BaseHex, BitSize64); err != nil {
return
}
return ParseUnix2UTC(ut), nil
}
// TimeEqual compare two time with difference,
// return true if time difference less than difference
func TimeEqual(ts1, ts2 time.Time, difference time.Duration) bool {
sub := ts1.Sub(ts2)
return sub < difference && sub > -difference
}
// ParseHexNano2UTC parse hex contains nano to UTC time
func ParseHexNano2UTC(ts string) (t time.Time, err error) {
var ut int64
if ut, err = strconv.ParseInt(ts, BaseHex, BitSize64); err != nil {
return
}
return ParseUnixNano2UTC(ut), nil
}
// ParseTimeWithTruncate parse time with truncate
func ParseTimeWithTruncate(layout, value string, precision time.Duration) (t time.Time, err error) {
t, err = time.Parse(layout, value)
if err != nil {
return t, errors.Wrap(err, "parse time")
}
return t.Truncate(precision), nil
}
var ( // compatable to old version
// ParseTs2Time can parse unix timestamp(int64) to time.Time
ParseTs2Time = ParseTs2UTC
// UnixNano2UTC convert unixnano to UTC time
UnixNano2UTC = ParseUnixNano2UTC
)
// ---------------------------------------
// Clock
// ---------------------------------------
// ClockItf high performance lazy clock
type ClockItf interface {
Close()
runRefresh(ctx context.Context)
GetUTCNow() time.Time
GetDate() (time.Time, error)
GetTimeInRFC3339Nano() string
SetInterval(interval time.Duration)
GetTimeInHex() string
GetNanoTimeInHex() string
Interval() time.Duration
}
const defaultClockInterval = 10 * time.Millisecond
// SetInternalClock set internal Clock with refresh interval
func SetInternalClock(interval time.Duration) {
if interval < time.Microsecond {
panic("interval must greater than 1us")
}
if Clock == nil {
Clock = NewClock(context.Background(), interval)
} else {
Clock.SetInterval(interval)
}
}
var (
// Clock high performance time utils, replace Clock1
Clock = NewClock(context.Background(), defaultClockInterval)
)
// ClockT high performance ClockT with lazy refreshing
type ClockT struct {
sync.RWMutex
stopChan chan struct{}
interval time.Duration
now int64
}
// NewClock create new Clock
func NewClock(ctx context.Context, refreshInterval time.Duration) *ClockT {
c := &ClockT{
interval: refreshInterval,
now: UTCNow().UnixNano(),
stopChan: make(chan struct{}),
}
go c.runRefresh(ctx)
return c
}
// Close stop Clock update
func (c *ClockT) Close() {
c.stopChan <- struct{}{}
}
func (c *ClockT) runRefresh(ctx context.Context) {
var interval time.Duration
for {
select {
case <-c.stopChan:
return
case <-ctx.Done():
return
default:
c.RLock()
interval = c.interval
c.RUnlock()
time.Sleep(interval)
}
atomic.StoreInt64(&c.now, time.Now().UnixNano())
}
}
// GetUTCNow return Clock current time.Time
func (c *ClockT) GetUTCNow() time.Time {
return ParseUnixNano2UTC(atomic.LoadInt64(&c.now))
}
// GetDate return "yyyy-mm-dd"
func (c *ClockT) GetDate() (time.Time, error) {
return time.Parse(TimeFormatDate, c.GetUTCNow().Format(TimeFormatDate))
}
// GetTimeInRFC3339Nano return Clock current time in string
func (c *ClockT) GetTimeInRFC3339Nano() string {
return c.GetUTCNow().Format(time.RFC3339Nano)
}
// SetInterval setup update interval
func (c *ClockT) SetInterval(interval time.Duration) {
c.Lock()
defer c.Unlock()
c.interval = interval
}
// GetTimeInHex return current time in hex
func (c *ClockT) GetTimeInHex() string {
return strconv.FormatInt(c.GetUTCNow().Unix(), BaseHex)
}
// GetNanoTimeInHex return current time with nano in hex
func (c *ClockT) GetNanoTimeInHex() string {
return strconv.FormatInt(c.GetUTCNow().UnixNano(), BaseHex)
}
// Interval get current interval
func (c *ClockT) Interval() time.Duration {
c.RLock()
defer c.RUnlock()
return c.interval
}
var (
// TimeZoneUTC timezone UTC
TimeZoneUTC = time.UTC
// TimeZoneShanghai timezone Shanghai
// TimeZoneShanghai = time.FixedZone("Asia/Shanghai", 8*3600)
TimeZoneShanghai *time.Location
)
func init() {
var err error
TimeZoneShanghai, err = time.LoadLocation("Asia/Shanghai")
PanicIfErr(err)
}