This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 3840208e56 ARROW-16142: [C++] Temporal floor/ceil/round returns 
incorrect results for date32 and time32 inputs (#13539)
3840208e56 is described below

commit 3840208e565d190832b37a2dd050ef8ef08abb86
Author: Rok Mihevc <[email protected]>
AuthorDate: Mon Jul 11 14:59:55 2022 +0200

    ARROW-16142: [C++] Temporal floor/ceil/round returns incorrect results for 
date32 and time32 inputs (#13539)
    
    This is to resolve 
[ARROW-16142](https://issues.apache.org/jira/browse/ARROW-16142).
    
    Authored-by: Rok <[email protected]>
    Signed-off-by: David Li <[email protected]>
---
 .../arrow/compute/kernels/scalar_temporal_test.cc  | 29 ++++++++++++++++++++++
 .../arrow/compute/kernels/scalar_temporal_unary.cc |  9 +++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc 
b/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
index ab1f349c16..597157eb6e 100644
--- a/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
@@ -3572,5 +3572,34 @@ TEST_F(ScalarTemporalTest, 
TestCeilFloorRoundTemporalKolkata) {
   CheckScalarUnary("round_temporal", unit, times, unit, round_2_hours, 
&round_to_2_hours);
 }
 
+TEST_F(ScalarTemporalTest, TestCeilFloorRoundTemporalDate) {
+  RoundTemporalOptions round_to_2_hours = RoundTemporalOptions(2, 
CalendarUnit::HOUR);
+  const char* date32s = R"([0, 11016, -25932, null])";
+  const char* date64s = R"([0, 951782400000, -2240524800000, null])";
+  auto dates32 = ArrayFromJSON(date32(), date32s);
+  auto dates64 = ArrayFromJSON(date64(), date64s);
+
+  CheckScalarUnary("ceil_temporal", dates32, dates32, &round_to_2_hours);
+  CheckScalarUnary("floor_temporal", dates32, dates32, &round_to_2_hours);
+  CheckScalarUnary("round_temporal", dates32, dates32, &round_to_2_hours);
+  CheckScalarUnary("ceil_temporal", dates64, dates64, &round_to_2_hours);
+  CheckScalarUnary("floor_temporal", dates64, dates64, &round_to_2_hours);
+  CheckScalarUnary("round_temporal", dates64, dates64, &round_to_2_hours);
+
+  const char* times_s = R"([0, 7200, null])";
+  const char* times_ms = R"([0, 7200000, null])";
+  const char* times_us = R"([0, 7200000000, null])";
+  const char* times_ns = R"([0, 7200000000000, null])";
+  auto arr_s = ArrayFromJSON(time32(TimeUnit::SECOND), times_s);
+  auto arr_ms = ArrayFromJSON(time32(TimeUnit::MILLI), times_ms);
+  auto arr_us = ArrayFromJSON(time64(TimeUnit::MICRO), times_us);
+  auto arr_ns = ArrayFromJSON(time64(TimeUnit::NANO), times_ns);
+
+  CheckScalarUnary("ceil_temporal", arr_s, arr_s, &round_to_2_hours);
+  CheckScalarUnary("ceil_temporal", arr_ms, arr_ms, &round_to_2_hours);
+  CheckScalarUnary("ceil_temporal", arr_us, arr_us, &round_to_2_hours);
+  CheckScalarUnary("ceil_temporal", arr_ns, arr_ns, &round_to_2_hours);
+}
+
 }  // namespace compute
 }  // namespace arrow
diff --git a/cpp/src/arrow/compute/kernels/scalar_temporal_unary.cc 
b/cpp/src/arrow/compute/kernels/scalar_temporal_unary.cc
index 212f9bdad7..d7c045d84b 100644
--- a/cpp/src/arrow/compute/kernels/scalar_temporal_unary.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_temporal_unary.cc
@@ -165,11 +165,13 @@ struct TemporalComponentExtractWeek
   }
 };
 
+// Since OutType should always equal InType we set OutType to InType in the
+// TemporalComponentExtractBase template parameters.
 template <template <typename...> class Op, typename Duration, typename InType,
           typename OutType>
 struct TemporalComponentExtractRound
-    : public TemporalComponentExtractBase<Op, Duration, InType, OutType> {
-  using Base = TemporalComponentExtractBase<Op, Duration, InType, OutType>;
+    : public TemporalComponentExtractBase<Op, Duration, InType, InType> {
+  using Base = TemporalComponentExtractBase<Op, Duration, InType, InType>;
 
   static Status Exec(KernelContext* ctx, const ExecSpan& batch, ExecResult* 
out) {
     const RoundTemporalOptions& options = RoundTemporalState::Get(ctx);
@@ -1968,6 +1970,9 @@ void RegisterScalarTemporalUnary(FunctionRegistry* 
registry) {
   DCHECK_OK(registry->AddFunction(std::move(is_dst)));
 
   // Temporal rounding functions
+  // Note: UnaryTemporalFactory will not correctly resolve 
OutputType(FirstType) to
+  // output type. See TemporalComponentExtractRound for more.
+
   static const auto default_round_temporal_options = 
RoundTemporalOptions::Defaults();
   auto floor_temporal = UnaryTemporalFactory<FloorTemporal, 
TemporalComponentExtractRound,
                                              TimestampType>::Make<WithDates, 
WithTimes,

Reply via email to