/
timeutil.go
289 lines (256 loc) · 6.81 KB
/
timeutil.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
287
288
289
// timeutil provides a set of time utilities including comparisons,
// conversion to "DT8" int32 and "DT14" int64 formats and other
// capabilities.
package timeutil
import (
"fmt"
"strconv"
"time"
)
// TimeOpts represnts a struct for `time.Date`.
type TimeOpts struct {
Year int
Month int
Day int
Hour int
Minute int
Second int
Nanosecond int
Location *time.Location
}
// Time returns a `time.Time` struct. If no `Location`
// is set, `time.UTC` is used.
func (opts TimeOpts) Time() time.Time {
if opts.Location == nil {
opts.Location = time.UTC
}
return time.Date(
opts.Year,
time.Month(opts.Month),
opts.Day,
opts.Hour,
opts.Minute,
opts.Second,
opts.Nanosecond,
opts.Location)
}
func MustParse(layout, value string) time.Time {
t, err := time.Parse(layout, value)
if err != nil {
panic(err)
}
return t
}
// UnixToDay converts an epoch in seconds to a time.Time for the day.
func UnixToDay(epoch int64) time.Time {
return NewTimeMore(time.Unix(epoch, 0).UTC(), 0).DayStart()
}
// DT6 returns the Dt6 value for time.Time.
func (tm TimeMore) DT6() int32 {
return int32(tm.time.Year()*100 + int(tm.time.Month()))
}
// DT6ForDT14 returns the Dt6 value for Dt14.
func DT6ForDT14(dt14 int64) int32 {
return int32(float64(dt14) / float64(1000000))
}
// TimeForDT6 returns a time.Time value given a Dt6 value.
func TimeForDT6(dt6 int32) (time.Time, error) {
return time.Parse(DT6, strconv.FormatInt(int64(dt6), 10))
}
func DT6Parse(dt6 int32) (int16, int8) {
year := dt6 / 100
month := int(dt6) - (int(year) * 100)
return int16(year), int8(month)
}
func DT6Prev(dt6 int32) int32 {
year, month := DT6Parse(dt6)
if month == 1 {
month = 12
year = year - 1
} else {
month = month - 1
}
return int32(year)*100 + int32(month)
}
func DT6Next(dt6 int32) int32 {
year, month := DT6Parse(dt6)
if month == 12 {
month = 1
year++
} else {
month++
}
return int32(year)*100 + int32(month)
}
func TimeDT6AddNMonths(t time.Time, numMonths int) time.Time {
if numMonths == 0 {
return t
} else if numMonths < 0 {
return timeDT6SubNMonths(t, uint(-numMonths))
}
dt6 := NewTimeMore(t, 0).DT6()
for i := 0; i < numMonths; i++ {
dt6 = DT6Next(dt6)
}
dt6NextMonth, err := TimeForDT6(dt6)
if err != nil {
panic(fmt.Sprintf("Cannot find next month for time: %v\n", t.Format(time.RFC3339)))
}
return dt6NextMonth
}
func timeDT6SubNMonths(t time.Time, numMonths uint) time.Time {
if numMonths == 0 {
return t
}
dt6 := NewTimeMore(t, 0).DT6()
for i := uint(0); i < numMonths; i++ {
dt6 = DT6Prev(dt6)
}
dt6NextMonth, err := TimeForDT6(dt6)
if err != nil {
panic(fmt.Sprintf("Cannot find next month for time: %v\n", t.Format(time.RFC3339)))
}
return dt6NextMonth
}
func TimeDT4AddNYears(t time.Time, numYears int) time.Time {
return time.Date(t.Year()+numYears, time.January, 1, 0, 0, 0, 0, t.Location())
}
func DT6MinMaxSlice(minDt6 int32, maxDt6 int32) []int32 {
if maxDt6 < minDt6 {
tmpDt6 := maxDt6
maxDt6 = minDt6
minDt6 = tmpDt6
}
dt6Range := []int32{}
curDt6 := minDt6
for curDt6 < maxDt6+1 {
dt6Range = append(dt6Range, curDt6)
curDt6 = DT6Next(curDt6)
}
return dt6Range
}
/*
// Dt8Now returns Dt8 value for the current time.
func Dt8Now() int32 {
return Dt8ForTime(time.Now())
}
// DT8ForString returns a Dt8 value given a layout and value to parse to time.Parse.
func DT8ForString(layout, value string) (int32, error) {
dt8 := int32(0)
t, err := time.Parse(layout, value)
if err == nil {
dt8 = NewTimeMore(t, 0).DT8()
}
return dt8, err
}
// DT8ForInts returns a Dt8 value for year, month, and day.
func DT8ForInts(yyyy, mm, dd int) int32 {
sDt8 := fmt.Sprintf("%04d%02d%02d", yyyy, mm, dd)
iDt8, err := strconv.ParseInt(sDt8, 10, 32)
if err != nil {
panic(err)
}
return int32(iDt8)
}
// TimeForDT8 returns a time.Time value given a Dt8 value.
func TimeForDT8(dt8 int32) (time.Time, error) {
return time.Parse(DT8, strconv.FormatInt(int64(dt8), 10))
}
// Dt14Now returns a Dt14 value for the current time.
func Dt14Now() int64 {
return Dt14ForTime(time.Now())
}
*/
// Dt8ForTime returns a `DateTime8` value given a time struct.
func (tm TimeMore) DT8() (DateTime8, error) {
if !dt8TimeInbounds(tm.time) {
return 0, ErrDateTime8OutOfBounds
}
s := tm.time.Format(DT8)
iDt8, err := strconv.ParseInt(s, 10, 32)
if err != nil {
panic(err)
}
return DateTime8(iDt8), nil
}
// DT14ForString returns a DT14 value given a layout and value to parse to time.Parse.
func DT14ForString(layout, value string) (int64, error) {
dt14 := int64(0)
t, err := time.Parse(layout, value)
if err == nil {
dt14 = NewTimeMore(t, 0).DT14()
}
return dt14, err
}
// DT14ForInts returns a Dt8 value for a UTC year, month, day, hour, minute and second.
func DT14ForInts(yyyy, mm, dd, hr, mn, dy int) int64 {
sDt14 := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", yyyy, mm, dd, hr, mn, dy)
iDt14, err := strconv.ParseInt(sDt14, 10, 64)
if err != nil {
panic(err)
}
return iDt14
}
// Dt14ForTime returns a Dt14 value given a time.Time struct.
func (tm TimeMore) DT14() int64 {
s := tm.time.Format(DT14)
iDt14, err := strconv.ParseInt(s, 10, 64)
if err != nil {
panic(err)
}
return iDt14
}
// TimeForDT14 returns a time.Time value given a Dt14 value.
func TimeForDT14(dt14 int64) (time.Time, error) {
return time.Parse(DT14, strconv.FormatInt(dt14, 10))
}
/*
// WeekStart takes a time.Time object and a week start day
// in the time.Weekday format.
func WeekStart(dt time.Time, dow time.Weekday) (time.Time, error) {
return TimeDeltaDowInt(dt.UTC(), int(dow), -1, true, true)
}
// MonthStart returns a time.Time for the beginning of the
// month in UTC time.
func MonthStart(dt time.Time) time.Time {
dt = dt.UTC()
return time.Date(dt.Year(), dt.Month(), 1, 0, 0, 0, 0, time.UTC)
}
// QuarterEnd returns a time.Time for the end of the
// quarter by second in UTC time.
func QuarterEnd(dt time.Time) time.Time {
qs := QuarterStart(dt.UTC())
qn := TimeDt6AddNMonths(qs, 3)
return time.Date(qn.Year(), qn.Month(), 0, 23, 59, 59, 0, time.UTC)
}
// YearStart returns a a time.Time for the beginning of the year
// in UTC time.
func YearStart(dt time.Time) time.Time {
return time.Date(dt.UTC().Year(), time.January, 1, 0, 0, 0, 0, time.UTC)
}
// YearEnd returns a a time.Time for the end of the year in UTC time.
func YearEnd(dt time.Time) time.Time {
return time.Date(dt.UTC().Year(), time.December, 31, 23, 59, 59, 999999999, time.UTC)
}
func NextYearStart(dt time.Time) time.Time {
return time.Date(dt.UTC().Year()+1, time.January, 1, 0, 0, 0, 0, time.UTC)
}
func IsYearStart(t time.Time) bool {
t = t.UTC()
if t.Nanosecond() == 0 &&
t.Second() == 0 &&
t.Minute() == 0 &&
t.Hour() == 0 &&
t.Day() == 1 &&
t.Month() == time.January {
return true
}
return false
}
func ToMonthStart(t time.Time) time.Time {
return time.Date(
t.Year(), t.Month(), 1,
0, 0, 0, 0,
t.Location())
}
*/