Skip to content

Commit b151ba1

Browse files
DX-110851 Truncate subseconds beyond milliseconds in castTIMESTAMP_utf8 and castTIME_utf8
1 parent ab9245e commit b151ba1

2 files changed

Lines changed: 49 additions & 24 deletions

File tree

cpp/src/gandiva/precompiled/time.cc

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -745,11 +745,12 @@ gdv_timestamp castTIMESTAMP_utf8(int64_t context, const char* input, gdv_int32 l
745745

746746
// adjust the milliseconds
747747
if (sub_seconds_len > 0) {
748-
if (sub_seconds_len > 3) {
749-
const char* msg = "Invalid millis for timestamp value ";
750-
set_error_for_date(length, input, msg, context);
751-
return 0;
748+
// Truncate to 3 digits (milliseconds precision) if more digits are provided
749+
while (sub_seconds_len > 3) {
750+
ts_fields[TimeFields::kSubSeconds] /= 10;
751+
sub_seconds_len--;
752752
}
753+
// Pad with zeros if less than 3 digits
753754
while (sub_seconds_len < 3) {
754755
ts_fields[TimeFields::kSubSeconds] *= 10;
755756
sub_seconds_len++;
@@ -865,12 +866,12 @@ gdv_time32 castTIME_utf8(int64_t context, const char* input, int32_t length) {
865866

866867
// adjust the milliseconds
867868
if (sub_seconds_len > 0) {
868-
if (sub_seconds_len > 3) {
869-
const char* msg = "Invalid millis for time value ";
870-
set_error_for_date(length, input, msg, context);
871-
return 0;
869+
// Truncate to 3 digits (milliseconds precision) if more digits are provided
870+
while (sub_seconds_len > 3) {
871+
time_fields[TimeFields::kSubSeconds - TimeFields::kHours] /= 10;
872+
sub_seconds_len--;
872873
}
873-
874+
// Pad with zeros if less than 3 digits
874875
while (sub_seconds_len < 3) {
875876
time_fields[TimeFields::kSubSeconds - TimeFields::kHours] *= 10;
876877
sub_seconds_len++;

cpp/src/gandiva/precompiled/time_test.cc

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,26 @@ TEST(TestTime, TestCastTimestamp) {
121121
"Not a valid time for timestamp value 2000-01-01 00:00:100");
122122
context.Reset();
123123

124-
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.0001", 24), 0);
125-
EXPECT_EQ(context.get_error(),
126-
"Invalid millis for timestamp value 2000-01-01 00:00:00.0001");
127-
context.Reset();
128-
129-
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.1000", 24), 0);
130-
EXPECT_EQ(context.get_error(),
131-
"Invalid millis for timestamp value 2000-01-01 00:00:00.1000");
132-
context.Reset();
124+
// Test truncation of subseconds to 3 digits (milliseconds)
125+
// "2000-01-01 00:00:00.0001" should truncate to "2000-01-01 00:00:00.000"
126+
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.0001", 24),
127+
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.000", 23));
128+
129+
// "2000-01-01 00:00:00.1000" should truncate to "2000-01-01 00:00:00.100"
130+
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.1000", 24),
131+
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.100", 23));
132+
133+
// "2000-01-01 00:00:00.123456789" should truncate to "2000-01-01 00:00:00.123"
134+
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.123456789", 29),
135+
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.123", 23));
136+
137+
// "2000-01-01 00:00:00.1999" should truncate to "2000-01-01 00:00:00.199"
138+
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.1999", 24),
139+
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.199", 23));
140+
141+
// "2000-01-01 00:00:00.1994" should truncate to "2000-01-01 00:00:00.199"
142+
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.1994", 24),
143+
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.199", 23));
133144
}
134145

135146
TEST(TestTime, TestCastTimeUtf8) {
@@ -165,13 +176,26 @@ TEST(TestTime, TestCastTimeUtf8) {
165176
EXPECT_EQ(context.get_error(), "Not a valid time value 00:00:100");
166177
context.Reset();
167178

168-
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.0001", 13), 0);
169-
EXPECT_EQ(context.get_error(), "Invalid millis for time value 00:00:00.0001");
170-
context.Reset();
179+
// Test truncation of subseconds to 3 digits (milliseconds)
180+
// "00:00:00.0001" should truncate to "00:00:00.000"
181+
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.0001", 13),
182+
castTIME_utf8(context_ptr, "00:00:00.000", 12));
171183

172-
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.1000", 13), 0);
173-
EXPECT_EQ(context.get_error(), "Invalid millis for time value 00:00:00.1000");
174-
context.Reset();
184+
// "00:00:00.1000" should truncate to "00:00:00.100"
185+
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.1000", 13),
186+
castTIME_utf8(context_ptr, "00:00:00.100", 12));
187+
188+
// "9:45:30.123456789" should truncate to "9:45:30.123"
189+
EXPECT_EQ(castTIME_utf8(context_ptr, "9:45:30.123456789", 17),
190+
castTIME_utf8(context_ptr, "9:45:30.123", 11));
191+
192+
// "00:00:00.1999" should truncate to "00:00:00.199"
193+
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.1999", 13),
194+
castTIME_utf8(context_ptr, "00:00:00.199", 12));
195+
196+
// "00:00:00.1994" should truncate to "00:00:00.199"
197+
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.1994", 13),
198+
castTIME_utf8(context_ptr, "00:00:00.199", 12));
175199
}
176200

177201
#ifndef _WIN32

0 commit comments

Comments
 (0)