@@ -17,9 +17,27 @@ using namespace arrow;
1717using namespace odbcabstraction ;
1818
1919TEST (TEST_TIMESTAMP, TIMESTAMP_WITH_MILLI) {
20- std::vector<int64_t > values = {86400370 , 172800000 , 259200000 , 1649793238110LL ,
21- 345600000 , 432000000 , 518400000 };
22-
20+ std::vector<int64_t > values = {86400370 , 172800000 , 259200000 , 1649793238110LL , 345600000 ,
21+ 432000000 , 518400000 , -86399000 , 0 , -86399999 , -86399001 ,
22+ 86400001 , 86400999 };
23+ std::vector<TIMESTAMP_STRUCT> expected = {
24+ /* year(16), month(u16), day(u16), hour(u16), minute(u16), second(u16), fraction(u32) */
25+ {1970 , 1 , 2 , 0 , 0 , 0 , 370000000 },
26+ {1970 , 1 , 3 , 0 , 0 , 0 , 0 },
27+ {1970 , 1 , 4 , 0 , 0 , 0 , 0 },
28+ {2022 , 4 , 12 , 19 , 53 , 58 , 110000000 },
29+ {1970 , 1 , 5 , 0 , 0 , 0 , 0 },
30+ {1970 , 1 , 6 , 0 , 0 , 0 , 0 },
31+ {1970 , 1 , 7 , 0 , 0 , 0 , 0 },
32+ {1969 , 12 , 31 , 0 , 0 , 1 , 0 },
33+ {1970 , 1 , 1 , 0 , 0 , 0 , 0 },
34+ /* Tests both ends of the fraction rounding range to ensure we don't tip the wrong way */
35+ {1969 , 12 , 31 , 0 , 0 , 0 , 1000000 },
36+ {1969 , 12 , 31 , 0 , 0 , 0 , 999000000 },
37+ {1970 , 1 , 2 , 0 , 0 , 0 , 1000000 },
38+ {1970 , 1 , 2 , 0 , 0 , 0 , 999000000 },
39+ };
40+
2341 std::shared_ptr<Array> timestamp_array;
2442
2543 auto timestamp_field = field (" timestamp_field" , timestamp (TimeUnit::MILLI));
@@ -40,26 +58,31 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILLI) {
4058 for (size_t i = 0 ; i < values.size (); ++i) {
4159 ASSERT_EQ (sizeof (TIMESTAMP_STRUCT), strlen_buffer[i]);
4260
43- tm date{};
44-
45- auto converted_time = values[i] / MILLI_TO_SECONDS_DIVISOR;
46- GetTimeForSecondsSinceEpoch (date, converted_time);
47-
48- ASSERT_EQ (buffer[i].year , 1900 + (date.tm_year ));
49- ASSERT_EQ (buffer[i].month , date.tm_mon + 1 );
50- ASSERT_EQ (buffer[i].day , date.tm_mday );
51- ASSERT_EQ (buffer[i].hour , date.tm_hour );
52- ASSERT_EQ (buffer[i].minute , date.tm_min );
53- ASSERT_EQ (buffer[i].second , date.tm_sec );
54-
55- constexpr uint32_t NANOSECONDS_PER_MILLI = 1000000 ;
56- ASSERT_EQ (buffer[i].fraction , (values[i] % MILLI_TO_SECONDS_DIVISOR) * NANOSECONDS_PER_MILLI);
61+ ASSERT_EQ (buffer[i].year , expected[i].year );
62+ ASSERT_EQ (buffer[i].month , expected[i].month );
63+ ASSERT_EQ (buffer[i].day , expected[i].day );
64+ ASSERT_EQ (buffer[i].hour , expected[i].hour );
65+ ASSERT_EQ (buffer[i].minute , expected[i].minute );
66+ ASSERT_EQ (buffer[i].second , expected[i].second );
67+ ASSERT_EQ (buffer[i].fraction , expected[i].fraction );
5768 }
5869}
5970
6071TEST (TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) {
6172 std::vector<int64_t > values = {86400 , 172800 , 259200 , 1649793238 ,
62- 345600 , 432000 , 518400 };
73+ 345600 , 432000 , 518400 , -86399 , 0 };
74+ std::vector<TIMESTAMP_STRUCT> expected = {
75+ /* year(16), month(u16), day(u16), hour(u16), minute(u16), second(u16), fraction(u32) */
76+ {1970 , 1 , 2 , 0 , 0 , 0 , 0 },
77+ {1970 , 1 , 3 , 0 , 0 , 0 , 0 },
78+ {1970 , 1 , 4 , 0 , 0 , 0 , 0 },
79+ {2022 , 4 , 12 , 19 , 53 , 58 , 0 },
80+ {1970 , 1 , 5 , 0 , 0 , 0 , 0 },
81+ {1970 , 1 , 6 , 0 , 0 , 0 , 0 },
82+ {1970 , 1 , 7 , 0 , 0 , 0 , 0 },
83+ {1969 , 12 , 31 , 0 , 0 , 1 , 0 },
84+ {1970 , 1 , 1 , 0 , 0 , 0 , 0 },
85+ };
6386
6487 std::shared_ptr<Array> timestamp_array;
6588
@@ -81,23 +104,27 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) {
81104
82105 for (size_t i = 0 ; i < values.size (); ++i) {
83106 ASSERT_EQ (sizeof (TIMESTAMP_STRUCT), strlen_buffer[i]);
84- tm date{};
85-
86- auto converted_time = values[i];
87- GetTimeForSecondsSinceEpoch (date, converted_time);
88107
89- ASSERT_EQ (buffer[i].year , 1900 + (date. tm_year ) );
90- ASSERT_EQ (buffer[i].month , date. tm_mon + 1 );
91- ASSERT_EQ (buffer[i].day , date. tm_mday );
92- ASSERT_EQ (buffer[i].hour , date. tm_hour );
93- ASSERT_EQ (buffer[i].minute , date. tm_min );
94- ASSERT_EQ (buffer[i].second , date. tm_sec );
108+ ASSERT_EQ (buffer[i].year , expected[i]. year );
109+ ASSERT_EQ (buffer[i].month , expected[i]. month );
110+ ASSERT_EQ (buffer[i].day , expected[i]. day );
111+ ASSERT_EQ (buffer[i].hour , expected[i]. hour );
112+ ASSERT_EQ (buffer[i].minute , expected[i]. minute );
113+ ASSERT_EQ (buffer[i].second , expected[i]. second );
95114 ASSERT_EQ (buffer[i].fraction , 0 );
96115 }
97116}
98117
99118TEST (TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) {
100- std::vector<int64_t > values = {86400000000 , 1649793238000000 };
119+ std::vector<int64_t > values = {0 , 86400000000 , 1649793238000000 , -86399999999 , -86399000001 };
120+ std::vector<TIMESTAMP_STRUCT> expected = {
121+ /* year(16), month(u16), day(u16), hour(u16), minute(u16), second(u16), fraction(u32) */
122+ {1970 , 1 , 1 , 0 , 0 , 0 , 0 },
123+ {1970 , 1 , 2 , 0 , 0 , 0 , 0 },
124+ {2022 , 4 , 12 , 19 , 53 , 58 , 0 },
125+ {1969 , 12 , 31 , 0 , 0 , 0 , 1000 },
126+ {1969 , 12 , 31 , 0 , 0 , 0 , 999999000 },
127+ };
101128
102129 std::shared_ptr<Array> timestamp_array;
103130
@@ -120,24 +147,31 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) {
120147 for (size_t i = 0 ; i < values.size (); ++i) {
121148 ASSERT_EQ (sizeof (TIMESTAMP_STRUCT), strlen_buffer[i]);
122149
123- tm date{};
124-
125- auto converted_time = values[i] / MICRO_TO_SECONDS_DIVISOR;
126- GetTimeForSecondsSinceEpoch (date, converted_time);
127-
128- ASSERT_EQ (buffer[i].year , 1900 + (date.tm_year ));
129- ASSERT_EQ (buffer[i].month , date.tm_mon + 1 );
130- ASSERT_EQ (buffer[i].day , date.tm_mday );
131- ASSERT_EQ (buffer[i].hour , date.tm_hour );
132- ASSERT_EQ (buffer[i].minute , date.tm_min );
133- ASSERT_EQ (buffer[i].second , date.tm_sec );
134- constexpr uint32_t MICROS_PER_NANO = 1000 ;
135- ASSERT_EQ (buffer[i].fraction , (values[i] % MICRO_TO_SECONDS_DIVISOR) * MICROS_PER_NANO);
150+ ASSERT_EQ (buffer[i].year , expected[i].year );
151+ ASSERT_EQ (buffer[i].month , expected[i].month );
152+ ASSERT_EQ (buffer[i].day , expected[i].day );
153+ ASSERT_EQ (buffer[i].hour , expected[i].hour );
154+ ASSERT_EQ (buffer[i].minute , expected[i].minute );
155+ ASSERT_EQ (buffer[i].second , expected[i].second );
156+ ASSERT_EQ (buffer[i].fraction , expected[i].fraction );
136157 }
137158}
138159
139160TEST (TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) {
140- std::vector<int64_t > values = {86400000010000 , 1649793238000000000 };
161+ std::vector<int64_t > values = {86400000010000 , 1649793238000000000 , -86399999999999 , -86399000000001 ,
162+ 86400000000001 , 86400999999999 , 0 , -9223372036000000001 };
163+ std::vector<TIMESTAMP_STRUCT> expected = {
164+ /* year(16), month(u16), day(u16), hour(u16), minute(u16), second(u16), fraction(u32) */
165+ {1970 , 1 , 2 , 0 , 0 , 0 , 10000 },
166+ {2022 , 4 , 12 , 19 , 53 , 58 , 0 },
167+ {1969 , 12 , 31 , 0 , 0 , 0 , 1 },
168+ {1969 , 12 , 31 , 0 , 0 , 0 , 999999999 },
169+ {1970 , 1 , 2 , 0 , 0 , 0 , 1 },
170+ {1970 , 1 , 2 , 0 , 0 , 0 , 999999999 },
171+ {1970 , 1 , 1 , 0 , 0 , 0 , 0 },
172+ /* Test within range where floor (seconds) value is below INT64_MIN in nanoseconds */
173+ {1677 , 9 , 21 , 0 , 12 , 43 , 999999999 },
174+ };
141175
142176 std::shared_ptr<Array> timestamp_array;
143177
@@ -159,19 +193,16 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) {
159193
160194 for (size_t i = 0 ; i < values.size (); ++i) {
161195 ASSERT_EQ (sizeof (TIMESTAMP_STRUCT), strlen_buffer[i]);
162- tm date{};
163-
164- auto converted_time = values[i] / NANO_TO_SECONDS_DIVISOR;
165- GetTimeForSecondsSinceEpoch (date, converted_time);
166-
167- ASSERT_EQ (buffer[i].year , 1900 + (date.tm_year ));
168- ASSERT_EQ (buffer[i].month , date.tm_mon + 1 );
169- ASSERT_EQ (buffer[i].day , date.tm_mday );
170- ASSERT_EQ (buffer[i].hour , date.tm_hour );
171- ASSERT_EQ (buffer[i].minute , date.tm_min );
172- ASSERT_EQ (buffer[i].second , date.tm_sec );
173- ASSERT_EQ (buffer[i].fraction , (values[i] % NANO_TO_SECONDS_DIVISOR));
196+
197+ ASSERT_EQ (buffer[i].year , expected[i].year );
198+ ASSERT_EQ (buffer[i].month , expected[i].month );
199+ ASSERT_EQ (buffer[i].day , expected[i].day );
200+ ASSERT_EQ (buffer[i].hour , expected[i].hour );
201+ ASSERT_EQ (buffer[i].minute , expected[i].minute );
202+ ASSERT_EQ (buffer[i].second , expected[i].second );
203+ ASSERT_EQ (buffer[i].fraction , expected[i].fraction );
174204 }
175205}
206+
176207} // namespace flight_sql
177208} // namespace driver
0 commit comments