-
Notifications
You must be signed in to change notification settings - Fork 0
/
timestamp.custom.go
141 lines (124 loc) · 3.37 KB
/
timestamp.custom.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
package timestamp
import (
"database/sql"
"database/sql/driver"
"errors"
timei "github.com/hopeio/cherry/utils/time"
"google.golang.org/protobuf/runtime/protoimpl"
"io"
"time"
)
// Now constructs a new Timestamp from the current time.
func Now() *Timestamp {
return New(time.Now())
}
// New constructs a new Timestamp from the provided time.Time.
func New(t time.Time) *Timestamp {
return &Timestamp{Seconds: t.Unix(), Nanos: int32(t.Nanosecond())}
}
// AsTime converts x to a time.Time.
func (x *Timestamp) AsTime() time.Time {
return time.Unix(x.GetSeconds(), int64(x.GetNanos()))
}
// IsValid reports whether the timestamp is valid.
// It is equivalent to CheckValid == nil.
func (x *Timestamp) IsValid() bool {
return x != nil && x.check() == 0
}
// CheckValid returns an error if the timestamp is invalid.
// In particular, it checks whether the value represents a date that is
// in the range of 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.
// An error is reported for a nil Timestamp.
func (x *Timestamp) CheckValid() error {
switch x.check() {
case invalidNil:
return protoimpl.X.NewError("invalid nil Timestamp")
case invalidUnderflow:
return protoimpl.X.NewError("timestamp (%v) before 0001-01-01", x)
case invalidOverflow:
return protoimpl.X.NewError("timestamp (%v) after 9999-12-31", x)
case invalidNanos:
return protoimpl.X.NewError("timestamp (%v) has out-of-range nanos", x)
default:
return nil
}
}
const (
_ = iota
invalidNil
invalidUnderflow
invalidOverflow
invalidNanos
)
func (x *Timestamp) check() uint {
const minTimestamp = -62135596800 // Seconds between 1970-01-01T00:00:00Z and 0001-01-01T00:00:00Z, inclusive
const maxTimestamp = +253402300799 // Seconds between 1970-01-01T00:00:00Z and 9999-12-31T23:59:59Z, inclusive
secs := x.GetSeconds()
nanos := x.GetNanos()
switch {
case x == nil:
return invalidNil
case secs < minTimestamp:
return invalidUnderflow
case secs > maxTimestamp:
return invalidOverflow
case nanos < 0 || nanos >= 1e9:
return invalidNanos
default:
return 0
}
}
// Scan scan time.
func (t *Timestamp) Scan(value interface{}) error {
nullTime := &sql.NullTime{}
err := nullTime.Scan(value)
if err != nil {
return err
}
if nullTime.Valid {
*t = Timestamp{Seconds: nullTime.Time.Unix(), Nanos: int32(nullTime.Time.Nanosecond())}
}
return nil
}
// Value get time value.
func (t *Timestamp) Value() (driver.Value, error) {
if t == nil {
return nil, nil
}
return t.Time(), nil
}
func (ts *Timestamp) GormDataType() string {
return "time"
}
// Time get time.
func (t *Timestamp) Time() time.Time {
return time.Unix(t.Seconds, int64(t.Nanos))
}
func (t *Timestamp) MarshalJSON() ([]byte, error) {
return timei.MarshalJSON(t.Time())
}
func (t *Timestamp) UnmarshalJSON(data []byte) error {
var st time.Time
if err := timei.UnmarshalJSON(&st, data); err != nil {
return err
}
*t = Timestamp{Seconds: st.Unix(), Nanos: int32(st.Nanosecond())}
return nil
}
func (x *Timestamp) MarshalGQL(w io.Writer) {
data, _ := timei.MarshalText(x.Time())
w.Write(data)
}
func (x *Timestamp) UnmarshalGQL(v interface{}) error {
var t time.Time
if i, ok := v.(string); ok {
err := timei.UnmarshalText(&t, []byte(i))
if err != nil {
return err
}
*x = Timestamp{Seconds: t.Unix(), Nanos: int32(t.Nanosecond())}
return nil
}
return errors.New("enum need integer type")
}
type TimestampInput = Timestamp