]>
Commit | Line | Data |
---|---|---|
1d09f67e TL |
1 | // Licensed to the Apache Software Foundation (ASF) under one |
2 | // or more contributor license agreements. See the NOTICE file | |
3 | // distributed with this work for additional information | |
4 | // regarding copyright ownership. The ASF licenses this file | |
5 | // to you under the Apache License, Version 2.0 (the | |
6 | // "License"); you may not use this file except in compliance | |
7 | // with the License. You may obtain a copy of the License at | |
8 | // | |
9 | // http://www.apache.org/licenses/LICENSE-2.0 | |
10 | // | |
11 | // Unless required by applicable law or agreed to in writing, | |
12 | // software distributed under the License is distributed on an | |
13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | // KIND, either express or implied. See the License for the | |
15 | // specific language governing permissions and limitations | |
16 | // under the License. | |
17 | ||
18 | #include <string> | |
19 | #include <vector> | |
20 | ||
21 | #include <gtest/gtest.h> | |
22 | ||
23 | #include "arrow/testing/gtest_util.h" | |
24 | #include "arrow/type.h" | |
25 | #include "arrow/util/value_parsing.h" | |
26 | ||
27 | namespace arrow { | |
28 | namespace internal { | |
29 | ||
30 | template <typename T> | |
31 | void AssertConversion(const T& type, const std::string& s, typename T::c_type expected) { | |
32 | typename T::c_type out{}; | |
33 | ASSERT_TRUE(ParseValue(type, s.data(), s.length(), &out)) | |
34 | << "Conversion failed for '" << s << "' (expected to return " << expected << ")"; | |
35 | ASSERT_EQ(out, expected) << "Conversion failed for '" << s << "'"; | |
36 | } | |
37 | ||
38 | template <typename T> | |
39 | void AssertConversion(const std::string& s, typename T::c_type expected) { | |
40 | auto type = checked_pointer_cast<T>(TypeTraits<T>::type_singleton()); | |
41 | AssertConversion(*type, s, expected); | |
42 | } | |
43 | ||
44 | template <typename T> | |
45 | void AssertConversionFails(const T& type, const std::string& s) { | |
46 | typename T::c_type out{}; | |
47 | ASSERT_FALSE(ParseValue(type, s.data(), s.length(), &out)) | |
48 | << "Conversion should have failed for '" << s << "' (returned " << out << ")"; | |
49 | } | |
50 | ||
51 | template <typename T> | |
52 | void AssertConversionFails(const std::string& s) { | |
53 | auto type = checked_pointer_cast<T>(TypeTraits<T>::type_singleton()); | |
54 | AssertConversionFails(*type, s); | |
55 | } | |
56 | ||
57 | TEST(StringConversion, ToBoolean) { | |
58 | AssertConversion<BooleanType>("true", true); | |
59 | AssertConversion<BooleanType>("tRuE", true); | |
60 | AssertConversion<BooleanType>("FAlse", false); | |
61 | AssertConversion<BooleanType>("false", false); | |
62 | AssertConversion<BooleanType>("1", true); | |
63 | AssertConversion<BooleanType>("0", false); | |
64 | ||
65 | AssertConversionFails<BooleanType>(""); | |
66 | } | |
67 | ||
68 | TEST(StringConversion, ToFloat) { | |
69 | AssertConversion<FloatType>("1.5", 1.5f); | |
70 | AssertConversion<FloatType>("0", 0.0f); | |
71 | // XXX ASSERT_EQ doesn't distinguish signed zeros | |
72 | AssertConversion<FloatType>("-0.0", -0.0f); | |
73 | AssertConversion<FloatType>("-1e20", -1e20f); | |
74 | ||
75 | AssertConversionFails<FloatType>(""); | |
76 | AssertConversionFails<FloatType>("e"); | |
77 | } | |
78 | ||
79 | TEST(StringConversion, ToDouble) { | |
80 | AssertConversion<DoubleType>("1.5", 1.5); | |
81 | AssertConversion<DoubleType>("0", 0); | |
82 | // XXX ASSERT_EQ doesn't distinguish signed zeros | |
83 | AssertConversion<DoubleType>("-0.0", -0.0); | |
84 | AssertConversion<DoubleType>("-1e100", -1e100); | |
85 | ||
86 | AssertConversionFails<DoubleType>(""); | |
87 | AssertConversionFails<DoubleType>("e"); | |
88 | } | |
89 | ||
90 | #if !defined(_WIN32) || defined(NDEBUG) | |
91 | ||
92 | TEST(StringConversion, ToFloatLocale) { | |
93 | // French locale uses the comma as decimal point | |
94 | LocaleGuard locale_guard("fr_FR.UTF-8"); | |
95 | ||
96 | AssertConversion<FloatType>("1.5", 1.5f); | |
97 | } | |
98 | ||
99 | TEST(StringConversion, ToDoubleLocale) { | |
100 | // French locale uses the comma as decimal point | |
101 | LocaleGuard locale_guard("fr_FR.UTF-8"); | |
102 | ||
103 | AssertConversion<DoubleType>("1.5", 1.5f); | |
104 | } | |
105 | ||
106 | #endif // _WIN32 | |
107 | ||
108 | TEST(StringConversion, ToInt8) { | |
109 | AssertConversion<Int8Type>("0", 0); | |
110 | AssertConversion<Int8Type>("127", 127); | |
111 | AssertConversion<Int8Type>("0127", 127); | |
112 | AssertConversion<Int8Type>("-128", -128); | |
113 | AssertConversion<Int8Type>("-00128", -128); | |
114 | ||
115 | // Non-representable values | |
116 | AssertConversionFails<Int8Type>("128"); | |
117 | AssertConversionFails<Int8Type>("-129"); | |
118 | ||
119 | AssertConversionFails<Int8Type>(""); | |
120 | AssertConversionFails<Int8Type>("-"); | |
121 | AssertConversionFails<Int8Type>("0.0"); | |
122 | AssertConversionFails<Int8Type>("e"); | |
123 | ||
124 | // Hex | |
125 | AssertConversion<Int8Type>("0x0", 0); | |
126 | AssertConversion<Int8Type>("0X1A", 26); | |
127 | AssertConversion<Int8Type>("0xb", 11); | |
128 | AssertConversion<Int8Type>("0x7F", 127); | |
129 | AssertConversion<Int8Type>("0xFF", -1); | |
130 | AssertConversionFails<Int8Type>("0x"); | |
131 | AssertConversionFails<Int8Type>("0x100"); | |
132 | AssertConversionFails<Int8Type>("0x1g"); | |
133 | } | |
134 | ||
135 | TEST(StringConversion, ToUInt8) { | |
136 | AssertConversion<UInt8Type>("0", 0); | |
137 | AssertConversion<UInt8Type>("26", 26); | |
138 | AssertConversion<UInt8Type>("255", 255); | |
139 | AssertConversion<UInt8Type>("0255", 255); | |
140 | ||
141 | // Non-representable values | |
142 | AssertConversionFails<UInt8Type>("-1"); | |
143 | AssertConversionFails<UInt8Type>("256"); | |
144 | AssertConversionFails<UInt8Type>("260"); | |
145 | AssertConversionFails<UInt8Type>("1234"); | |
146 | ||
147 | AssertConversionFails<UInt8Type>(""); | |
148 | AssertConversionFails<UInt8Type>("-"); | |
149 | AssertConversionFails<UInt8Type>("0.0"); | |
150 | AssertConversionFails<UInt8Type>("e"); | |
151 | ||
152 | // Hex | |
153 | AssertConversion<UInt8Type>("0x0", 0); | |
154 | AssertConversion<UInt8Type>("0x1A", 26); | |
155 | AssertConversion<UInt8Type>("0xb", 11); | |
156 | AssertConversion<UInt8Type>("0x7F", 127); | |
157 | AssertConversion<UInt8Type>("0xFF", 255); | |
158 | AssertConversionFails<UInt8Type>("0x"); | |
159 | AssertConversionFails<UInt8Type>("0x100"); | |
160 | AssertConversionFails<UInt8Type>("0x1g"); | |
161 | } | |
162 | ||
163 | TEST(StringConversion, ToInt16) { | |
164 | AssertConversion<Int16Type>("0", 0); | |
165 | AssertConversion<Int16Type>("32767", 32767); | |
166 | AssertConversion<Int16Type>("032767", 32767); | |
167 | AssertConversion<Int16Type>("-32768", -32768); | |
168 | AssertConversion<Int16Type>("-0032768", -32768); | |
169 | ||
170 | // Non-representable values | |
171 | AssertConversionFails<Int16Type>("32768"); | |
172 | AssertConversionFails<Int16Type>("-32769"); | |
173 | ||
174 | AssertConversionFails<Int16Type>(""); | |
175 | AssertConversionFails<Int16Type>("-"); | |
176 | AssertConversionFails<Int16Type>("0.0"); | |
177 | AssertConversionFails<Int16Type>("e"); | |
178 | ||
179 | // Hex | |
180 | AssertConversion<Int16Type>("0x0", 0); | |
181 | AssertConversion<Int16Type>("0X1aA", 426); | |
182 | AssertConversion<Int16Type>("0xb", 11); | |
183 | AssertConversion<Int16Type>("0x7ffF", 32767); | |
184 | AssertConversion<Int16Type>("0XfffF", -1); | |
185 | AssertConversionFails<Int16Type>("0x"); | |
186 | AssertConversionFails<Int16Type>("0x10000"); | |
187 | AssertConversionFails<Int16Type>("0x1g"); | |
188 | } | |
189 | ||
190 | TEST(StringConversion, ToUInt16) { | |
191 | AssertConversion<UInt16Type>("0", 0); | |
192 | AssertConversion<UInt16Type>("6660", 6660); | |
193 | AssertConversion<UInt16Type>("65535", 65535); | |
194 | AssertConversion<UInt16Type>("065535", 65535); | |
195 | ||
196 | // Non-representable values | |
197 | AssertConversionFails<UInt16Type>("-1"); | |
198 | AssertConversionFails<UInt16Type>("65536"); | |
199 | AssertConversionFails<UInt16Type>("123456"); | |
200 | ||
201 | AssertConversionFails<UInt16Type>(""); | |
202 | AssertConversionFails<UInt16Type>("-"); | |
203 | AssertConversionFails<UInt16Type>("0.0"); | |
204 | AssertConversionFails<UInt16Type>("e"); | |
205 | ||
206 | // Hex | |
207 | AssertConversion<UInt16Type>("0x0", 0); | |
208 | AssertConversion<UInt16Type>("0x1aA", 426); | |
209 | AssertConversion<UInt16Type>("0xb", 11); | |
210 | AssertConversion<UInt16Type>("0x7ffF", 32767); | |
211 | AssertConversion<UInt16Type>("0xFffF", 65535); | |
212 | AssertConversionFails<UInt16Type>("0x"); | |
213 | AssertConversionFails<UInt16Type>("0x10000"); | |
214 | AssertConversionFails<UInt16Type>("0x1g"); | |
215 | } | |
216 | ||
217 | TEST(StringConversion, ToInt32) { | |
218 | AssertConversion<Int32Type>("0", 0); | |
219 | AssertConversion<Int32Type>("2147483647", 2147483647); | |
220 | AssertConversion<Int32Type>("02147483647", 2147483647); | |
221 | AssertConversion<Int32Type>("-2147483648", -2147483648LL); | |
222 | AssertConversion<Int32Type>("-002147483648", -2147483648LL); | |
223 | ||
224 | // Non-representable values | |
225 | AssertConversionFails<Int32Type>("2147483648"); | |
226 | AssertConversionFails<Int32Type>("-2147483649"); | |
227 | ||
228 | AssertConversionFails<Int32Type>(""); | |
229 | AssertConversionFails<Int32Type>("-"); | |
230 | AssertConversionFails<Int32Type>("0.0"); | |
231 | AssertConversionFails<Int32Type>("e"); | |
232 | ||
233 | // Hex | |
234 | AssertConversion<Int32Type>("0x0", 0); | |
235 | AssertConversion<Int32Type>("0x123ABC", 1194684); | |
236 | AssertConversion<Int32Type>("0xA4B35", 674613); | |
237 | AssertConversion<Int32Type>("0x7FFFFFFF", 2147483647); | |
238 | AssertConversion<Int32Type>("0x123abc", 1194684); | |
239 | AssertConversion<Int32Type>("0xA4b35", 674613); | |
240 | AssertConversion<Int32Type>("0x7FFFfFfF", 2147483647); | |
241 | AssertConversion<Int32Type>("0XFFFFfFfF", -1); | |
242 | AssertConversionFails<Int32Type>("0X"); | |
243 | AssertConversionFails<Int32Type>("0x23512ak"); | |
244 | } | |
245 | ||
246 | TEST(StringConversion, ToUInt32) { | |
247 | AssertConversion<UInt32Type>("0", 0); | |
248 | AssertConversion<UInt32Type>("432198765", 432198765UL); | |
249 | AssertConversion<UInt32Type>("4294967295", 4294967295UL); | |
250 | AssertConversion<UInt32Type>("04294967295", 4294967295UL); | |
251 | ||
252 | // Non-representable values | |
253 | AssertConversionFails<UInt32Type>("-1"); | |
254 | AssertConversionFails<UInt32Type>("4294967296"); | |
255 | AssertConversionFails<UInt32Type>("12345678901"); | |
256 | ||
257 | AssertConversionFails<UInt32Type>(""); | |
258 | AssertConversionFails<UInt32Type>("-"); | |
259 | AssertConversionFails<UInt32Type>("0.0"); | |
260 | AssertConversionFails<UInt32Type>("e"); | |
261 | ||
262 | // Hex | |
263 | AssertConversion<UInt32Type>("0x0", 0); | |
264 | AssertConversion<UInt32Type>("0x123ABC", 1194684); | |
265 | AssertConversion<UInt32Type>("0xA4B35", 674613); | |
266 | AssertConversion<UInt32Type>("0x7FFFFFFF", 2147483647); | |
267 | AssertConversion<UInt32Type>("0x123abc", 1194684); | |
268 | AssertConversion<UInt32Type>("0xA4b35", 674613); | |
269 | AssertConversion<UInt32Type>("0x7FFFfFfF", 2147483647); | |
270 | AssertConversion<UInt32Type>("0XFFFFfFfF", 4294967295); | |
271 | AssertConversionFails<UInt32Type>("0X"); | |
272 | AssertConversionFails<UInt32Type>("0x23512ak"); | |
273 | } | |
274 | ||
275 | TEST(StringConversion, ToInt64) { | |
276 | AssertConversion<Int64Type>("0", 0); | |
277 | AssertConversion<Int64Type>("9223372036854775807", 9223372036854775807LL); | |
278 | AssertConversion<Int64Type>("09223372036854775807", 9223372036854775807LL); | |
279 | AssertConversion<Int64Type>("-9223372036854775808", -9223372036854775807LL - 1); | |
280 | AssertConversion<Int64Type>("-009223372036854775808", -9223372036854775807LL - 1); | |
281 | ||
282 | // Non-representable values | |
283 | AssertConversionFails<Int64Type>("9223372036854775808"); | |
284 | AssertConversionFails<Int64Type>("-9223372036854775809"); | |
285 | ||
286 | AssertConversionFails<Int64Type>(""); | |
287 | AssertConversionFails<Int64Type>("-"); | |
288 | AssertConversionFails<Int64Type>("0.0"); | |
289 | AssertConversionFails<Int64Type>("e"); | |
290 | ||
291 | // Hex | |
292 | AssertConversion<Int64Type>("0x0", 0); | |
293 | AssertConversion<Int64Type>("0x5415a123ABC123cb", 6058926048274359243); | |
294 | AssertConversion<Int64Type>("0xA4B35", 674613); | |
295 | AssertConversion<Int64Type>("0x7FFFFFFFFFFFFFFf", 9223372036854775807); | |
296 | AssertConversion<Int64Type>("0XF000000000000001", -1152921504606846975); | |
297 | AssertConversion<Int64Type>("0xfFFFFFFFFFFFFFFf", -1); | |
298 | AssertConversionFails<Int64Type>("0X"); | |
299 | AssertConversionFails<Int64Type>("0x12345678901234567"); | |
300 | AssertConversionFails<Int64Type>("0x23512ak"); | |
301 | } | |
302 | ||
303 | TEST(StringConversion, ToUInt64) { | |
304 | AssertConversion<UInt64Type>("0", 0); | |
305 | AssertConversion<UInt64Type>("18446744073709551615", 18446744073709551615ULL); | |
306 | ||
307 | // Non-representable values | |
308 | AssertConversionFails<UInt64Type>("-1"); | |
309 | AssertConversionFails<UInt64Type>("18446744073709551616"); | |
310 | ||
311 | AssertConversionFails<UInt64Type>(""); | |
312 | AssertConversionFails<UInt64Type>("-"); | |
313 | AssertConversionFails<UInt64Type>("0.0"); | |
314 | AssertConversionFails<UInt64Type>("e"); | |
315 | ||
316 | // Hex | |
317 | AssertConversion<UInt64Type>("0x0", 0); | |
318 | AssertConversion<UInt64Type>("0x5415a123ABC123cb", 6058926048274359243); | |
319 | AssertConversion<UInt64Type>("0xA4B35", 674613); | |
320 | AssertConversion<UInt64Type>("0x7FFFFFFFFFFFFFFf", 9223372036854775807); | |
321 | AssertConversion<UInt64Type>("0XF000000000000001", 17293822569102704641ULL); | |
322 | AssertConversion<UInt64Type>("0xfFFFFFFFFFFFFFFf", 18446744073709551615ULL); | |
323 | AssertConversionFails<UInt64Type>("0x"); | |
324 | AssertConversionFails<UInt64Type>("0x12345678901234567"); | |
325 | AssertConversionFails<UInt64Type>("0x23512ak"); | |
326 | } | |
327 | ||
328 | TEST(StringConversion, ToDate32) { | |
329 | AssertConversion<Date32Type>("1970-01-01", 0); | |
330 | AssertConversion<Date32Type>("1970-01-02", 1); | |
331 | AssertConversion<Date32Type>("2020-03-15", 18336); | |
332 | AssertConversion<Date32Type>("1945-05-08", -9004); | |
333 | AssertConversion<Date32Type>("4707-11-28", 999999); | |
334 | AssertConversion<Date32Type>("0001-01-01", -719162); | |
335 | ||
336 | // Invalid format | |
337 | AssertConversionFails<Date32Type>(""); | |
338 | AssertConversionFails<Date32Type>("1970"); | |
339 | AssertConversionFails<Date32Type>("1970-01"); | |
340 | AssertConversionFails<Date32Type>("1970-01-01 00:00:00"); | |
341 | AssertConversionFails<Date32Type>("1970/01/01"); | |
342 | } | |
343 | ||
344 | TEST(StringConversion, ToDate64) { | |
345 | AssertConversion<Date64Type>("1970-01-01", 0); | |
346 | AssertConversion<Date64Type>("1970-01-02", 86400000); | |
347 | AssertConversion<Date64Type>("2020-03-15", 1584230400000LL); | |
348 | AssertConversion<Date64Type>("1945-05-08", -777945600000LL); | |
349 | AssertConversion<Date64Type>("4707-11-28", 86399913600000LL); | |
350 | AssertConversion<Date64Type>("0001-01-01", -62135596800000LL); | |
351 | } | |
352 | ||
353 | template <typename T> | |
354 | void AssertInvalidTimes(const T& type) { | |
355 | // Invalid time format | |
356 | AssertConversionFails(type, ""); | |
357 | AssertConversionFails(type, "00"); | |
358 | AssertConversionFails(type, "00:"); | |
359 | AssertConversionFails(type, "00:00:"); | |
360 | AssertConversionFails(type, "00:00:00:"); | |
361 | AssertConversionFails(type, "000000"); | |
362 | AssertConversionFails(type, "000000.000"); | |
363 | ||
364 | // Invalid time value | |
365 | AssertConversionFails(type, "24:00:00"); | |
366 | AssertConversionFails(type, "00:60:00"); | |
367 | AssertConversionFails(type, "00:00:60"); | |
368 | } | |
369 | ||
370 | TEST(StringConversion, ToTime32) { | |
371 | { | |
372 | Time32Type type{TimeUnit::SECOND}; | |
373 | ||
374 | AssertConversion(type, "00:00", 0); | |
375 | AssertConversion(type, "01:23", 4980); | |
376 | AssertConversion(type, "23:59", 86340); | |
377 | ||
378 | AssertConversion(type, "00:00:00", 0); | |
379 | AssertConversion(type, "01:23:45", 5025); | |
380 | AssertConversion(type, "23:45:43", 85543); | |
381 | AssertConversion(type, "23:59:59", 86399); | |
382 | ||
383 | AssertInvalidTimes(type); | |
384 | // No subseconds allowed | |
385 | AssertConversionFails(type, "00:00:00.123"); | |
386 | } | |
387 | { | |
388 | Time32Type type{TimeUnit::MILLI}; | |
389 | ||
390 | AssertConversion(type, "00:00", 0); | |
391 | AssertConversion(type, "01:23", 4980000); | |
392 | AssertConversion(type, "23:59", 86340000); | |
393 | ||
394 | AssertConversion(type, "00:00:00", 0); | |
395 | AssertConversion(type, "01:23:45", 5025000); | |
396 | AssertConversion(type, "23:45:43", 85543000); | |
397 | AssertConversion(type, "23:59:59", 86399000); | |
398 | ||
399 | AssertConversion(type, "00:00:00.123", 123); | |
400 | AssertConversion(type, "01:23:45.000", 5025000); | |
401 | AssertConversion(type, "01:23:45.1", 5025100); | |
402 | AssertConversion(type, "01:23:45.123", 5025123); | |
403 | AssertConversion(type, "01:23:45.999", 5025999); | |
404 | ||
405 | AssertInvalidTimes(type); | |
406 | // Invalid subseconds | |
407 | AssertConversionFails(type, "00:00:00.1234"); | |
408 | } | |
409 | } | |
410 | ||
411 | TEST(StringConversion, ToTime64) { | |
412 | { | |
413 | Time64Type type{TimeUnit::MICRO}; | |
414 | ||
415 | AssertConversion(type, "00:00:00", 0LL); | |
416 | AssertConversion(type, "01:23:45", 5025000000LL); | |
417 | AssertConversion(type, "23:45:43", 85543000000LL); | |
418 | AssertConversion(type, "23:59:59", 86399000000LL); | |
419 | ||
420 | AssertConversion(type, "00:00:00.123456", 123456LL); | |
421 | AssertConversion(type, "01:23:45.000000", 5025000000LL); | |
422 | AssertConversion(type, "01:23:45.1", 5025100000LL); | |
423 | AssertConversion(type, "01:23:45.123", 5025123000LL); | |
424 | AssertConversion(type, "01:23:45.999999", 5025999999LL); | |
425 | ||
426 | AssertInvalidTimes(type); | |
427 | // Invalid subseconds | |
428 | AssertConversionFails(type, "00:00:00.1234567"); | |
429 | } | |
430 | { | |
431 | Time64Type type{TimeUnit::NANO}; | |
432 | ||
433 | AssertConversion(type, "00:00:00", 0LL); | |
434 | AssertConversion(type, "01:23:45", 5025000000000LL); | |
435 | AssertConversion(type, "23:45:43", 85543000000000LL); | |
436 | AssertConversion(type, "23:59:59", 86399000000000LL); | |
437 | ||
438 | AssertConversion(type, "00:00:00.123456789", 123456789LL); | |
439 | AssertConversion(type, "01:23:45.000000000", 5025000000000LL); | |
440 | AssertConversion(type, "01:23:45.1", 5025100000000LL); | |
441 | AssertConversion(type, "01:23:45.1234", 5025123400000LL); | |
442 | AssertConversion(type, "01:23:45.999999999", 5025999999999LL); | |
443 | ||
444 | AssertInvalidTimes(type); | |
445 | // Invalid subseconds | |
446 | AssertConversionFails(type, "00:00:00.1234567891"); | |
447 | } | |
448 | } | |
449 | ||
450 | TEST(StringConversion, ToTimestampDate_ISO8601) { | |
451 | { | |
452 | TimestampType type{TimeUnit::SECOND}; | |
453 | ||
454 | AssertConversion(type, "1970-01-01", 0); | |
455 | AssertConversion(type, "1989-07-14", 616377600); | |
456 | AssertConversion(type, "2000-02-29", 951782400); | |
457 | AssertConversion(type, "3989-07-14", 63730281600LL); | |
458 | AssertConversion(type, "1900-02-28", -2203977600LL); | |
459 | ||
460 | AssertConversionFails(type, ""); | |
461 | AssertConversionFails(type, "1970"); | |
462 | AssertConversionFails(type, "19700101"); | |
463 | AssertConversionFails(type, "1970/01/01"); | |
464 | AssertConversionFails(type, "1970-01-01 "); | |
465 | AssertConversionFails(type, "1970-01-01Z"); | |
466 | ||
467 | // Invalid dates | |
468 | AssertConversionFails(type, "1970-00-01"); | |
469 | AssertConversionFails(type, "1970-13-01"); | |
470 | AssertConversionFails(type, "1970-01-32"); | |
471 | AssertConversionFails(type, "1970-02-29"); | |
472 | AssertConversionFails(type, "2100-02-29"); | |
473 | } | |
474 | { | |
475 | TimestampType type{TimeUnit::MILLI}; | |
476 | ||
477 | AssertConversion(type, "1970-01-01", 0); | |
478 | AssertConversion(type, "1989-07-14", 616377600000LL); | |
479 | AssertConversion(type, "3989-07-14", 63730281600000LL); | |
480 | AssertConversion(type, "1900-02-28", -2203977600000LL); | |
481 | } | |
482 | { | |
483 | TimestampType type{TimeUnit::MICRO}; | |
484 | ||
485 | AssertConversion(type, "1970-01-01", 0); | |
486 | AssertConversion(type, "1989-07-14", 616377600000000LL); | |
487 | AssertConversion(type, "3989-07-14", 63730281600000000LL); | |
488 | AssertConversion(type, "1900-02-28", -2203977600000000LL); | |
489 | } | |
490 | { | |
491 | TimestampType type{TimeUnit::NANO}; | |
492 | ||
493 | AssertConversion(type, "1970-01-01", 0); | |
494 | AssertConversion(type, "1989-07-14", 616377600000000000LL); | |
495 | AssertConversion(type, "2018-11-13", 1542067200000000000LL); | |
496 | AssertConversion(type, "1900-02-28", -2203977600000000000LL); | |
497 | } | |
498 | } | |
499 | ||
500 | TEST(StringConversion, ToTimestampDateTime_ISO8601) { | |
501 | { | |
502 | TimestampType type{TimeUnit::SECOND}; | |
503 | ||
504 | AssertConversion(type, "1970-01-01 00:00:00", 0); | |
505 | AssertConversion(type, "2018-11-13 17", 1542128400); | |
506 | AssertConversion(type, "2018-11-13T17", 1542128400); | |
507 | AssertConversion(type, "2018-11-13 17Z", 1542128400); | |
508 | AssertConversion(type, "2018-11-13T17Z", 1542128400); | |
509 | AssertConversion(type, "2018-11-13 17:11", 1542129060); | |
510 | AssertConversion(type, "2018-11-13T17:11", 1542129060); | |
511 | AssertConversion(type, "2018-11-13 17:11Z", 1542129060); | |
512 | AssertConversion(type, "2018-11-13T17:11Z", 1542129060); | |
513 | AssertConversion(type, "2018-11-13 17:11:10", 1542129070); | |
514 | AssertConversion(type, "2018-11-13T17:11:10", 1542129070); | |
515 | AssertConversion(type, "2018-11-13 17:11:10Z", 1542129070); | |
516 | AssertConversion(type, "2018-11-13T17:11:10Z", 1542129070); | |
517 | AssertConversion(type, "1900-02-28 12:34:56", -2203932304LL); | |
518 | ||
519 | // No subseconds allowed | |
520 | AssertConversionFails(type, "1900-02-28 12:34:56.001"); | |
521 | // Invalid dates | |
522 | AssertConversionFails(type, "1970-02-29 00:00:00"); | |
523 | AssertConversionFails(type, "2100-02-29 00:00:00"); | |
524 | // Invalid times | |
525 | AssertConversionFails(type, "1970-01-01 24"); | |
526 | AssertConversionFails(type, "1970-01-01 00:60"); | |
527 | AssertConversionFails(type, "1970-01-01 00,00"); | |
528 | AssertConversionFails(type, "1970-01-01 24:00:00"); | |
529 | AssertConversionFails(type, "1970-01-01 00:60:00"); | |
530 | AssertConversionFails(type, "1970-01-01 00:00:60"); | |
531 | AssertConversionFails(type, "1970-01-01 00:00,00"); | |
532 | AssertConversionFails(type, "1970-01-01 00,00:00"); | |
533 | } | |
534 | { | |
535 | TimestampType type{TimeUnit::MILLI}; | |
536 | ||
537 | AssertConversion(type, "2018-11-13 17:11:10", 1542129070000LL); | |
538 | AssertConversion(type, "2018-11-13T17:11:10Z", 1542129070000LL); | |
539 | AssertConversion(type, "3989-07-14T11:22:33Z", 63730322553000LL); | |
540 | AssertConversion(type, "1900-02-28 12:34:56", -2203932304000LL); | |
541 | AssertConversion(type, "2018-11-13T17:11:10.777Z", 1542129070777LL); | |
542 | ||
543 | AssertConversion(type, "1900-02-28 12:34:56.1", -2203932304000LL + 100LL); | |
544 | AssertConversion(type, "1900-02-28 12:34:56.12", -2203932304000LL + 120LL); | |
545 | AssertConversion(type, "1900-02-28 12:34:56.123", -2203932304000LL + 123LL); | |
546 | ||
547 | // Invalid subseconds | |
548 | AssertConversionFails(type, "1900-02-28 12:34:56.1234"); | |
549 | AssertConversionFails(type, "1900-02-28 12:34:56.12345"); | |
550 | AssertConversionFails(type, "1900-02-28 12:34:56.123456"); | |
551 | AssertConversionFails(type, "1900-02-28 12:34:56.1234567"); | |
552 | AssertConversionFails(type, "1900-02-28 12:34:56.12345678"); | |
553 | AssertConversionFails(type, "1900-02-28 12:34:56.123456789"); | |
554 | } | |
555 | { | |
556 | TimestampType type{TimeUnit::MICRO}; | |
557 | ||
558 | AssertConversion(type, "2018-11-13 17:11:10", 1542129070000000LL); | |
559 | AssertConversion(type, "2018-11-13T17:11:10Z", 1542129070000000LL); | |
560 | AssertConversion(type, "3989-07-14T11:22:33Z", 63730322553000000LL); | |
561 | AssertConversion(type, "1900-02-28 12:34:56", -2203932304000000LL); | |
562 | AssertConversion(type, "2018-11-13T17:11:10.777000", 1542129070777000LL); | |
563 | AssertConversion(type, "3989-07-14T11:22:33.000777Z", 63730322553000777LL); | |
564 | ||
565 | AssertConversion(type, "1900-02-28 12:34:56.1", -2203932304000000LL + 100000LL); | |
566 | AssertConversion(type, "1900-02-28 12:34:56.12", -2203932304000000LL + 120000LL); | |
567 | AssertConversion(type, "1900-02-28 12:34:56.123", -2203932304000000LL + 123000LL); | |
568 | AssertConversion(type, "1900-02-28 12:34:56.1234", -2203932304000000LL + 123400LL); | |
569 | AssertConversion(type, "1900-02-28 12:34:56.12345", -2203932304000000LL + 123450LL); | |
570 | AssertConversion(type, "1900-02-28 12:34:56.123456", -2203932304000000LL + 123456LL); | |
571 | ||
572 | // Invalid subseconds | |
573 | AssertConversionFails(type, "1900-02-28 12:34:56.1234567"); | |
574 | AssertConversionFails(type, "1900-02-28 12:34:56.12345678"); | |
575 | AssertConversionFails(type, "1900-02-28 12:34:56.123456789"); | |
576 | } | |
577 | { | |
578 | TimestampType type{TimeUnit::NANO}; | |
579 | ||
580 | AssertConversion(type, "2018-11-13 17:11:10", 1542129070000000000LL); | |
581 | AssertConversion(type, "2018-11-13T17:11:10Z", 1542129070000000000LL); | |
582 | AssertConversion(type, "1900-02-28 12:34:56", -2203932304000000000LL); | |
583 | AssertConversion(type, "2018-11-13 17:11:10.777000000", 1542129070777000000LL); | |
584 | AssertConversion(type, "2018-11-13T17:11:10.000777000Z", 1542129070000777000LL); | |
585 | AssertConversion(type, "1969-12-31 23:59:59.999999999", -1); | |
586 | ||
587 | AssertConversion(type, "1900-02-28 12:34:56.1", -2203932304000000000LL + 100000000LL); | |
588 | AssertConversion(type, "1900-02-28 12:34:56.12", | |
589 | -2203932304000000000LL + 120000000LL); | |
590 | AssertConversion(type, "1900-02-28 12:34:56.123", | |
591 | -2203932304000000000LL + 123000000LL); | |
592 | AssertConversion(type, "1900-02-28 12:34:56.1234", | |
593 | -2203932304000000000LL + 123400000LL); | |
594 | AssertConversion(type, "1900-02-28 12:34:56.12345", | |
595 | -2203932304000000000LL + 123450000LL); | |
596 | AssertConversion(type, "1900-02-28 12:34:56.123456", | |
597 | -2203932304000000000LL + 123456000LL); | |
598 | AssertConversion(type, "1900-02-28 12:34:56.1234567", | |
599 | -2203932304000000000LL + 123456700LL); | |
600 | AssertConversion(type, "1900-02-28 12:34:56.12345678", | |
601 | -2203932304000000000LL + 123456780LL); | |
602 | AssertConversion(type, "1900-02-28 12:34:56.123456789", | |
603 | -2203932304000000000LL + 123456789LL); | |
604 | ||
605 | // Invalid subseconds | |
606 | } | |
607 | } | |
608 | ||
609 | TEST(TimestampParser, StrptimeParser) { | |
610 | std::string format = "%m/%d/%Y %H:%M:%S"; | |
611 | auto parser = TimestampParser::MakeStrptime(format); | |
612 | ||
613 | struct Case { | |
614 | std::string value; | |
615 | std::string iso8601; | |
616 | }; | |
617 | ||
618 | std::vector<Case> cases = {{"5/31/2000 12:34:56", "2000-05-31 12:34:56"}, | |
619 | {"5/31/2000 00:00:00", "2000-05-31 00:00:00"}}; | |
620 | ||
621 | std::vector<TimeUnit::type> units = {TimeUnit::SECOND, TimeUnit::MILLI, TimeUnit::MICRO, | |
622 | TimeUnit::NANO}; | |
623 | ||
624 | for (auto unit : units) { | |
625 | for (const auto& case_ : cases) { | |
626 | int64_t converted, expected; | |
627 | ASSERT_TRUE((*parser)(case_.value.c_str(), case_.value.size(), unit, &converted)); | |
628 | ASSERT_TRUE(ParseTimestampISO8601(case_.iso8601.c_str(), case_.iso8601.size(), unit, | |
629 | &expected)); | |
630 | ASSERT_EQ(expected, converted); | |
631 | } | |
632 | } | |
633 | ||
634 | // Unparseable strings | |
635 | std::vector<std::string> unparseables = {"foo", "5/1/2000", "5/1/2000 12:34:56:6"}; | |
636 | for (auto& value : unparseables) { | |
637 | int64_t dummy; | |
638 | ASSERT_FALSE((*parser)(value.c_str(), value.size(), TimeUnit::SECOND, &dummy)); | |
639 | } | |
640 | } | |
641 | ||
642 | } // namespace internal | |
643 | } // namespace arrow |