forked from hyperledger-archives/aries-framework-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
time.go
130 lines (106 loc) · 3.51 KB
/
time.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
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package util
import (
"encoding/json"
"time"
)
// TimeWrapper overrides marshalling of time.Time. If a TimeWrapper is created from a time string, or
// unmarshalled from JSON, it saves the string literal, which it uses when marshalling.
// If a TimeWrapper is created using NewTime or a struct literal, it marshals with the default
// time.RFC3339 format.
type TimeWrapper struct {
time.Time
timeStr string
}
// TimeWithTrailingZeroMsec overrides marshalling of time.Time. It keeps a format of initial unmarshalling
// in case when date has zero a fractional second (e.g. ".000").
// For example, time.Time marshals 2018-03-15T00:00:00.000Z to 2018-03-15T00:00:00Z
// while TimeWithTrailingZeroMsec marshals to the initial 2018-03-15T00:00:00.000Z value.
//
// Deprecated: use TimeWrapper instead.
type TimeWithTrailingZeroMsec = TimeWrapper
// NewTime creates a TimeWrapper wrapped around the given time.Time.
// It functions as a normal time.Time object.
func NewTime(t time.Time) *TimeWrapper {
return &TimeWrapper{Time: t}
}
// NewTimeWithTrailingZeroMsec creates a TimeWrapper wrapped around the given time.Time.
//
// Deprecated: use NewTime instead. For sub-zero precision,
// use ParseTimeWrapper on a string with the desired precision.
func NewTimeWithTrailingZeroMsec(t time.Time, _ int) *TimeWrapper {
return &TimeWrapper{
Time: t,
}
}
// MarshalJSON implements the json.Marshaler interface.
// The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
// In case of zero sub-second precision presence, trailing zeros are included.
func (tm TimeWrapper) MarshalJSON() ([]byte, error) {
// catch time.Time marshaling errors
_, err := tm.Time.MarshalJSON()
if err != nil {
return nil, err
}
if tm.timeStr != "" {
return json.Marshal(tm.timeStr)
}
return json.Marshal(tm.FormatToString())
}
// UnmarshalJSON implements the json.Unmarshaler interface.
// The time is expected to be a quoted string in RFC 3339 format.
// The source string value is saved, and used if this is marshalled back to JSON.
func (tm *TimeWrapper) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
return nil
}
timeStr := ""
err := json.Unmarshal(data, &timeStr)
if err != nil {
return err
}
err = tm.parse(timeStr)
if err != nil {
return err
}
return nil
}
func (tm *TimeWrapper) parse(timeStr string) error {
t, err := time.Parse(time.RFC3339, timeStr)
if err != nil {
t, err = time.Parse(time.RFC3339, timeStr+"Z")
if err != nil {
return err
}
}
tm.Time = t
tm.timeStr = timeStr
return nil
}
// FormatToString returns the string representation of this TimeWrapper.
// If it was unmarshalled from a JSON object, this returns the original string it was parsed from.
// Otherwise, this returns the time in the time.RFC3339Nano format.
func (tm *TimeWrapper) FormatToString() string {
if tm.timeStr != "" {
return tm.timeStr
}
return tm.Time.Format(time.RFC3339Nano)
}
// ParseTimeWithTrailingZeroMsec parses a formatted string and returns the time value it represents.
//
// Deprecated: use ParseTimeWrapper instead.
func ParseTimeWithTrailingZeroMsec(timeStr string) (*TimeWrapper, error) {
return ParseTimeWrapper(timeStr)
}
// ParseTimeWrapper parses a formatted string and returns the time value it represents.
func ParseTimeWrapper(timeStr string) (*TimeWrapper, error) {
tm := TimeWrapper{}
err := tm.parse(timeStr)
if err != nil {
return nil, err
}
return &tm, nil
}