1 package time
2
3 import (
4 "math"
5 "strconv"
6 "testing"
7 "time"
8 )
9
10 func TestDateTime(t *testing.T) {
11 cases := map[string]struct {
12 TimeString string
13 TimeValue time.Time
14 SymmetricString bool
15 }{
16 "no offset": {
17 TimeString: "1985-04-12T23:20:50.52Z",
18 TimeValue: time.Date(1985, 4, 12, 23, 20, 50, int(520*time.Millisecond),
19 time.UTC),
20 SymmetricString: true,
21 },
22 "no offset, no Z": {
23 TimeString: "1985-04-12T23:20:50.524",
24 TimeValue: time.Date(1985, 4, 12, 23, 20, 50, int(524*time.Millisecond),
25 time.UTC),
26 SymmetricString: false,
27 },
28 "with negative offset": {
29 TimeString: "1985-04-12T23:20:50.52-07:00",
30 TimeValue: time.Date(1985, 4, 12, 23, 20, 50, int(520*time.Millisecond),
31 time.FixedZone("-0700", -7*60*60)),
32 SymmetricString: false,
33 },
34 "with positive offset": {
35 TimeString: "1985-04-12T23:20:50.52+07:00",
36 TimeValue: time.Date(1985, 4, 12, 23, 20, 50, int(520*time.Millisecond),
37 time.FixedZone("-0700", +7*60*60)),
38 SymmetricString: false,
39 },
40 "UTC serialize": {
41 TimeString: "1985-04-13T06:20:50.52Z",
42 TimeValue: time.Date(1985, 4, 12, 23, 20, 50, int(520*time.Millisecond),
43 time.FixedZone("-0700", -7*60*60)),
44 SymmetricString: true,
45 },
46 }
47
48 for name, c := range cases {
49 t.Run(name, func(t *testing.T) {
50 formattedTimeValue := FormatDateTime(c.TimeValue)
51
52
53 parsedTimeValue, err := ParseDateTime(formattedTimeValue)
54 if err != nil {
55 t.Fatalf("expected no error, got %v", err)
56 }
57
58 parsedTimeString, err := ParseDateTime(c.TimeString)
59 if err != nil {
60 t.Fatalf("expected no error, got %v", err)
61 }
62
63
64 if c.SymmetricString {
65 if e, a := c.TimeString, formattedTimeValue; e != a {
66 t.Errorf("expected %v, got %v", e, a)
67 }
68 }
69 if e, a := c.TimeValue, parsedTimeValue; !e.Equal(a) {
70 t.Errorf("expected %v, got %v", e, a)
71 }
72 if e, a := c.TimeValue, parsedTimeString; !e.Equal(a) {
73 t.Errorf("expected %v, got %v", e, a)
74 }
75 })
76 }
77 }
78
79 func TestHTTPDate(t *testing.T) {
80 refTime := time.Date(2014, 4, 29, 18, 30, 38, 0, time.UTC)
81
82 httpDate := FormatHTTPDate(refTime)
83 if e, a := "Tue, 29 Apr 2014 18:30:38 GMT", httpDate; e != a {
84 t.Errorf("expected %v, got %v", e, a)
85 }
86
87 parseTime, err := ParseHTTPDate(httpDate)
88 if err != nil {
89 t.Fatalf("expected no error, got %v", err)
90 }
91
92 if e, a := refTime, parseTime; !e.Equal(a) {
93 t.Errorf("expected %v, got %v", e, a)
94 }
95
96
97 refTime = time.Date(2014, 4, 29, 18, 30, 38, 0, time.FixedZone("-700", -7*60*60))
98 httpDate = FormatHTTPDate(refTime)
99 if e, a := "Wed, 30 Apr 2014 01:30:38 GMT", httpDate; e != a {
100 t.Errorf("expected %v, got %v", e, a)
101 }
102 }
103
104 func TestParseHTTPDate(t *testing.T) {
105 cases := map[string]struct {
106 date string
107 expect time.Time
108 wantErr bool
109 }{
110 "with leading zero on day": {
111 date: "Fri, 05 Feb 2021 19:12:15 GMT",
112 expect: time.Date(2021, 2, 5, 19, 12, 15, 0, time.UTC),
113 },
114 "without leading zero on day": {
115 date: "Fri, 5 Feb 2021 19:12:15 GMT",
116 expect: time.Date(2021, 2, 5, 19, 12, 15, 0, time.UTC),
117 },
118 "with double digit day": {
119 date: "Fri, 15 Feb 2021 19:12:15 GMT",
120 expect: time.Date(2021, 2, 15, 19, 12, 15, 0, time.UTC),
121 },
122 "RFC850": {
123 date: "Friday, 05-Feb-21 19:12:15 UTC",
124 expect: time.Date(2021, 2, 5, 19, 12, 15, 0, time.UTC),
125 },
126 "ANSIC with leading zero on day": {
127 date: "Fri Feb 05 19:12:15 2021",
128 expect: time.Date(2021, 2, 5, 19, 12, 15, 0, time.UTC),
129 },
130 "ANSIC without leading zero on day": {
131 date: "Fri Feb 5 19:12:15 2021",
132 expect: time.Date(2021, 2, 5, 19, 12, 15, 0, time.UTC),
133 },
134 "ANSIC with double digit day": {
135 date: "Fri Feb 15 19:12:15 2021",
136 expect: time.Date(2021, 2, 15, 19, 12, 15, 0, time.UTC),
137 },
138 "invalid time format": {
139 date: "1985-04-12T23:20:50.52Z",
140 wantErr: true,
141 },
142 "shortened year with double digit day": {
143 date: "Thu, 11 Feb 21 11:04:03 GMT",
144 expect: time.Date(2021, 2, 11, 11, 04, 03, 0, time.UTC),
145 },
146 "shortened year without leading zero day": {
147 date: "Thu, 5 Feb 21 11:04:03 GMT",
148 expect: time.Date(2021, 2, 5, 11, 04, 03, 0, time.UTC),
149 },
150 "shortened year with leading zero day": {
151 date: "Thu, 05 Feb 21 11:04:03 GMT",
152 expect: time.Date(2021, 2, 5, 11, 04, 03, 0, time.UTC),
153 },
154 }
155
156 for name, tt := range cases {
157 t.Run(name, func(t *testing.T) {
158 result, err := ParseHTTPDate(tt.date)
159 if (err != nil) != tt.wantErr {
160 t.Fatalf("error = %v, wantErr = %v", err, tt.wantErr)
161 }
162 if err != nil {
163 return
164 }
165 if result.IsZero() {
166 t.Fatalf("expected non-zero timestamp")
167 }
168 if tt.expect != result {
169 t.Fatalf("expected %q, got %q", tt.expect, result)
170 }
171 })
172 }
173 }
174
175 func TestEpochSeconds(t *testing.T) {
176 cases := []struct {
177 reference time.Time
178 expectedUnix float64
179 expectedTime time.Time
180 }{
181 {
182 reference: time.Date(2018, 1, 9, 20, 51, 21, 123399936, time.UTC),
183 expectedUnix: 1515531081.123,
184 expectedTime: time.Date(2018, 1, 9, 20, 51, 21, 1.23e8, time.UTC),
185 },
186 {
187 reference: time.Date(2018, 1, 9, 20, 51, 21, 1e8, time.UTC),
188 expectedUnix: 1515531081.1,
189 expectedTime: time.Date(2018, 1, 9, 20, 51, 21, 1e8, time.UTC),
190 },
191 {
192 reference: time.Date(2018, 1, 9, 20, 51, 21, 123567891, time.UTC),
193 expectedUnix: 1515531081.123,
194 expectedTime: time.Date(2018, 1, 9, 20, 51, 21, 1.23e8, time.UTC),
195 },
196 {
197 reference: time.Unix(0, math.MaxInt64).UTC(),
198 expectedUnix: 9223372036.854,
199 expectedTime: time.Date(2262, 04, 11, 23, 47, 16, 8.54e8, time.UTC),
200 },
201 {
202 reference: time.Date(2018, 1, 9, 20, 51, 21, 123567891, time.FixedZone("-0700", -7*60*60)),
203 expectedUnix: 1515556281.123,
204 expectedTime: time.Date(2018, 1, 10, 03, 51, 21, 1.23e8, time.UTC),
205 },
206 }
207
208 for i, tt := range cases {
209 t.Run(strconv.Itoa(i), func(t *testing.T) {
210 epochSeconds := FormatEpochSeconds(tt.reference)
211 if e, a := tt.expectedUnix, epochSeconds; e != a {
212 t.Errorf("expected %v, got %v", e, a)
213 }
214
215 parseTime := ParseEpochSeconds(epochSeconds)
216
217 if e, a := tt.expectedTime, parseTime; !e.Equal(a) {
218 t.Errorf("expected %v, got %v", e, a)
219 }
220 })
221 }
222
223
224 if e, a := time.Date(2018, 1, 9, 20, 51, 21, 1.23e8, time.UTC), ParseEpochSeconds(1515531081.12356); !e.Equal(a) {
225 t.Errorf("expected %v, got %v", e, a)
226 }
227 }
228
View as plain text