anthonylouisbsb commented on a change in pull request #10711:
URL: https://github.com/apache/arrow/pull/10711#discussion_r671204429



##########
File path: cpp/src/gandiva/gdv_function_stubs.cc
##########
@@ -767,6 +769,113 @@ const char* gdv_fn_initcap_utf8(int64_t context, const 
char* data, int32_t data_
 }
 }
 
+GANDIVA_EXPORT
+const char* gdv_fn_from_unixtime_int64(int64_t context, gdv_timestamp in,
+                                       int32_t* out_len) {
+  const char* pattern = "yyyy-MM-dd hh:mm:ss";
+  const int length = strlen(pattern);
+  const char* ret =
+      gdv_fn_from_unixtime_int64_utf8(context, in, pattern, length, out_len);
+
+  return ret;
+}
+
+GANDIVA_EXPORT
+const char* gdv_fn_from_unixtime_int64_utf8(int64_t context, gdv_timestamp in,
+                                            const char* pattern, int32_t 
pattern_len,
+                                            int32_t* out_len) {
+  // Patter dictionary to translate a given pattern like yyyy-MM-dd to
+  // a pattern like %Y-%m-%d that the std::strftime can translate.
+  std::map<std::string, std::string> pattern_dict{
+      {"YYYY", "%Y"},  // converts 'YYYY' to full year, eg. 1970
+      {"YY", "%y"},    // converts 'YY' to final two-digits year, eg. 70
+      {"yyyy", "%Y"},  // converts 'YYYY' to full year, eg. 1970
+      {"yy", "%y"},    // converts 'YY' to final two-digits year, eg. 70
+      {"MM", "%m"},    // converts 'MM' to month digits, eg. 10
+      {"M", "%b"},     // converts 'M' to month abbreviation, eg. Oct
+      {"Mm", "%B"},    // converts 'Mm' to month abbreviation, eg. October
+      {"d", "%e"},  // converts 'd' to day of the month as a decimal number 
(range [1,31])
+      {"dd",
+       "%d"},  // converts 'dd' to day of the month as a decimal number (range 
[01,31])
+      {"h",
+       "%I"},  // converts 'h' hour as a decimal number, 12 hour clock (range 
[01-12])
+      {"hh",
+       "%H"},  // converts 'hh' to hour as a decimal number, 24 hour clock 
(range [00-23])
+      {"m", "%M"},   // converts 'm' to minute as a decimal number (range 
[00,59])
+      {"mm", "%M"},  // converts 'mm' minute as a decimal number (range 
[00,59])
+      {"s", "%S"},   // converts 's' to second as a decimal number (range 
[00,60])
+      {"ss", "%S"},  // converts 'ss' to second as a decimal number (range 
[00,60])
+  };
+
+  if (pattern_len <= 0) {
+    gdv_fn_context_set_error_msg(context,
+                                 "Invalid pattern, it must have at least 1 
char");
+    *out_len = 0;
+    return "";
+  }

Review comment:
       Is the pattern Literal? If it is Literal you can follow the example of 
the 
[TO_DATE](https://github.com/apache/arrow/blob/master/cpp/src/gandiva/to_date_holder.cc)
 function and move this process to a holder to avoid instantiate and convert 
this map for each value

##########
File path: cpp/src/gandiva/gdv_function_stubs.cc
##########
@@ -767,6 +769,113 @@ const char* gdv_fn_initcap_utf8(int64_t context, const 
char* data, int32_t data_
 }
 }
 
+GANDIVA_EXPORT
+const char* gdv_fn_from_unixtime_int64(int64_t context, gdv_timestamp in,
+                                       int32_t* out_len) {
+  const char* pattern = "yyyy-MM-dd hh:mm:ss";
+  const int length = strlen(pattern);

Review comment:
       I think you should insert the pattern length manually and change the 
name to `pattern_len`.
   
   I think magic numbers are bad when they are inserted without context, but in 
that case you know that number refers to the pattern above. It would avoid a 
call to the `strlen` function too. 

##########
File path: cpp/src/gandiva/tests/projector_test.cc
##########
@@ -1353,4 +1353,51 @@ TEST_F(TestProjector, TestBinRepresentation) {
   EXPECT_ARROW_ARRAY_EQUALS(exp, outputs.at(0));
 }
 
+TEST_F(TestProjector, TestFromUnixTime) {
+  // schema for input fields
+  auto field0 = field("f0", arrow::int64());
+  auto field1 = field("f1", arrow::utf8());
+  auto schema = arrow::schema({field0, field1});
+
+  // output fields
+  auto field_from_unixtime = field("from_unixtime", arrow::utf8());
+
+  // Build expression
+  auto from_unixtime_expr = TreeExprBuilder::MakeExpression(
+      "from_unixtime", {field0, field1}, field_from_unixtime);
+
+  std::shared_ptr<Projector> projector;
+  auto status =
+      Projector::Make(schema, {from_unixtime_expr}, TestConfiguration(), 
&projector);
+  EXPECT_TRUE(status.ok()) << status.message();
+
+  // Create a row-batch with some sample data
+  int64_t epoch_timestamp1 = 1107428640;  // 2005-02-03 11:04:00
+  int64_t epoch_timestamp2 = 1338975201;  // 2012-06-06 09:33:21
+  int64_t epoch_timestamp3 = 1543449599;  // 2018-11-28 23:59:59
+
+  std::string pattern1 = "yyyy-MM-dd hh:mm";
+  std::string pattern2 = "dd-M-yy";
+  std::string pattern3 = "hh:mm:ss dd-Mm-YYYY";
+
+  int num_records = 3;
+  auto array0 = MakeArrowArrayInt64(
+      {epoch_timestamp1, epoch_timestamp2, epoch_timestamp3}, {true, true, 
true});
+  auto array1 = MakeArrowArrayUtf8({pattern1, pattern2, pattern3}, {true, 
true, true});
+  // expected output
+  auto exp_from_unixtime = MakeArrowArrayUtf8(
+      {"2005-02-03 11:04", "06-Jun-12", "23:59:59 28-November-2018"}, {true, 
true, true});

Review comment:
       The date functions in the Gandiva usually consider the patterns as 
Literal(see the `TO_DATE` function). That one that you added has a different 
behavior?




-- 
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