Skip to content
Merged
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
36 changes: 26 additions & 10 deletions cpp/src/gandiva/date_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,31 @@ class GANDIVA_EXPORT DateUtils {
namespace internal {

/// \brief Returns seconds since the UNIX epoch
static inline bool ParseTimestamp(const char* buf, const char* format, int64_t* out) {
static inline bool ParseTimestamp(const char* buf, const char* format,
bool ignoreTimeInDay, int64_t* out) {
#if defined(_MSC_VER)
static std::locale lc_all(setlocale(LC_ALL, NULLPTR));
std::istringstream stream(buf);
stream.imbue(lc_all);

date::sys_seconds secs;
stream >> date::parse(format, secs);
if (stream.fail()) {
return false;
// TODO: date::parse fails parsing when the hour value is 0.
// eg.1886-12-01 00:00:00
date::sys_seconds seconds;
if (ignoreTimeInDay) {
date::sys_days days;
stream >> date::parse(format, days);
if (stream.fail()) {
return false;
}
seconds = days;
} else {
stream >> date::parse(format, seconds);
if (stream.fail()) {
return false;
}
}

*out = secs.time_since_epoch().count();
auto seconds_in_epoch = seconds.time_since_epoch().count();
*out = seconds_in_epoch;
return true;
#else
struct tm result;
Expand All @@ -81,9 +93,13 @@ static inline bool ParseTimestamp(const char* buf, const char* format, int64_t*
return false;
}
// ignore the time part
auto days = date::sys_days(date::year(result.tm_year + 1900) / (result.tm_mon + 1) /
result.tm_mday);
*out = days.time_since_epoch().count();
date::sys_seconds secs = date::sys_days(date::year(result.tm_year + 1900) /
(result.tm_mon + 1) / result.tm_mday);
if (!ignoreTimeInDay) {
secs += (std::chrono::hours(result.tm_hour) + std::chrono::minutes(result.tm_min) +
std::chrono::seconds(result.tm_sec));
}
*out = secs.time_since_epoch().count();
return true;
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/gandiva/precompiled/testing.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace gandiva {

timestamp StringToTimestamp(const char* buf) {
int64_t out = 0;
DCHECK(internal::ParseTimestamp(buf, "%Y-%m-%d %H:%M:%S", &out));
DCHECK(internal::ParseTimestamp(buf, "%Y-%m-%d %H:%M:%S", false, &out));
return out * 1000;
}

Expand Down
10 changes: 7 additions & 3 deletions cpp/src/gandiva/tests/projector_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,14 @@ TEST_F(TestProjector, TestProjectCache) {
EXPECT_EQ(cached_projector, projector);

// if configuration is different, should return a new projector.

// build a new path by replacing the first '/' with '//'
std::string alt_path(GANDIVA_BYTE_COMPILE_FILE_PATH);
auto pos = alt_path.find('/', 0);
EXPECT_NE(pos, std::string::npos);
alt_path.replace(pos, 1, "//");
auto other_configuration =
ConfigurationBuilder()
.set_byte_code_file_path("/" + std::string(GANDIVA_BYTE_COMPILE_FILE_PATH))
.build();
ConfigurationBuilder().set_byte_code_file_path(alt_path).build();
std::shared_ptr<Projector> should_be_new_projector2;
status = Projector::Make(schema, {sum_expr, sub_expr}, other_configuration,
&should_be_new_projector2);
Expand Down
5 changes: 2 additions & 3 deletions cpp/src/gandiva/to_date_holder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,11 @@ int64_t ToDateHolder::operator()(ExecutionContext* context, const std::string& d
// 1. processes date that do not match the format.
// 2. does not process time in format +08:00 (or) id.
int64_t seconds_since_epoch = 0;
if (!internal::ParseTimestamp(data.c_str(), pattern_.c_str(), &seconds_since_epoch)) {
if (!internal::ParseTimestamp(data.c_str(), pattern_.c_str(), true,
&seconds_since_epoch)) {
return_error(context, data);
return 0;
}
// Drop any time component
seconds_since_epoch -= seconds_since_epoch % 86400;

*out_valid = true;
return seconds_since_epoch * 1000;
Expand Down
12 changes: 12 additions & 0 deletions cpp/src/gandiva/to_date_holder_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ TEST_F(TestToDateHolder, TestSimpleDateTime) {
to_date(&execution_context_, "1986-12-01 01:01:01 +0800", true, &out_valid);
EXPECT_EQ(millis_since_epoch, 533779200000);

#if 0
// TODO : this fails parsing with date::parse and strptime on linux
millis_since_epoch =
to_date(&execution_context_, "1886-12-01 00:00:00", true, &out_valid);
EXPECT_EQ(out_valid, true);
EXPECT_EQ(millis_since_epoch, -2621894400000);
#endif

millis_since_epoch =
to_date(&execution_context_, "1886-12-01 01:01:01", true, &out_valid);
EXPECT_EQ(millis_since_epoch, -2621894400000);

millis_since_epoch =
to_date(&execution_context_, "1986-12-11 01:30:00", true, &out_valid);
EXPECT_EQ(millis_since_epoch, 534643200000);
Expand Down