-
Notifications
You must be signed in to change notification settings - Fork 8
/
dt8.go
125 lines (109 loc) · 3.09 KB
/
dt8.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
package timeutil
import (
"errors"
"fmt"
"strconv"
"strings"
"time"
)
var ErrDateTime8OutOfBounds = errors.New("datetime8: time.Time is out of bounds")
// DateTime8 represents a datetime `int32` value in the `yyyymmdd` format. It supports
// dates from 1000-01-01 to 9999-12-31.
type DateTime8 uint32
func (dt8 DateTime8) Format(layout string, loc *time.Location) (string, error) {
dt, err := dt8.Time(loc)
if err != nil {
return "", err
}
return dt.Format(layout), nil
}
func (dt8 DateTime8) Split() (uint32, uint32, uint32) {
year := dt8 / 10000
month := int(dt8/100) - (int(year) * 100)
day := int(dt8) - (int(year) * 10000) - (month * 100)
return uint32(year), uint32(month), uint32(day)
}
/*
// DurationForNowSubDt8 returns a duartion struct between a Dt8 value and the current time.
func (dt8 DateTime8) DurationForNowSubDT8(dt8 int32) (time.Duration, error) {
t, err := TimeForDT8(dt8)
if err != nil {
var d time.Duration
return d, err
}
now := time.Now()
return now.Sub(t), nil
}
*/
// Sub returns the duration dt8-u. If the result exceeds the maximum (or minimum) value that can be stored in a Duration, the maximum (or minimum) duration will be returned. To compute dt8-d for a duration d, use t.Add(-d).
func (dt8 DateTime8) SubTime(u time.Time, loc *time.Location) (time.Duration, error) {
t, err := dt8.Time(loc)
if err != nil {
return 0, err
}
return t.Sub(u), nil
}
func (dt8 DateTime8) Time(loc *time.Location) (time.Time, error) {
dt, err := time.Parse(DT8, strconv.Itoa(int(dt8)))
if err != nil || loc == nil || (loc == dt.Location()) {
return dt, err
}
return time.Date(dt.Year(), dt.Month(), dt.Day(), 0, 0, 0, 0, loc), nil
}
var ErrDateTime8Invalid = errors.New("timeutil.datetime8: invalid value")
type DateTime8UnmarshalError struct {
Msg string
}
func (e *DateTime8UnmarshalError) Error() string {
return fmt.Sprintf("timeutil.datetime8: unmarshal error (%s)", e.Msg)
}
func (dt8 *DateTime8) UnmarshalJSON(data []byte) error {
s := strings.TrimSpace(string(data))
if len(s) == 0 || s == "0" {
*dt8 = 0
return nil
}
i, err := strconv.Atoi(s)
if err != nil {
return &DateTime8UnmarshalError{Msg: err.Error()}
}
d8 := DateTime8(uint32(i))
err = d8.Validate()
if err != nil {
return err
}
*dt8 = d8
return nil
}
func (dt8 DateTime8) Validate() error {
_, err := dt8.Time(time.UTC)
if err != nil {
return err
}
return nil
}
// DT8ParseString returns a `DateTime8` value given a layout and value to parse to time.Parse.
func DT8ParseString(layout, value string) (DateTime8, error) {
dt8 := DateTime8(int32(0))
t, err := time.Parse(layout, value)
if err != nil {
return dt8, err
}
return NewTimeMore(t, 0).DT8()
}
// DT8ParseUints returns a `DateTime8` value for year, month, and day.
func DT8ParseUints(yyyy, mm, dd uint) (DateTime8, error) {
dt8String := fmt.Sprintf("%04d%02d%02d", yyyy, mm, dd)
dt8Int, err := strconv.ParseInt(dt8String, 10, 32)
if err != nil {
panic(err)
}
dt8 := DateTime8(int32(dt8Int))
return dt8, dt8.Validate()
}
func dt8TimeInbounds(t time.Time) bool {
if t.Year() < 1000 || t.Year() > 9999 {
return false
}
return true
}