Skip to content

Commit d5322bf

Browse files
author
Nimo
committed
parse format json
🇨🇳
0 parents  commit d5322bf

15 files changed

+315
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea

example_test.go

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package xtime_test
2+
3+
import (
4+
xjson "github.com/goclub/json"
5+
xtime "github.com/goclub/time"
6+
"log"
7+
"testing"
8+
"time"
9+
)
10+
11+
func ExampleParse() {
12+
log.Print("ExampleParse")
13+
year, err := xtime.ParseChinaYear("2020") ; if err != nil {panic(err)}
14+
log.Print(year.String())
15+
yearAndMonth, err := xtime.ParseChinaYearAndMonth("2020-11") ; if err != nil {panic(err)}
16+
log.Print(yearAndMonth.String())
17+
date, err := xtime.ParseChinaDate("2020-11-11") ; if err != nil {panic(err)}
18+
log.Print(date.String())
19+
sometime, err := xtime.ParseChinaTime("2020-11-11 21:52:24") ; if err != nil {panic(err)}
20+
log.Print(sometime.String())
21+
}
22+
func ExampleFormat() {
23+
log.Print("ExampleFormat")
24+
sometime := time.Date(2020,12,31,23,23,23, 0,time.UTC)
25+
log.Print(xtime.FormatChinaYear(sometime)) // 2021
26+
log.Print(xtime.FormatChinaYearAndMonth(sometime)) // 2021-01
27+
log.Print(xtime.FormatChinaDate(sometime)) // 2021-01-01
28+
log.Print(xtime.FormatChinaTime(sometime)) // 2021-01-01 07:23:23
29+
log.Print(xtime.FormatChinaHourMinuteSecond(sometime)) // 07:23:23
30+
}
31+
32+
func ExampleLocation() {
33+
log.Print("now time is :" + time.Now().In(xtime.LocationChina).String())
34+
}
35+
// 直接使用 time.Time 作为json 字段时因为 time.Time{}.UnmarshalJSON() 和 time.Time{}.MarshalJSON() 的原因会以 time.RFC3339 格式作为 layout
36+
func ExampleJSON_RFC3339() {
37+
log.Print("ExampleJSON_RFC3339")
38+
reqeust := struct {
39+
Time time.Time `json:"time"`
40+
}{}
41+
err := xjson.Unmarshal([]byte(`{"time": "2020-12-31T23:23:23Z"}`), &reqeust) ; if err != nil {panic(err)}
42+
log.Printf("reqeust: %+v", reqeust)
43+
44+
response := struct {
45+
Time time.Time `json:"time"`
46+
}{Time: time.Date(2020,12,31,23,23,23, 0,time.UTC)}
47+
data, err := xjson.Marshal(response) ; if err != nil {panic(err)}
48+
log.Print("response json : " + string(data)) // {"time":"2020-12-31T23:23:23Z"}
49+
}
50+
func ExampleJSONChinaTime () {
51+
log.Print("ExampleJSONChinaTime")
52+
reqeust := struct {
53+
Time xtime.ChinaTime `json:"time"`
54+
}{}
55+
err := xjson.Unmarshal([]byte(`{"time": "2020-12-31 23:23:23"}`), &reqeust) ; if err != nil {panic(err)}
56+
log.Printf("reqeust: %+v", reqeust)
57+
58+
response := struct {
59+
Time xtime.ChinaTime `json:"time"`
60+
}{Time: xtime.NewChinaTime(time.Date(2020,12,31,23,23,23, 0,time.UTC))}
61+
data, err := xjson.Marshal(response) ; if err != nil {panic(err)}
62+
log.Print("response json : " + string(data)) // {"time":"2020-12-31 23:23:23"}
63+
}
64+
func TestExample(t *testing.T) {
65+
ExampleFormat()
66+
ExampleLocation()
67+
ExampleParse()
68+
ExampleJSON_RFC3339()
69+
ExampleJSONChinaTime()
70+
}

format.go

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package xtime
2+
3+
import "time"
4+
func FormatChinaYear(t time.Time) string {
5+
return t.In(LocationChina).Format(layoutYear)
6+
}
7+
func FormatChinaYearAndMonth(t time.Time) string {
8+
return t.In(LocationChina).Format(layoutYearAndMonth)
9+
}
10+
func FormatChinaTime(t time.Time) string {
11+
return t.In(LocationChina).Format(layoutTime)
12+
}
13+
func FormatChinaDate(t time.Time) string {
14+
return t.In(LocationChina).Format(layoutDate)
15+
}
16+
func FormatChinaHourMinuteSecond(t time.Time) string {
17+
return t.In(LocationChina).Format(layoutHourMinuteSecond)
18+
}

