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]

Reply via email to