Skip to content

Commit 48ac28f

Browse files
committed
Date
在数据库中或者前后端数据传递中都会用到日期, `xtime.Date` 和 `xtime.NullDate` 支持 JSON 和SQL 解析 并提供 `xtime.NewDate` `xtime.NewDateForTime` `xtime.NewDateForString` 等方法创建数据 > 注意 xtime.Date 表达的是日期所以无需时区,但是 xtime.Date 转换为 time.Time 时候需要指定时区
1 parent 000d106 commit 48ac28f

File tree

6 files changed

+342
-6
lines changed

6 files changed

+342
-6
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.idea
2+
vendor

go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ module github.com/goclub/time
33
go 1.13
44

55
require (
6+
github.com/go-sql-driver/mysql v1.6.0
7+
github.com/goclub/error v0.0.0-20220203142532-3d4dac42a2ff
68
github.com/goclub/json v0.0.0-20201212033753-4350fe0a941e
79
github.com/stretchr/testify v1.6.1
810
)

go.sum

+7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
22
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
4+
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
5+
github.com/goclub/error v0.0.0-20220203142532-3d4dac42a2ff h1:wCHleJjPYHwUkFFvsWDN0rTaVK0HbmK+tYG6ObZ/nRs=
6+
github.com/goclub/error v0.0.0-20220203142532-3d4dac42a2ff/go.mod h1:2ombCAL3uNuhVNevp56iOpelgiQIyxlYkz7t6nWEC18=
37
github.com/goclub/json v0.0.0-20201212033753-4350fe0a941e h1:f/k5Ym11yl5ZXT12kQRuI1OFI+j66ubwLHCm6i+Mg9E=
48
github.com/goclub/json v0.0.0-20201212033753-4350fe0a941e/go.mod h1:K7bX26XRz/QHEzyXUZNCYwN8yQsrfedeC1hhsE9HcRk=
9+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
10+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
511
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
612
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
713
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
814
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
915
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
16+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
1017
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1118
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
1219
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

readme.md

+8-5
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ Format 也有相同的问题。
3030

3131
当 json 传递的时间格式不是 RFC3339 而是中国时区年月日时分秒 `2006-01-02 15:04:05`,可以使用 `xtime.ChinaTime` 解析和转换
3232

33-
## UnixMilli
33+
## Date
34+
35+
在数据库中或者前后端数据传递中都会用到日期, `xtime.Date``xtime.NullDate` 支持 JSON 和SQL 解析
36+
37+
并提供 `xtime.NewDate` `xtime.NewDateForTime` `xtime.NewDateForString` 等方法创建数据
38+
39+
> 注意 xtime.Date 表达的是日期所以无需时区,但是 xtime.Date 转换为 time.Time 时候需要指定时区
40+
3441

35-
```go
36-
sometime := time.Date(2020,12,31,23,23,23, 0,LocationChina)
37-
assert.Equal(t, UnixMilli(sometime), int64(1609428203000), )
38-
```

time.go

+135-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package xtime
22

33
import (
4+
"database/sql/driver"
5+
"fmt"
6+
xerr "github.com/goclub/error"
47
"log"
8+
"strconv"
59
"time"
610
)
711

@@ -25,5 +29,135 @@ func InRange(target time.Time, r Range) (in bool) {
2529
}
2630
return
2731
}
32+
type Date struct {
33+
Year int
34+
Month time.Month
35+
Day int
36+
}
37+
func NowDate(loc *time.Location) Date {
38+
year, month, day := time.Now().In(loc).Date()
39+
return Date{
40+
Year: year,
41+
Month: month,
42+
Day: day,
43+
}
44+
}
45+
func NewDate(year int, month time.Month, day int) Date {
46+
return Date{
47+
year, month,day,
48+
}
49+
}
50+
func NewDateForTime(t time.Time) Date {
51+
return NewDate(t.Date())
52+
}
53+
func NewDateForString(value string) (d Date, err error) {
54+
t, err := time.Parse(LayoutDate, value) ; if err != nil {
55+
err = xerr.WithStack(err)
56+
return
57+
}
58+
return NewDateForTime(t), nil
59+
}
60+
61+
func (d *Date) UnmarshalJSON(b []byte) error {
62+
value, err := strconv.Unquote(string(b)) ; if err != nil {
63+
return xerr.WithStack(err)
64+
}
65+
date, err := NewDateForString(value) ; if err != nil {
66+
return xerr.WithStack(err)
67+
}
68+
*d = date
69+
return err
70+
}
71+
72+
func (d Date) MarshalJSON() ([]byte, error) {
73+
return []byte(`"` + d.String() + `"`), nil
74+
}
75+
func (d Date) Time(loc *time.Location) time.Time {
76+
return time.Date(d.Year, d.Month, d.Day, 0,0,0,0, loc)
77+
}
78+
func (d Date) ChinaTime() ChinaTime {
79+
return NewChinaTime(d.Time(LocationChina))
80+
}
81+
func (d Date) String() string {
82+
return time.Date(d.Year, d.Month, d.Day, 0,0,0,0, time.UTC).Format(LayoutDate)
83+
}
84+
func (d Date) Value() (driver.Value, error) {
85+
return d.String(), nil
86+
}
87+
func (d *Date) Scan(value interface{}) (err error) {
88+
if value == nil {
89+
return xerr.New("unsupported NULL xtime.date value, maybe you should use xtime.NullDate")
90+
}
91+
var date Date
92+
date, err = NewDateForString(fmt.Sprintf("%s", value)) ; if err != nil {
93+
return
94+
}
95+
*d = date
96+
return
97+
}
98+
99+
type NullDate struct {
100+
date Date
101+
valid bool
102+
}
103+
104+
func (v NullDate) Date() Date {
105+
return v.date
106+
}
107+
func (v *NullDate) SetDate(date Date) {
108+
v.date = date
109+
}
110+
func (v NullDate) Valid() bool {
111+
return v.valid
112+
}
113+
func NewNullDate(year int, month time.Month, day int) NullDate {
114+
return NullDate{
115+
date: NewDate(year, month, day),
116+
valid: true,
117+
}
118+
}
119+
120+
func (d *NullDate) UnmarshalJSON(b []byte) error {
121+
if string(b) == "null" || string(b) == "" {
122+
d.valid = false
123+
return nil
124+
}
125+
date := Date{}
126+
err := date.UnmarshalJSON(b) ; if err != nil {
127+
return xerr.WithStack(err)
128+
}
129+
*d = NullDate{
130+
date: date,
131+
valid: true,
132+
}
133+
return err
134+
}
28135

29-
// func inRangeDate(begin string, end string, target string) bool
136+
func (d NullDate) MarshalJSON() ([]byte, error) {
137+
if d.valid {
138+
return d.date.MarshalJSON()
139+
} else {
140+
return []byte(`null`), nil
141+
}
142+
}
143+
func (d NullDate) String() string {
144+
if d.valid {
145+
return d.date.String()
146+
}
147+
return "null"
148+
}
149+
150+
func (d NullDate) Value() (driver.Value, error) {
151+
if d.valid {
152+
return d.date.Value()
153+
}
154+
return nil, nil
155+
}
156+
func (d *NullDate) Scan(value interface{}) error {
157+
if value == nil {
158+
d.valid = false
159+
return nil
160+
}
161+
d.valid = true
162+
return d.date.Scan(value)
163+
}

0 commit comments

Comments
 (0)