Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions cpp/src/gandiva/precompiled/time.cc
Original file line number Diff line number Diff line change
Expand Up @@ -747,11 +747,12 @@ gdv_timestamp castTIMESTAMP_utf8(int64_t context, const char* input, gdv_int32 l

// adjust the milliseconds
if (sub_seconds_len > 0) {
if (sub_seconds_len > 3) {
const char* msg = "Invalid millis for timestamp value ";
set_error_for_date(length, input, msg, context);
return 0;
// Truncate to 3 digits (milliseconds precision) if more digits are provided
while (sub_seconds_len > 3) {
ts_fields[TimeFields::kSubSeconds] /= 10;
sub_seconds_len--;
}
// Pad with zeros if less than 3 digits
while (sub_seconds_len < 3) {
ts_fields[TimeFields::kSubSeconds] *= 10;
sub_seconds_len++;
Expand Down Expand Up @@ -867,12 +868,12 @@ gdv_time32 castTIME_utf8(int64_t context, const char* input, int32_t length) {

// adjust the milliseconds
if (sub_seconds_len > 0) {
if (sub_seconds_len > 3) {
const char* msg = "Invalid millis for time value ";
set_error_for_date(length, input, msg, context);
return 0;
// Truncate to 3 digits (milliseconds precision) if more digits are provided
while (sub_seconds_len > 3) {
time_fields[TimeFields::kSubSeconds - TimeFields::kHours] /= 10;
sub_seconds_len--;
}

// Pad with zeros if less than 3 digits
while (sub_seconds_len < 3) {
time_fields[TimeFields::kSubSeconds - TimeFields::kHours] *= 10;
sub_seconds_len++;
Expand Down
54 changes: 39 additions & 15 deletions cpp/src/gandiva/precompiled/time_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,26 @@ TEST(TestTime, TestCastTimestamp) {
"Not a valid time for timestamp value 2000-01-01 00:00:100");
context.Reset();

EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.0001", 24), 0);
EXPECT_EQ(context.get_error(),
"Invalid millis for timestamp value 2000-01-01 00:00:00.0001");
context.Reset();

EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.1000", 24), 0);
EXPECT_EQ(context.get_error(),
"Invalid millis for timestamp value 2000-01-01 00:00:00.1000");
context.Reset();
// Test truncation of subseconds to 3 digits (milliseconds)
// "2000-01-01 00:00:00.0001" should truncate to "2000-01-01 00:00:00.000"
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.0001", 24),
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.000", 23));

// "2000-01-01 00:00:00.1000" should truncate to "2000-01-01 00:00:00.100"
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.1000", 24),
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.100", 23));

// "2000-01-01 00:00:00.123456789" should truncate to "2000-01-01 00:00:00.123"
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.123456789", 29),
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.123", 23));

// "2000-01-01 00:00:00.1999" should truncate to "2000-01-01 00:00:00.199"
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.1999", 24),
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.199", 23));

// "2000-01-01 00:00:00.1994" should truncate to "2000-01-01 00:00:00.199"
EXPECT_EQ(castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.1994", 24),
castTIMESTAMP_utf8(context_ptr, "2000-01-01 00:00:00.199", 23));
}

TEST(TestTime, TestCastTimeUtf8) {
Expand Down Expand Up @@ -166,13 +177,26 @@ TEST(TestTime, TestCastTimeUtf8) {
EXPECT_EQ(context.get_error(), "Not a valid time value 00:00:100");
context.Reset();

EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.0001", 13), 0);
EXPECT_EQ(context.get_error(), "Invalid millis for time value 00:00:00.0001");
context.Reset();
// Test truncation of subseconds to 3 digits (milliseconds)
// "00:00:00.0001" should truncate to "00:00:00.000"
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.0001", 13),
castTIME_utf8(context_ptr, "00:00:00.000", 12));

EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.1000", 13), 0);
EXPECT_EQ(context.get_error(), "Invalid millis for time value 00:00:00.1000");
context.Reset();
// "00:00:00.1000" should truncate to "00:00:00.100"
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.1000", 13),
castTIME_utf8(context_ptr, "00:00:00.100", 12));

// "9:45:30.123456789" should truncate to "9:45:30.123"
EXPECT_EQ(castTIME_utf8(context_ptr, "9:45:30.123456789", 17),
castTIME_utf8(context_ptr, "9:45:30.123", 11));

// "00:00:00.1999" should truncate to "00:00:00.199"
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.1999", 13),
castTIME_utf8(context_ptr, "00:00:00.199", 12));

// "00:00:00.1994" should truncate to "00:00:00.199"
EXPECT_EQ(castTIME_utf8(context_ptr, "00:00:00.1994", 13),
castTIME_utf8(context_ptr, "00:00:00.199", 12));
}

#ifndef _WIN32
Expand Down