format_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package xtime
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
"time"
7+
)
8+
9+
func TestFormatChinaYear(t *testing.T) {
10+
sometime := time.Date(2020,12,31,23,23,23, 0,time.UTC)
11+
assert.Equal(t, FormatChinaYear(sometime), "2021")
12+
}
13+
func TestFormatChinaYearAndMonth(t *testing.T) {
14+
sometime := time.Date(2020,12,31,23,23,23, 0,time.UTC)
15+
assert.Equal(t, FormatChinaYearAndMonth(sometime), "2021-01")
16+
}
17+
func TestFormatChinaDate(t *testing.T) {
18+
sometime := time.Date(2020,12,31,23,23,23, 0,time.UTC)
19+
assert.Equal(t, FormatChinaDate(sometime), "2021-01-01")
20+
}
21+
func TestFormatChinaTime(t *testing.T) {
22+
sometime := time.Date(2020,12,31,23,23,23, 0,time.UTC)
23+
assert.Equal(t, FormatChinaTime(sometime), "2021-01-01 07:23:23")
24+
}
25+
func TestFormatChinaHourMinuteSecond(t *testing.T) {
26+
sometime := time.Date(2020,12,31,23,23,23, 0,time.UTC)
27+
assert.Equal(t, FormatChinaHourMinuteSecond(sometime), "07:23:23")
28+
}

go.mod

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/goclub/time
2+
3+
go 1.13
4+
5+
require (
6+
github.com/goclub/json v0.0.0-20201212033753-4350fe0a941e
7+
github.com/stretchr/testify v1.6.1
8+
)

go.sum

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/goclub/json v0.0.0-20201212033753-4350fe0a941e h1:f/k5Ym11yl5ZXT12kQRuI1OFI+j66ubwLHCm6i+Mg9E=
4+
github.com/goclub/json v0.0.0-20201212033753-4350fe0a941e/go.mod h1:K7bX26XRz/QHEzyXUZNCYwN8yQsrfedeC1hhsE9HcRk=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
8+
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
9+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
10+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
11+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
12+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

json.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package xtime
2+
3+
4+
import (
5+
"time"
6+
)
7+
8+
9+
type ChinaTime struct {
10+
time.Time
11+
}
12+
func NewChinaTime(time time.Time) ChinaTime {
13+
return ChinaTime{Time: time.In(LocationChina)}
14+
}
15+
func (t ChinaTime) MarshalJSON() ([]byte, error) {
16+
return []byte(`"` + t.In(LocationChina).Format(layoutTime) + `"`), nil
17+
}
18+
func (t *ChinaTime) UnmarshalJSON(b []byte) error {
19+
v, err := time.ParseInLocation(`"` + layoutTime + `"`, string(b), LocationChina)
20+
t.Time = v
21+
return err
22+
}

json_test.go

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package xtime
2+
3+
import (
4+
xjson "github.com/goclub/json"
5+
"github.com/stretchr/testify/assert"
6+
"testing"
7+
"time"
8+
)
9+
10+
func TestChinaTime(t *testing.T) {
11+
String := func (v interface{}) string {
12+
data, err := xjson.Marshal(v) ; if err != nil {panic(err)}
13+
return string(data)
14+
}
15+
{
16+
tValue, err := time.ParseInLocation("2006-01-02 15:04:05", "2020-07-31 15:29:29", time.FixedZone("CST", 2*3600))
17+
assert.Equal(t, err, nil)
18+
assert.Equal(t, String(NewChinaTime(tValue)), `"2020-07-31 21:29:29"`)
19+
}
20+
{
21+
tValue, err := time.ParseInLocation("2006-01-02 15:04:05", "2020-07-31 15:29:29", time.FixedZone("CST", 8*3600))
22+
assert.Equal(t, err, nil)
23+
assert.Equal(t, String(NewChinaTime(tValue)), `"2020-07-31 15:29:29"`)
24+
}
25+
{
26+
tValue, err := time.ParseInLocation("2006-01-02 15:04:05", "2020-07-31 15:29:29", time.FixedZone("CST", 0*3600))
27+
assert.Equal(t, err, nil)
28+
assert.Equal(t, String(NewChinaTime(tValue)), `"2020-07-31 23:29:29"`)
29+
}
30+
{
31+
type Request struct {
32+
Time ChinaTime `db:"time"`
33+
}
34+
req := Request{}
35+
err := xjson.Unmarshal([]byte(`{"time":"2020-07-31 15:37:44"}`), &req)
36+
assert.NoError(t, err)
37+
assert.Equal(t, req.Time.In(time.FixedZone("CST", 8*3600)).String(), "2020-07-31 15:37:44 +0800 CST")
38+
}
39+
{
40+
type Reply struct {
41+
Time ChinaTime `db:"time"`
42+
}
43+
reply := Reply{}
44+
tValue, err := time.ParseInLocation("2006-01-02 15:04:05", "2020-07-31 15:29:29", time.UTC)
45+
assert.Equal(t, err, nil)
46+
reply.Time = NewChinaTime(tValue)
47+
assert.Equal(t, reply.Time.String(), "2020-07-31 23:29:29 +0800 CST")
48+
}
49+
}

