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,