kou commented on code in PR #13428:
URL: https://github.com/apache/arrow/pull/13428#discussion_r920615543
##########
cpp/src/gandiva/gdv_function_stubs.cc:
##########
@@ -611,6 +611,65 @@ int32_t gdv_fn_cast_intervalyear_utf8_int32(int64_t
context_ptr, int64_t holder_
auto* holder = reinterpret_cast<gandiva::IntervalYearsHolder*>(holder_ptr);
return (*holder)(context, data, data_len, in1_validity, out_valid);
}
+
+GANDIVA_EXPORT
+gdv_timestamp to_utc_timezone_timestamp(int64_t context, gdv_timestamp
time_miliseconds,
+ const char* timezone, gdv_int32
length) {
+ using std::chrono::milliseconds;
+ using arrow_vendored::date::sys_time;
+ using arrow_vendored::date::time_zone;
+ using arrow_vendored::date::zoned_time;
+ using arrow_vendored::date::locate_zone;
+
+ sys_time <milliseconds> tp {milliseconds{time_miliseconds}};
+ try {
+ const auto local_tz = locate_zone(std::string(timezone, length));
+ gdv_timestamp offset = local_tz->get_info(tp).offset.count()*1000;
+ return time_miliseconds - static_cast<gdv_timestamp>(offset);
+ } catch(...) {
+ int32_t msg_len = static_cast<int32_t>(strlen(timezone) + 50);
+ char* err_msg =
+ reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, msg_len));
+ if (err_msg == nullptr) {
+ gdv_fn_context_set_error_msg(context, "Could not allocate memory");
+ return 0;
+ }
+ std::snprintf(err_msg, msg_len, "'%s' is an invalid time zone name.",
timezone);
+ gdv_fn_context_set_error_msg(context, err_msg);
+ return 0;
+ }
+}
+
+GANDIVA_EXPORT
+gdv_timestamp from_utc_timezone_timestamp(gdv_int64 context,
+ gdv_timestamp time_miliseconds,
+ const char* timezone, gdv_int32
length) {
+ using std::chrono::milliseconds;
+ using arrow_vendored::date::sys_time;
+ using arrow_vendored::date::time_zone;
+ using arrow_vendored::date::zoned_time;
Review Comment:
```suggestion
```
##########
cpp/src/gandiva/gdv_function_stubs.cc:
##########
@@ -611,6 +611,65 @@ int32_t gdv_fn_cast_intervalyear_utf8_int32(int64_t
context_ptr, int64_t holder_
auto* holder = reinterpret_cast<gandiva::IntervalYearsHolder*>(holder_ptr);
return (*holder)(context, data, data_len, in1_validity, out_valid);
}
+
+GANDIVA_EXPORT
+gdv_timestamp to_utc_timezone_timestamp(int64_t context, gdv_timestamp
time_miliseconds,
+ const char* timezone, gdv_int32
length) {
+ using std::chrono::milliseconds;
+ using arrow_vendored::date::sys_time;
+ using arrow_vendored::date::time_zone;
+ using arrow_vendored::date::zoned_time;
+ using arrow_vendored::date::locate_zone;
+
+ sys_time <milliseconds> tp {milliseconds{time_miliseconds}};
+ try {
+ const auto local_tz = locate_zone(std::string(timezone, length));
+ gdv_timestamp offset = local_tz->get_info(tp).offset.count()*1000;
+ return time_miliseconds - static_cast<gdv_timestamp>(offset);
+ } catch(...) {
+ int32_t msg_len = static_cast<int32_t>(strlen(timezone) + 50);
Review Comment:
```suggestion
auto msg_len = static_cast<int32_t>(strlen(timezone) + 50);
```
##########
cpp/src/gandiva/gdv_function_stubs_test.cc:
##########
@@ -993,4 +993,61 @@ TEST(TestGdvFnStubs, TestTranslate) {
EXPECT_EQ(expected, std::string(result, out_len));
}
+TEST(TestGdvFnStubs, TestToUtcTimezone) {
+ gandiva::ExecutionContext context;
+ auto context_ptr = reinterpret_cast<int64_t>(&context);
+ gdv_int32 len_ist = static_cast<gdv_int32>(strlen("Asia/Kolkata"));
+ gdv_int32 len_pst = static_cast<gdv_int32>(strlen("America/Los_Angeles"));
+
+ //2012-02-28 15:30:00
+ gdv_timestamp ts = 1330443000000;
+ gdv_timestamp ts2 =
+ to_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(1330423200000, ts2);
+
+ //1970-01-01 5:00:00
+ ts = 18000000;
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(ts2, -1800000);
+
+ //daylight savings check
+ //2018-03-11 01:00:00
+ ts = 1520730000000;
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "America/Los_Angeles",
len_pst);
+ EXPECT_EQ(ts2, 1520758800000);
+
+ //2018-03-12 01:00:00
+ ts = 1331712000000;
Review Comment:
Is this correct?
It seems that 1331712000000 is "2012-03-14 08:00:00 UTC".
##########
cpp/src/gandiva/gdv_function_stubs_test.cc:
##########
@@ -993,4 +993,61 @@ TEST(TestGdvFnStubs, TestTranslate) {
EXPECT_EQ(expected, std::string(result, out_len));
}
+TEST(TestGdvFnStubs, TestToUtcTimezone) {
+ gandiva::ExecutionContext context;
+ auto context_ptr = reinterpret_cast<int64_t>(&context);
+ gdv_int32 len_ist = static_cast<gdv_int32>(strlen("Asia/Kolkata"));
+ gdv_int32 len_pst = static_cast<gdv_int32>(strlen("America/Los_Angeles"));
+
+ //2012-02-28 15:30:00
+ gdv_timestamp ts = 1330443000000;
+ gdv_timestamp ts2 =
+ to_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(1330423200000, ts2);
+
+ //1970-01-01 5:00:00
+ ts = 18000000;
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(ts2, -1800000);
+
+ //daylight savings check
+ //2018-03-11 01:00:00
+ ts = 1520730000000;
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "America/Los_Angeles",
len_pst);
+ EXPECT_EQ(ts2, 1520758800000);
+
+ //2018-03-12 01:00:00
+ ts = 1331712000000;
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "America/Los_Angeles",
len_pst);
+ EXPECT_EQ(ts2, 1331737200000);
+
+ //Failure case
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "America/LA", 10);
+ EXPECT_THAT(context.get_error(), "'America/LA' is an invalid time zone
name.");
+}
+
+TEST(TestGdvFnStubs, TestFromUtcTimezone) {
+ ExecutionContext context;
+ auto context_ptr = reinterpret_cast<int64_t>(&context);
+ gdv_int32 len_ist = static_cast<gdv_int32>(strlen("Asia/Kolkata"));
+ gdv_int32 len_pst = static_cast<gdv_int32>(strlen("America/Los_Angeles"));
Review Comment:
```suggestion
auto len_ist = static_cast<gdv_int32>(strlen("Asia/Kolkata"));
auto len_pst = static_cast<gdv_int32>(strlen("America/Los_Angeles"));
```
##########
cpp/src/gandiva/gdv_function_stubs.cc:
##########
@@ -611,6 +611,65 @@ int32_t gdv_fn_cast_intervalyear_utf8_int32(int64_t
context_ptr, int64_t holder_
auto* holder = reinterpret_cast<gandiva::IntervalYearsHolder*>(holder_ptr);
return (*holder)(context, data, data_len, in1_validity, out_valid);
}
+
+GANDIVA_EXPORT
+gdv_timestamp to_utc_timezone_timestamp(int64_t context, gdv_timestamp
time_miliseconds,
+ const char* timezone, gdv_int32
length) {
+ using std::chrono::milliseconds;
+ using arrow_vendored::date::sys_time;
+ using arrow_vendored::date::time_zone;
+ using arrow_vendored::date::zoned_time;
Review Comment:
```suggestion
```
##########
cpp/src/gandiva/gdv_function_stubs_test.cc:
##########
@@ -993,4 +993,61 @@ TEST(TestGdvFnStubs, TestTranslate) {
EXPECT_EQ(expected, std::string(result, out_len));
}
+TEST(TestGdvFnStubs, TestToUtcTimezone) {
+ gandiva::ExecutionContext context;
+ auto context_ptr = reinterpret_cast<int64_t>(&context);
+ gdv_int32 len_ist = static_cast<gdv_int32>(strlen("Asia/Kolkata"));
+ gdv_int32 len_pst = static_cast<gdv_int32>(strlen("America/Los_Angeles"));
Review Comment:
```suggestion
auto len_ist = static_cast<gdv_int32>(strlen("Asia/Kolkata"));
auto len_pst = static_cast<gdv_int32>(strlen("America/Los_Angeles"));
```
##########
cpp/src/gandiva/gdv_function_stubs.cc:
##########
@@ -611,6 +611,65 @@ int32_t gdv_fn_cast_intervalyear_utf8_int32(int64_t
context_ptr, int64_t holder_
auto* holder = reinterpret_cast<gandiva::IntervalYearsHolder*>(holder_ptr);
return (*holder)(context, data, data_len, in1_validity, out_valid);
}
+
+GANDIVA_EXPORT
+gdv_timestamp to_utc_timezone_timestamp(int64_t context, gdv_timestamp
time_miliseconds,
+ const char* timezone, gdv_int32
length) {
+ using std::chrono::milliseconds;
+ using arrow_vendored::date::sys_time;
+ using arrow_vendored::date::time_zone;
+ using arrow_vendored::date::zoned_time;
+ using arrow_vendored::date::locate_zone;
+
+ sys_time <milliseconds> tp {milliseconds{time_miliseconds}};
+ try {
+ const auto local_tz = locate_zone(std::string(timezone, length));
+ gdv_timestamp offset = local_tz->get_info(tp).offset.count()*1000;
+ return time_miliseconds - static_cast<gdv_timestamp>(offset);
+ } catch(...) {
+ int32_t msg_len = static_cast<int32_t>(strlen(timezone) + 50);
+ char* err_msg =
Review Comment:
```suggestion
auto err_msg =
```
##########
cpp/src/gandiva/gdv_function_stubs.cc:
##########
@@ -611,6 +611,65 @@ int32_t gdv_fn_cast_intervalyear_utf8_int32(int64_t
context_ptr, int64_t holder_
auto* holder = reinterpret_cast<gandiva::IntervalYearsHolder*>(holder_ptr);
return (*holder)(context, data, data_len, in1_validity, out_valid);
}
+
+GANDIVA_EXPORT
+gdv_timestamp to_utc_timezone_timestamp(int64_t context, gdv_timestamp
time_miliseconds,
+ const char* timezone, gdv_int32
length) {
+ using std::chrono::milliseconds;
+ using arrow_vendored::date::sys_time;
+ using arrow_vendored::date::time_zone;
+ using arrow_vendored::date::zoned_time;
+ using arrow_vendored::date::locate_zone;
+
+ sys_time <milliseconds> tp {milliseconds{time_miliseconds}};
+ try {
+ const auto local_tz = locate_zone(std::string(timezone, length));
+ gdv_timestamp offset = local_tz->get_info(tp).offset.count()*1000;
+ return time_miliseconds - static_cast<gdv_timestamp>(offset);
+ } catch(...) {
+ int32_t msg_len = static_cast<int32_t>(strlen(timezone) + 50);
+ char* err_msg =
+ reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, msg_len));
+ if (err_msg == nullptr) {
+ gdv_fn_context_set_error_msg(context, "Could not allocate memory");
+ return 0;
+ }
+ std::snprintf(err_msg, msg_len, "'%s' is an invalid time zone name.",
timezone);
+ gdv_fn_context_set_error_msg(context, err_msg);
+ return 0;
+ }
+}
+
+GANDIVA_EXPORT
+gdv_timestamp from_utc_timezone_timestamp(gdv_int64 context,
+ gdv_timestamp time_miliseconds,
+ const char* timezone, gdv_int32
length) {
+ using std::chrono::milliseconds;
+ using arrow_vendored::date::sys_time;
+ using arrow_vendored::date::time_zone;
+ using arrow_vendored::date::zoned_time;
+ using arrow_vendored::date::make_zoned;
+
+ sys_time <milliseconds> tp {milliseconds{time_miliseconds}};
+ const auto utc_tz = make_zoned(std::string("Etc/UTC"), tp);
+ try {
+ const auto local_tz = make_zoned(std::string(timezone, length), utc_tz);
+ gdv_timestamp offset =
local_tz.get_time_zone()->get_info(tp).offset.count()*1000;
+ return time_miliseconds + static_cast<gdv_timestamp>(offset);
+ } catch(...) {
+ int32_t msg_len = static_cast<int32_t>(strlen(timezone) + 50);
Review Comment:
```suggestion
auto msg_len = static_cast<int32_t>(strlen(timezone) + 50);
```
##########
cpp/src/gandiva/gdv_function_stubs.cc:
##########
@@ -611,6 +611,65 @@ int32_t gdv_fn_cast_intervalyear_utf8_int32(int64_t
context_ptr, int64_t holder_
auto* holder = reinterpret_cast<gandiva::IntervalYearsHolder*>(holder_ptr);
return (*holder)(context, data, data_len, in1_validity, out_valid);
}
+
+GANDIVA_EXPORT
+gdv_timestamp to_utc_timezone_timestamp(int64_t context, gdv_timestamp
time_miliseconds,
+ const char* timezone, gdv_int32
length) {
+ using std::chrono::milliseconds;
+ using arrow_vendored::date::sys_time;
+ using arrow_vendored::date::time_zone;
+ using arrow_vendored::date::zoned_time;
+ using arrow_vendored::date::locate_zone;
+
+ sys_time <milliseconds> tp {milliseconds{time_miliseconds}};
+ try {
+ const auto local_tz = locate_zone(std::string(timezone, length));
+ gdv_timestamp offset = local_tz->get_info(tp).offset.count()*1000;
+ return time_miliseconds - static_cast<gdv_timestamp>(offset);
+ } catch(...) {
+ int32_t msg_len = static_cast<int32_t>(strlen(timezone) + 50);
+ char* err_msg =
+ reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, msg_len));
+ if (err_msg == nullptr) {
+ gdv_fn_context_set_error_msg(context, "Could not allocate memory");
+ return 0;
+ }
+ std::snprintf(err_msg, msg_len, "'%s' is an invalid time zone name.",
timezone);
+ gdv_fn_context_set_error_msg(context, err_msg);
+ return 0;
+ }
+}
+
+GANDIVA_EXPORT
+gdv_timestamp from_utc_timezone_timestamp(gdv_int64 context,
+ gdv_timestamp time_miliseconds,
+ const char* timezone, gdv_int32
length) {
+ using std::chrono::milliseconds;
+ using arrow_vendored::date::sys_time;
+ using arrow_vendored::date::time_zone;
+ using arrow_vendored::date::zoned_time;
+ using arrow_vendored::date::make_zoned;
+
+ sys_time <milliseconds> tp {milliseconds{time_miliseconds}};
+ const auto utc_tz = make_zoned(std::string("Etc/UTC"), tp);
+ try {
+ const auto local_tz = make_zoned(std::string(timezone, length), utc_tz);
+ gdv_timestamp offset =
local_tz.get_time_zone()->get_info(tp).offset.count()*1000;
+ return time_miliseconds + static_cast<gdv_timestamp>(offset);
+ } catch(...) {
+ int32_t msg_len = static_cast<int32_t>(strlen(timezone) + 50);
+ char* err_msg =
Review Comment:
```suggestion
auto err_msg =
```
##########
cpp/src/gandiva/gdv_function_stubs_test.cc:
##########
@@ -993,4 +993,61 @@ TEST(TestGdvFnStubs, TestTranslate) {
EXPECT_EQ(expected, std::string(result, out_len));
}
+TEST(TestGdvFnStubs, TestToUtcTimezone) {
+ gandiva::ExecutionContext context;
+ auto context_ptr = reinterpret_cast<int64_t>(&context);
+ gdv_int32 len_ist = static_cast<gdv_int32>(strlen("Asia/Kolkata"));
+ gdv_int32 len_pst = static_cast<gdv_int32>(strlen("America/Los_Angeles"));
+
+ //2012-02-28 15:30:00
+ gdv_timestamp ts = 1330443000000;
+ gdv_timestamp ts2 =
+ to_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(1330423200000, ts2);
+
+ //1970-01-01 5:00:00
+ ts = 18000000;
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(ts2, -1800000);
+
+ //daylight savings check
+ //2018-03-11 01:00:00
+ ts = 1520730000000;
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "America/Los_Angeles",
len_pst);
+ EXPECT_EQ(ts2, 1520758800000);
+
+ //2018-03-12 01:00:00
+ ts = 1331712000000;
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "America/Los_Angeles",
len_pst);
+ EXPECT_EQ(ts2, 1331737200000);
+
+ //Failure case
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "America/LA", 10);
+ EXPECT_THAT(context.get_error(), "'America/LA' is an invalid time zone
name.");
+}
+
+TEST(TestGdvFnStubs, TestFromUtcTimezone) {
+ ExecutionContext context;
+ auto context_ptr = reinterpret_cast<int64_t>(&context);
+ gdv_int32 len_ist = static_cast<gdv_int32>(strlen("Asia/Kolkata"));
+ gdv_int32 len_pst = static_cast<gdv_int32>(strlen("America/Los_Angeles"));
+
+ gdv_timestamp ts = 36000000;
+ gdv_timestamp ts2 =
+ from_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(ts2, 55800000);
+
+ ts = -1800000;
+ ts2 = from_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(ts2, 18000000);
+
+ ts = 1520758800000;
+ ts2 = from_utc_timezone_timestamp(context_ptr, ts, "America/Los_Angeles",
len_pst);
+ EXPECT_EQ(ts2, 1520730000000);
+
+ ts = 1331737200000;
+ ts2 = from_utc_timezone_timestamp(context_ptr, ts, "America/Los_Angeles",
len_pst);
+ EXPECT_EQ(ts2, 1331712000000);
+}
Review Comment:
How about adding error case for `from_utc_timezone_timestamp()` too?
##########
cpp/src/gandiva/gdv_function_stubs_test.cc:
##########
@@ -993,4 +993,61 @@ TEST(TestGdvFnStubs, TestTranslate) {
EXPECT_EQ(expected, std::string(result, out_len));
}
+TEST(TestGdvFnStubs, TestToUtcTimezone) {
+ gandiva::ExecutionContext context;
+ auto context_ptr = reinterpret_cast<int64_t>(&context);
+ gdv_int32 len_ist = static_cast<gdv_int32>(strlen("Asia/Kolkata"));
+ gdv_int32 len_pst = static_cast<gdv_int32>(strlen("America/Los_Angeles"));
+
+ //2012-02-28 15:30:00
+ gdv_timestamp ts = 1330443000000;
+ gdv_timestamp ts2 =
+ to_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(1330423200000, ts2);
+
+ //1970-01-01 5:00:00
+ ts = 18000000;
+ ts2 = to_utc_timezone_timestamp(context_ptr, ts, "Asia/Kolkata", len_ist);
+ EXPECT_EQ(ts2, -1800000);
+
+ //daylight savings check
+ //2018-03-11 01:00:00
+ ts = 1520730000000;
Review Comment:
```suggestion
ts = 1520730000000;
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]