1 /*
2 * Copyright 2019 Content Management AG
3 * All rights reserved.
4 *
5 * author: Max Kellermann <mk@cm4all.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * - Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the
17 * distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "time/ISO8601.hxx"
34
35 #include <gtest/gtest.h>
36
37 static constexpr struct {
38 const char *s;
39 time_t t;
40 std::chrono::system_clock::duration d;
41 } parse_tests[] = {
42 /* full ISO8601 */
43 { "1970-01-01T00:00:00Z", 0, std::chrono::seconds(1) },
44 { "1970-01-01T00:00:01Z", 1, std::chrono::seconds(1) },
45 { "2019-02-04T16:46:41Z", 1549298801, std::chrono::seconds(1) },
46 { "2018-12-31T23:59:59Z", 1546300799, std::chrono::seconds(1) },
47 { "2019-01-01T00:00:00Z", 1546300800, std::chrono::seconds(1) },
48
49 /* full month */
50 { "1970-01", 0, std::chrono::hours(24 * 31) },
51 { "2019-02", 1548979200, std::chrono::hours(24 * 28) },
52 { "2019-01", 1546300800, std::chrono::hours(24 * 31) },
53
54 /* only date */
55 { "1970-01-01", 0, std::chrono::hours(24) },
56 { "2019-02-04", 1549238400, std::chrono::hours(24) },
57 { "2018-12-31", 1546214400, std::chrono::hours(24) },
58 { "2019-01-01", 1546300800, std::chrono::hours(24) },
59
60 /* date with time zone */
61 { "2019-02-04Z", 1549238400, std::chrono::hours(24) },
62
63 /* without time zone */
64 { "2019-02-04T16:46:41", 1549298801, std::chrono::seconds(1) },
65
66 /* without seconds */
67 { "2019-02-04T16:46", 1549298760, std::chrono::minutes(1) },
68 { "2019-02-04T16:46Z", 1549298760, std::chrono::minutes(1) },
69
70 /* without minutes */
71 { "2019-02-04T16", 1549296000, std::chrono::hours(1) },
72 { "2019-02-04T16Z", 1549296000, std::chrono::hours(1) },
73
74 /* with time zone */
75 { "2019-02-04T16:46:41+02", 1549291601, std::chrono::seconds(1) },
76 { "2019-02-04T16:46:41+0200", 1549291601, std::chrono::seconds(1) },
77 { "2019-02-04T16:46:41+02:00", 1549291601, std::chrono::seconds(1) },
78 { "2019-02-04T16:46:41-0200", 1549306001, std::chrono::seconds(1) },
79
80 /* without field separators */
81 { "19700101T000000Z", 0, std::chrono::seconds(1) },
82 { "19700101T000001Z", 1, std::chrono::seconds(1) },
83 { "20190204T164641Z", 1549298801, std::chrono::seconds(1) },
84 { "19700101", 0, std::chrono::hours(24) },
85 { "20190204", 1549238400, std::chrono::hours(24) },
86 { "20190204T1646", 1549298760, std::chrono::minutes(1) },
87 { "20190204T16", 1549296000, std::chrono::hours(1) },
88 };
89
TEST(ISO8601,Parse)90 TEST(ISO8601, Parse)
91 {
92 #ifdef _WIN32
93 // TODO: re-enable when ParseISO8601() has been implemented on Windows
94 GTEST_SKIP();
95 #endif
96
97 for (const auto &i : parse_tests) {
98 const auto result = ParseISO8601(i.s);
99 EXPECT_EQ(std::chrono::system_clock::to_time_t(result.first), i.t);
100 EXPECT_EQ(result.second, i.d);
101 }
102 }
103