Skip to content

Commit 8235963

Browse files
authored
time: Handle different time formats when unmarshalling (#162)
* time: Handle different time formats when unmarshalling * readme: Update example, increment version
1 parent a6c478e commit 8235963

File tree

4 files changed

+62
-18
lines changed

4 files changed

+62
-18
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ import (
4343

4444
func main() {
4545
lunoClient := luno.NewClient()
46-
lunoClient.SetAuth("<id>", "<secret>")
46+
err := lunoClient.SetAuth("<id>", "<secret>")
47+
if err != nil {
48+
log.Fatal(err)
49+
}
4750

4851
req := luno.GetOrderBookRequest{Pair: "XBTZAR"}
4952
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(10*time.Second))

time.go

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,63 @@
11
package luno
22

33
import (
4+
"encoding/json"
45
"strconv"
56
"time"
67
)
78

89
type Time time.Time
910

1011
func (t *Time) UnmarshalJSON(b []byte) error {
12+
// Handle null case
13+
if string(b) == "null" || len(b) == 0 {
14+
*t = Time{}
15+
return nil
16+
}
17+
18+
// Try to parse as integer (milliseconds since epoch)
1119
i, err := strconv.ParseInt(string(b), 10, 64)
12-
if err != nil {
20+
if err == nil {
21+
if i == 0 {
22+
*t = Time{}
23+
return nil
24+
}
25+
*t = Time(time.Unix(0, i*1e6))
26+
return nil
27+
}
28+
29+
// Try to parse as string
30+
var timeStr string
31+
if err := json.Unmarshal(b, &timeStr); err != nil {
1332
return err
1433
}
15-
if i == 0 {
16-
*t = Time{}
34+
35+
// Try RFC3339 format
36+
parsed, err := time.Parse(time.RFC3339, timeStr)
37+
if err == nil {
38+
*t = Time(parsed)
39+
return nil
40+
}
41+
42+
// Try Go's default format
43+
parsed, err = time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", timeStr)
44+
if err == nil {
45+
*t = Time(parsed)
1746
return nil
1847
}
19-
*t = Time(time.Unix(0, i*1e6))
20-
return nil
48+
49+
return err
2150
}
2251

2352
func (t Time) MarshalJSON() ([]byte, error) {
24-
return []byte(t.String()), nil
53+
// Omit if zero
54+
if time.Time(t).IsZero() {
55+
return []byte("null"), nil
56+
}
57+
58+
// Format as RFC3339 string
59+
timeStr := time.Time(t).Format(time.RFC3339)
60+
return json.Marshal(timeStr)
2561
}
2662

2763
func (t Time) String() string {

time_test.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ func TestTimeUnmarshalJSON(t *testing.T) {
1616

1717
testCases := []testCase{
1818
{
19-
err: true,
19+
in: []byte("null"),
20+
exp: luno.Time{},
2021
},
2122
{
2223
in: []byte{},
23-
err: true,
24+
exp: luno.Time{},
2425
},
2526
{
2627
in: []byte("abc"),
@@ -34,6 +35,14 @@ func TestTimeUnmarshalJSON(t *testing.T) {
3435
in: []byte("-123456"),
3536
exp: luno.Time(time.Unix(0, -123456e6)),
3637
},
38+
{
39+
in: []byte(`"2006-01-02T15:04:05Z"`),
40+
exp: luno.Time(time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)),
41+
},
42+
{
43+
in: []byte(`"2006-01-02 15:04:05 +0000 UTC"`),
44+
exp: luno.Time(time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)),
45+
},
3746
}
3847

3948
var act luno.Time
@@ -58,20 +67,16 @@ func TestTimeMarshalJSON(t *testing.T) {
5867
exp string
5968
}
6069

61-
now := time.Now()
70+
date := time.Date(2006, 1, 2, 3, 4, 5, 0, time.UTC)
6271

6372
testCases := []testCase{
6473
{
6574
in: luno.Time{},
66-
exp: time.Time{}.String(),
67-
},
68-
{
69-
in: luno.Time(now),
70-
exp: now.String(),
75+
exp: "null",
7176
},
7277
{
73-
in: luno.Time(time.Date(2006, 1, 2, 3, 4, 5, 999, time.UTC)),
74-
exp: time.Date(2006, 1, 2, 3, 4, 5, 999, time.UTC).String(),
78+
in: luno.Time(date),
79+
exp: `"2006-01-02T03:04:05Z"`,
7580
},
7681
}
7782

version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package luno
22

3-
const Version = "0.0.33"
3+
const Version = "0.0.34"
44

55
// vi: ft=go

0 commit comments

Comments
 (0)