-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtime.go
286 lines (244 loc) · 6.86 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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
package utils
import (
"context"
"time"
"github.com/fufuok/utils/pools/timerpool"
)
// InitCSTLocation 初始化默认时区为中国东八区(GMT+8)
// 返回值:
// name: "Asia/Shanghai" 或本地时区名称
// loc: 优先尝试解析中国时区, 失败(Windows)后使用本地时区(time.Local)
// cst: 强制偏移的中国时区, !!!注意: 无法使用 time.LoadLocation(cst.String()) 二次加载
// ok: true 表示初始化中国时区成功, false 表示 local 不一定是中国时区
func InitCSTLocation() (name string, loc *time.Location, cst *time.Location, ok bool) {
name = "Asia/Shanghai"
loc, ok = InitLocation(name)
time.Local = loc
name = loc.String()
cst = time.FixedZone("CST", 8*60*60)
return
}
// InitLocation 解析并初始化本地时区
func InitLocation(name string) (*time.Location, bool) {
loc, err := time.LoadLocation(name)
if err != nil {
return time.Local, false
}
return loc, true
}
// WaitUntilMinute 等待, 直到 m 分钟
func WaitUntilMinute(m int, t ...time.Time) {
var now time.Time
if len(t) > 0 {
now = t[0]
} else {
now = time.Now()
}
n := m - now.Minute()
if n < 0 {
n += 60
}
timer := timerpool.New(time.Duration(n) * time.Minute)
<-timer.C
timerpool.Release(timer)
}
// WaitNextMinute 下一分钟, 对齐时间, 0 秒
func WaitNextMinute(t ...time.Time) {
_ = WaitNextMinuteWithTime(t...)
}
// WaitNextMinuteWithTime 下一分钟, 对齐时间, 0 秒
func WaitNextMinuteWithTime(t ...time.Time) (now time.Time) {
var start time.Time
if len(t) > 0 {
start = t[0]
} else {
start = time.Now()
}
now = BeginOfMinute(start.Add(time.Minute))
timer := timerpool.New(now.Sub(start))
<-timer.C
timerpool.Release(timer)
return
}
// WaitUntilSecond 等待, 直到 s 秒
func WaitUntilSecond(s int, t ...time.Time) {
var now time.Time
if len(t) > 0 {
now = t[0]
} else {
now = time.Now()
}
n := s - now.Second()
if n < 0 {
n += 60
}
timer := timerpool.New(time.Duration(n) * time.Second)
<-timer.C
timerpool.Release(timer)
}
// WaitNextSecond 下一秒, 对齐时间, 0 毫秒 (近似)
func WaitNextSecond(t ...time.Time) {
_ = WaitNextSecondWithTime(t...)
}
// WaitNextSecondWithTime 下一秒, 对齐时间, 0 毫秒 (近似)
func WaitNextSecondWithTime(t ...time.Time) (now time.Time) {
var start time.Time
if len(t) > 0 {
start = t[0]
} else {
start = time.Now()
}
now = BeginOfSecond(start.Add(time.Second))
timer := timerpool.New(now.Sub(start))
<-timer.C
timerpool.Release(timer)
return
}
// BeginOfDay 当天 0 点
func BeginOfDay(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, 0, 0, 0, 0, t.Location())
}
// EndOfDay 当天最后时刻
func EndOfDay(t time.Time) time.Time {
return BeginOfTomorrow(t).Add(-time.Nanosecond)
}
// BeginOfYesterday 昨天 0 点
func BeginOfYesterday(t time.Time) time.Time {
return BeginOfDay(t.AddDate(0, 0, -1))
}
// EndOfYesterday 昨天最后时刻
func EndOfYesterday(t time.Time) time.Time {
return EndOfDay(t.AddDate(0, 0, -1))
}
// BeginOfTomorrow 明天 0 点
func BeginOfTomorrow(t time.Time) time.Time {
return BeginOfDay(t.AddDate(0, 0, 1))
}
// EndOfTomorrow 明天 0 点
func EndOfTomorrow(t time.Time) time.Time {
return EndOfDay(t.AddDate(0, 0, 1))
}
// BeginOfSecond 0 毫秒
func BeginOfSecond(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), t.Minute(), t.Second(), 0, t.Location())
}
// EndOfSecond 最后一毫秒
func EndOfSecond(t time.Time) time.Time {
return BeginOfSecond(t).Add(time.Second - time.Nanosecond)
}
// BeginOfMinute 0 秒
func BeginOfMinute(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), t.Minute(), 0, 0, t.Location())
}
// EndOfMinute 最后一秒
func EndOfMinute(t time.Time) time.Time {
return BeginOfMinute(t).Add(time.Minute - time.Nanosecond)
}
// BeginOfHour 0 分
func BeginOfHour(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), 0, 0, 0, t.Location())
}
// EndOfHour 最后一分
func EndOfHour(t time.Time) time.Time {
return BeginOfHour(t).Add(time.Hour - time.Nanosecond)
}
// BeginOfWeek 本周一 0 点
func BeginOfWeek(t time.Time) time.Time {
offset := int(time.Monday - t.Weekday())
if offset > 0 {
offset = -6
}
return BeginOfDay(t).AddDate(0, 0, offset)
}
// EndOfWeek 本周末最后一刻
func EndOfWeek(t time.Time) time.Time {
return BeginOfNextWeek(t).Add(-time.Nanosecond)
}
// BeginOfLastWeek 上周一 0 点
func BeginOfLastWeek(t time.Time) time.Time {
return BeginOfWeek(t.AddDate(0, 0, -7))
}
// EndOfLastWeek 上周一最后一刻
func EndOfLastWeek(t time.Time) time.Time {
return EndOfWeek(t.AddDate(0, 0, -7))
}
// BeginOfNextWeek 下周一 0 点
func BeginOfNextWeek(t time.Time) time.Time {
return BeginOfWeek(t.AddDate(0, 0, 7))
}
// EndOfNextWeek 下周一最后一刻
func EndOfNextWeek(t time.Time) time.Time {
return EndOfWeek(t.AddDate(0, 0, 7))
}
// BeginOfMonth 当月第一天 0 点
func BeginOfMonth(t time.Time) time.Time {
y, m, _ := t.Date()
return time.Date(y, m, 1, 0, 0, 0, 0, t.Location())
}
// EndOfMonth 当月最后一刻
func EndOfMonth(t time.Time) time.Time {
return BeginOfNextMonth(t).Add(-time.Nanosecond)
}
// BeginOfLastMonth 上月第一天 0 点
func BeginOfLastMonth(t time.Time) time.Time {
return BeginOfMonth(BeginOfMonth(t).AddDate(0, 0, -1))
}
// EndOfLastMonth 上月最后一刻
func EndOfLastMonth(t time.Time) time.Time {
return BeginOfMonth(t).Add(-time.Nanosecond)
}
// BeginOfNextMonth 下月第一天 0 点
func BeginOfNextMonth(t time.Time) time.Time {
return BeginOfMonth(BeginOfMonth(t).AddDate(0, 0, 31))
}
// EndOfNextMonth 下月最后一刻
func EndOfNextMonth(t time.Time) time.Time {
return BeginOfMonth(BeginOfMonth(t).AddDate(0, 0, 62)).Add(-time.Nanosecond)
}
// GetMonthDays 当月天数
func GetMonthDays(t time.Time) int {
return int(BeginOfNextMonth(t).Sub(BeginOfMonth(t)).Hours() / 24)
}
// BeginOfYear 本年第一天 0 点
func BeginOfYear(t time.Time) time.Time {
return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, t.Location())
}
// EndOfYear 本年最后一刻
func EndOfYear(t time.Time) time.Time {
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
}
// Sleep 支持上下文中断的 time.Sleep
func Sleep(ctx context.Context, interval time.Duration) error {
timer := timerpool.New(interval)
select {
case <-ctx.Done():
timerpool.Release(timer)
return ctx.Err()
case <-timer.C:
timerpool.Release(timer)
return nil
}
}
// IsLeapYear 判断是否为闰年
func IsLeapYear(year int) bool {
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
}
// DaysInYear 返回年份天数
func DaysInYear(year int) int {
if IsLeapYear(year) {
return 366
}
return 365
}
var daysInMonth = [13]int{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
// DaysInMonth 返回月份天数
func DaysInMonth(year int, m time.Month) int {
if m == time.February && IsLeapYear(year) {
return 29
}
return daysInMonth[m]
}