layout.go

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package xtime
2+
3+
const layoutYear = "2006"
4+
const layoutYearAndMonth = "2006-01"
5+
const layoutDate = "2006-01-02"
6+
const layoutTime = "2006-01-02 15:04:05"
7+
const layoutHourMinuteSecond = "15:04:05"

layout_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package xtime
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
)
7+
8+
func TestLayout(t *testing.T) {
9+
assert.Equal(t, layoutYear, "2006")
10+
assert.Equal(t, layoutYearAndMonth, "2006-01")
11+
assert.Equal(t, layoutDate, "2006-01-02")
12+
assert.Equal(t, layoutTime, "2006-01-02 15:04:05")
13+
assert.Equal(t, layoutHourMinuteSecond, "15:04:05")
14+
}

location.go

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package xtime
2+
3+
import "time"
4+
5+
var LocationChina = time.FixedZone("CST", 8*3600)

location_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package xtime
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
"time"
7+
)
8+
9+
func TestLocation(t *testing.T) {
10+
sometime := time.Date(2020,11,11,11,11,11, 0,time.UTC)
11+
assert.Equal(t, sometime.String(), "2020-11-11 11:11:11 +0000 UTC")
12+
sometime = sometime.In(LocationChina)
13+
assert.Equal(t, sometime.String(), "2020-11-11 19:11:11 +0800 CST")
14+
}

parse.go

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package xtime
2+
3+
import "time"
4+
5+
6+
func ParseChinaYear(value string) (t time.Time, err error) {
7+
return time.ParseInLocation(layoutYear, value, LocationChina)
8+
}
9+
func ParseChinaYearAndMonth(value string) (t time.Time, err error) {
10+
return time.ParseInLocation(layoutYearAndMonth, value, LocationChina)
11+
}
12+
func ParseChinaDate(value string) (t time.Time, err error) {
13+
return time.ParseInLocation(layoutDate, value, LocationChina)
14+
}
15+
func ParseChinaTime(value string) (t time.Time, err error) {
16+
return time.ParseInLocation(layoutTime, value, LocationChina)
17+
}

parse_test.go

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package xtime
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
"time"
7+
)
8+
9+
func mustTime(t time.Time, err error) time.Time {
10+
if err != nil {panic(err)}
11+
return t
12+
}
13+
func TestParseChinaYear(t *testing.T) {
14+
assert.Equal(t, time.Date(2021,1,1,0,0,0,0, LocationChina), mustTime(ParseChinaYear("2021")))
15+
}
16+
func TestParseChinaYearAndMonth(t *testing.T) {
17+
assert.Equal(t, time.Date(2021,1,1,0,0,0,0, LocationChina), mustTime(ParseChinaYearAndMonth("2021-01")))
18+
}
19+
func TestParseChinaDate(t *testing.T) {
20+
assert.Equal(t, time.Date(2021,01,01,0,0,0,0, LocationChina), mustTime(ParseChinaDate("2021-01-01")))
21+
}
22+
func TestParseChinaTime(t *testing.T) {
23+
assert.Equal(t, time.Date(2021,01,01,7,23,23,0, LocationChina), mustTime(ParseChinaTime("2021-01-01 07:23:23")))
24+
}

readme.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# time
2+
3+
```go
4+
import "github.com/goclub/time"
5+
```
6+
7+
`time` 是 go 中非常重要的一个包,使用 time.Time 时一定要注意时区。
8+
9+
## Parse & Format
10+
11+
在将字符串解析为 `time.Time` 和将 `time.Time` 转换为字符串时如果不指定时区则会按照当前机器的本地时区解析和转换。
12+
13+
```go
14+
layoutTime := "2006-01-02 15:04:05"
15+
someTime, err := time.Parse(layoutTime, "2020-12-31 22:00:00") ; if err != nil {
16+
panic(err)
17+
}
18+
log.Print(someTime.String()) // 不同时区的机器运行结果不同
19+
```
20+
21+
当 layout 不包含时区时,以服务端时区解析字符串是不严谨的。
22+
Format 也有相同的问题。
23+
24+
故此 goclub/time 提供了一些指定时区的 parse 和 format,目前主要是 China 时区 `time.FixedZone("CST", 8*3600)`
25+
26+
当 json 传递的时间格式不是 RFC3339 而是中国时区年月日时分秒 `2006-01-02 15:04:05`,可以使用 `xtime.ChinaTime` 解析和转换

0 commit comments

Comments
 (0)