v / vlib / time / parse_test.v
325 lines · 292 sloc · 10.03 KB · 8902db4887548bcc0a464c10f1289a39b451a57f
Raw
1import time
2
3fn test_parse() {
4 s := '2018-01-27 12:48:34'
5 t := time.parse(s) or {
6 assert false, '> failing format: ${s} | err: ${err}'
7 return
8 }
9 assert t.year == 2018 && t.month == 1 && t.day == 27 && t.hour == 12 && t.minute == 48
10 && t.second == 34
11 assert t.unix() == 1517057314
12}
13
14fn test_parse_invalid() {
15 if x := time.parse('Invalid time string') {
16 assert false
17 }
18 assert true
19
20 if x := time.parse('2020-02-02 02.20.02') {
21 assert false
22 }
23 assert true
24}
25
26fn test_parse_rfc2822() {
27 s1 := 'Thu, 12 Dec 2019 06:07:45 GMT'
28 t1 := time.parse_rfc2822(s1) or {
29 assert false, '> failing format: ${s1} | err: ${err}'
30 return
31 }
32 assert t1.year == 2019 && t1.month == 12 && t1.day == 12 && t1.hour == 6 && t1.minute == 7
33 && t1.second == 45
34 assert t1.unix() == 1576130865
35 s2 := 'Thu 12 Dec 2019 06:07:45 +0800'
36 t2 := time.parse_rfc2822(s2) or {
37 assert false, '> failing format: ${s2} | err: ${err}'
38 return
39 }
40 assert t2.year == 2019 && t2.month == 12 && t2.day == 12 && t2.hour == 6 && t2.minute == 7
41 && t2.second == 45
42 assert t2.unix() == 1576130865
43}
44
45fn test_parse_rfc2822_invalid() {
46 s3 := 'Thu 12 Foo 2019 06:07:45 +0800'
47 time.parse_rfc2822(s3) or {
48 assert true
49 return
50 }
51 assert false
52}
53
54fn test_parse_iso8601() {
55 formats := [
56 '2020-06-05T15:38:06Z',
57 '2020-06-05T15:38:06.015959Z',
58 '2020-06-05T15:38:06.015959+00:00',
59 '2020-06-05T15:38:06.015959+02:00',
60 '2020-06-05T15:38:06.015959-02:00',
61 '2020-11-05T15:38:06.015959Z',
62 ]
63 times := [
64 [2020, 6, 5, 15, 38, 6, 0],
65 [2020, 6, 5, 15, 38, 6, 15959000],
66 [2020, 6, 5, 15, 38, 6, 15959000],
67 [2020, 6, 5, 13, 38, 6, 15959000],
68 [2020, 6, 5, 17, 38, 6, 15959000],
69 [2020, 11, 5, 15, 38, 6, 15959000],
70 ]
71 for i, format in formats {
72 t := time.parse_iso8601(format) or {
73 assert false, '>>> failing format: ${format} | err: ${err}'
74 continue
75 }
76 year := times[i][0]
77 assert t.year == year
78 month := times[i][1]
79 assert t.month == month
80 day := times[i][2]
81 assert t.day == day
82 hour := times[i][3]
83 assert t.hour == hour
84 minute := times[i][4]
85 assert t.minute == minute
86 second := times[i][5]
87 assert t.second == second
88 nanosecond := times[i][6]
89 assert t.nanosecond == nanosecond
90 }
91}
92
93fn test_parse_iso8601_local() {
94 format := '2020-06-05T15:38:06.015959'
95 t := time.parse_iso8601(format) or {
96 assert false, '> failing format: ${format} | err: ${err}'
97 return
98 }
99 assert t.year == 2020
100 assert t.month == 6
101 assert t.day == 5
102 assert t.hour == 15
103 assert t.minute == 38
104 assert t.second == 6
105 assert t.nanosecond == 15959_000
106}
107
108fn test_parse_iso8601_invalid() {
109 formats := [
110 '',
111 '2020-06-05X15:38:06.015959Z',
112 '2020-06-05T15:38:06.015959X',
113 '2020-06-05T15:38:06.015959+0000',
114 '2020-06-05T',
115 '2020-06-05Z',
116 '2020-06-05+00:00',
117 '15:38:06',
118 '2020-06-32T15:38:06.015959',
119 '2020-13-13T15:38:06.015959',
120 ]
121 for format in formats {
122 time.parse_iso8601(format) or {
123 assert true
124 continue
125 }
126 assert false
127 }
128}
129
130fn test_parse_iso8601_date_only() {
131 format := '2020-06-05'
132 t := time.parse_iso8601(format) or {
133 assert false, '> failing format: ${format} | err: ${err}'
134 return
135 }
136 assert t.year == 2020
137 assert t.month == 6
138 assert t.day == 5
139 assert t.hour == 0
140 assert t.minute == 0
141 assert t.second == 0
142 assert t.nanosecond == 0
143}
144
145fn check_invalid_date(s string) {
146 if date := time.parse(s) {
147 assert false, 'invalid date: "${s}" => "${date}"'
148 }
149 assert true
150}
151
152fn invalid_rfc3339(s string) string {
153 if date := time.parse_rfc3339(s) {
154 assert false, 'invalid date: "${s}" => "${date}"'
155 } else {
156 assert true
157 return err.str()
158 }
159 return ''
160}
161
162fn test_invalid_dates_should_error_during_parse() {
163 check_invalid_date('-99999-12-20 00:00:00')
164 check_invalid_date('99999-12-20 00:00:00')
165
166 check_invalid_date('2008-00-20 00:00:00')
167 check_invalid_date('2008-25-20 00:00:00')
168
169 check_invalid_date('2008-12-00 00:00:00')
170 check_invalid_date('2008-12-32 00:00:00')
171
172 check_invalid_date('2008-12-01 30:00:00')
173 check_invalid_date('2008-12-01 00:60:00')
174 check_invalid_date('2008-12-01 00:01:60')
175}
176
177fn test_parse_rfc3339() {
178 pairs := [
179 ['2015-01-06T15:47:32.080254511Z', '2015-01-06 15:47:32.080254'],
180 ['2015-01-06T15:47:32.072697474Z', '2015-01-06 15:47:32.072697'],
181 ['2015-01-06T15:47:32.1234Z', '2015-01-06 15:47:32.123400'],
182 ['2015-01-06T15:47:32.001234Z', '2015-01-06 15:47:32.001234'],
183 ['2015-01-06T15:47:32Z', '2015-01-06 15:47:32.000000'],
184 ['2015-01-06T15:47:32+00:00', '2015-01-06 15:47:32.000000'],
185 ['2015-01-06T15:47:32-00:00', '2015-01-06 15:47:32.000000'],
186 ['2015-01-06T15:47:32-01:00', '2015-01-06 16:47:32.000000'],
187 ['2015-01-06T15:47:32+01:00', '2015-01-06 14:47:32.000000'],
188 ['2015-01-06T15:47:32-01:10', '2015-01-06 16:57:32.000000'],
189 ['2015-01-06T15:47:32+01:10', '2015-01-06 14:37:32.000000'],
190 ['2015-01-06T15:47:32.1234-00:00', '2015-01-06 15:47:32.123400'],
191 ['2015-01-06T15:47:32.1234+01:00', '2015-01-06 14:47:32.123400'],
192 ['2015-01-06T15:47:32.1234-01:00', '2015-01-06 16:47:32.123400'],
193 ['2015-01-06T22:59:59-00:10', '2015-01-06 23:09:59.000000'],
194 ['1979-05-27T07:32:00-08:00', '1979-05-27 15:32:00.000000'],
195 ['2024-10-19T22:47:08-00:00', '2024-10-19 22:47:08.000000'],
196 ['2024-10-19T22:47:08.9+00:00', '2024-10-19 22:47:08.900000'],
197 ['2024-10-20T01:47:08+03:00', '2024-10-19 22:47:08.000000'],
198 ['2024-10-20T01:47:08.981+03:00', '2024-10-19 22:47:08.981000'],
199 ['1979-05-27t07:32:00z', '1979-05-27 07:32:00.000000'],
200 ['1979-05-27 07:32:00Z', '1979-05-27 07:32:00.000000'],
201 ['1979-05-27T00:32:00.999999Z', '1979-05-27 00:32:00.999999'],
202 ]
203 for pair in pairs {
204 input, expected := pair[0], pair[1]
205 res := time.parse_rfc3339(input) or {
206 assert false, '>>> failing input: ${input} | err: ${err}'
207 return
208 }
209 output := res.format_ss_micro()
210 assert expected == output
211 }
212 assert invalid_rfc3339('22:47:08Z') == 'missing date part of RFC 3339'
213 assert invalid_rfc3339('01:47:08.981+03:00') == 'missing date part of RFC 3339'
214 assert invalid_rfc3339('2006-01-00T00:00:00Z') == 'date error: invalid day 0'
215 assert invalid_rfc3339('2006-01-32T00:00:00Z') == 'date error: invalid day 32'
216 assert invalid_rfc3339('2006-01-88T00:00:00Z') == 'date error: invalid day 88'
217 assert invalid_rfc3339('2006-00-01T00:00:00Z') == 'date error: invalid month 0'
218 assert invalid_rfc3339('2006-13-01T00:00:00Z') == 'date error: invalid month 13'
219 assert invalid_rfc3339('2006-77-01T00:00:00Z') == 'date error: invalid month 77'
220 assert invalid_rfc3339('2006-01-01T24:47:08Z') == 'invalid hour: 24'
221 assert invalid_rfc3339('2006-01-01T99:47:08Z') == 'invalid hour: 99'
222 assert invalid_rfc3339('2006-01-01T23:60:08Z') == 'invalid minute: 60'
223 assert invalid_rfc3339('2006-01-01T23:99:08Z') == 'invalid minute: 99'
224 assert invalid_rfc3339('2006-01-01T23:59:60Z') == 'invalid second: 60'
225 assert invalid_rfc3339('2006-01-01T23:59:99Z') == 'invalid second: 99'
226 assert invalid_rfc3339('1979-05-27X07:32:00Z') == 'invalid date-time separator:X'
227 assert invalid_rfc3339('1979-05-27T07:32:00') == 'timezone error: datetime string is too short'
228 assert invalid_rfc3339('1979-05-27') == 'date-time too short to parse'
229 assert invalid_rfc3339('1979-05-27T00:32:00.999999') == 'timezone error: expected "Z" or "z" or "+" or "-" in position 26, not "9"'
230 assert invalid_rfc3339('1979-05-27T00:32:00.') == 'timezone error: expected "Z" or "z" at the end of the string'
231}
232
233fn test_parse_rfc3339_offset() {
234 pairs := [
235 ['2024-01-15T14:00:00+01:35', '2024-01-15 12:25:00'],
236 ['2024-01-15T14:10:00+01:40', '2024-01-15 12:30:00'],
237 ['2024-01-15T14:00:00+10:55', '2024-01-15 03:05:00'],
238 ]
239 for pair in pairs {
240 input, expected := pair[0], pair[1]
241 res := time.parse_rfc3339(input)!
242 assert res.str() == expected
243 }
244}
245
246fn test_parse_rfc2616() {
247 mut r := time.parse_rfc2616('Wed, 06 Nov 2024 08:49:37 GMT')!
248 assert r.unix() == 1730882977
249
250 r = time.parse_rfc2616('Wednesday, 06-Nov-24 08:49:37 GMT')!
251 assert r.unix() == 1730882977
252
253 r = time.parse_rfc2616('Wed Nov 6 08:49:37 2024')!
254 assert r.unix() == 1730882977
255
256 r = time.parse_rfc2616('Thu, 19 Feb 2026 11:07:09 GMT')!
257 assert r.unix() == 1771499229
258
259 r = time.parse_rfc2616('Tuesday, 19-Feb-26 11:07:09 GMT')!
260 assert r.unix() == 1771499229
261
262 r = time.parse_rfc2616('Thu Feb 19 11:07:09 2026')!
263 assert r.unix() == 1771499229
264
265 // This should map to 1994, not 2094.
266 r = time.parse_rfc2616('Tuesday, 06-Nov-94 11:07:09 GMT')!
267 assert r.unix() == 784120029
268
269 // This should map to 2020, not 1920.
270 r = time.parse_rfc2616('Friday, 06-Nov-20 08:49:37 GMT')!
271 assert r.unix() == 1604652577
272}
273
274fn test_parse_http_header_string() {
275 t := time.now()
276 header := t.http_header_string()
277 back_time := time.parse_http_header_string(header)!
278 assert t.str() == back_time.str()
279}
280
281fn test_ad_second_to_parse_result_in_2001() {
282 now_tm := time.parse('2001-01-01 04:00:00')!
283 future_tm := now_tm.add_seconds(60)
284 assert future_tm.str() == '2001-01-01 04:01:00'
285 assert now_tm.unix() < future_tm.unix()
286}
287
288fn test_ad_second_to_parse_result_pre_2001() {
289 now_tm := time.parse('2000-01-01 04:00:00')!
290 future_tm := now_tm.add_seconds(60)
291 assert future_tm.str() == '2000-01-01 04:01:00'
292 assert now_tm.unix() < future_tm.unix()
293}
294
295fn test_parse_format() {
296 mut s := '2018-01-27 12:48:34'
297 mut t := time.parse_format(s, 'YYYY-MM-DD HH:mm:ss') or {
298 assert false, '> failing format: ${s} | err: ${err}'
299 return
300 }
301 assert t.year == 2018 && t.month == 1 && t.day == 27 && t.hour == 12 && t.minute == 48
302 && t.second == 34
303
304 s = '2018-November-27 12:48:20'
305 t = time.parse_format(s, 'YYYY-MMMM-DD HH:mm:ss') or {
306 assert false, '> failing format: ${s} | err: ${err}'
307 return
308 }
309 assert t.year == 2018 && t.month == 11 && t.day == 27 && t.hour == 12 && t.minute == 48
310 && t.second == 20
311
312 s = '18-1-2 0:8:2'
313 t = time.parse_format(s, 'YY-M-D H:m:s') or {
314 assert false, '> failing format: ${s} | err: ${err}'
315 return
316 }
317 assert t.year == 2018 && t.month == 1 && t.day == 2 && t.hour == 0 && t.minute == 8
318 && t.second == 2
319
320 // This should always fail, because we test if M and D allow for a 01 value which they shouldn't
321 s = '2018-01-02 1:8:2'
322 t = time.parse_format(s, 'YYYY-M-D H:m:s') or { return }
323
324 assert false, '> failing for datetime: ${s}, the datetime string should not have passed the format "YYYY-M-D H:m:s"'
325}
326