You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by li...@apache.org on 2022/04/05 14:37:49 UTC
[arrow] branch master updated: ARROW-16060: [C++] subtract_checked support for timestamp("s") and date32
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 8eaa995f0e ARROW-16060: [C++] subtract_checked support for timestamp("s") and date32
8eaa995f0e is described below
commit 8eaa995f0e8de2ebc0f2b09648ef033f01f9f959
Author: Rok <ro...@mihevc.org>
AuthorDate: Tue Apr 5 10:37:27 2022 -0400
ARROW-16060: [C++] subtract_checked support for timestamp("s") and date32
This is to resolve [ARROW-16060](https://issues.apache.org/jira/browse/ARROW-16060).
Closes #12774 from rok/ARROW-16060
Authored-by: Rok <ro...@mihevc.org>
Signed-off-by: David Li <li...@gmail.com>
---
cpp/src/arrow/compute/kernels/codegen_internal.cc | 24 ++++--
cpp/src/arrow/compute/kernels/codegen_internal.h | 3 +-
.../arrow/compute/kernels/codegen_internal_test.cc | 98 ++++++++++++++--------
cpp/src/arrow/compute/kernels/scalar_arithmetic.cc | 10 +--
.../arrow/compute/kernels/scalar_temporal_test.cc | 78 +++++++++++++++++
5 files changed, 165 insertions(+), 48 deletions(-)
diff --git a/cpp/src/arrow/compute/kernels/codegen_internal.cc b/cpp/src/arrow/compute/kernels/codegen_internal.cc
index 26c12ebf59..b31ef408b1 100644
--- a/cpp/src/arrow/compute/kernels/codegen_internal.cc
+++ b/cpp/src/arrow/compute/kernels/codegen_internal.cc
@@ -214,45 +214,53 @@ std::shared_ptr<DataType> CommonNumeric(const ValueDescr* begin, size_t count) {
return int8();
}
-TimeUnit::type CommonTemporalResolution(const ValueDescr* begin, size_t count) {
- TimeUnit::type finest_unit = TimeUnit::SECOND;
+bool CommonTemporalResolution(const ValueDescr* begin, size_t count,
+ TimeUnit::type* finest_unit) {
+ bool is_time_unit = false;
+ *finest_unit = TimeUnit::SECOND;
const ValueDescr* end = begin + count;
for (auto it = begin; it != end; it++) {
auto id = it->type->id();
switch (id) {
case Type::DATE32: {
// Date32's unit is days, but the coarsest we have is seconds
+ is_time_unit = true;
continue;
}
case Type::DATE64: {
- finest_unit = std::max(finest_unit, TimeUnit::MILLI);
+ *finest_unit = std::max(*finest_unit, TimeUnit::MILLI);
+ is_time_unit = true;
continue;
}
case Type::TIMESTAMP: {
const auto& ty = checked_cast<const TimestampType&>(*it->type);
- finest_unit = std::max(finest_unit, ty.unit());
+ *finest_unit = std::max(*finest_unit, ty.unit());
+ is_time_unit = true;
continue;
}
case Type::DURATION: {
const auto& ty = checked_cast<const DurationType&>(*it->type);
- finest_unit = std::max(finest_unit, ty.unit());
+ *finest_unit = std::max(*finest_unit, ty.unit());
+ is_time_unit = true;
continue;
}
case Type::TIME32: {
const auto& ty = checked_cast<const Time32Type&>(*it->type);
- finest_unit = std::max(finest_unit, ty.unit());
+ *finest_unit = std::max(*finest_unit, ty.unit());
+ is_time_unit = true;
continue;
}
case Type::TIME64: {
const auto& ty = checked_cast<const Time64Type&>(*it->type);
- finest_unit = std::max(finest_unit, ty.unit());
+ *finest_unit = std::max(*finest_unit, ty.unit());
+ is_time_unit = true;
continue;
}
default:
continue;
}
}
- return finest_unit;
+ return is_time_unit;
}
std::shared_ptr<DataType> CommonTemporal(const ValueDescr* begin, size_t count) {
diff --git a/cpp/src/arrow/compute/kernels/codegen_internal.h b/cpp/src/arrow/compute/kernels/codegen_internal.h
index ff7b9161fe..fa50427bc3 100644
--- a/cpp/src/arrow/compute/kernels/codegen_internal.h
+++ b/cpp/src/arrow/compute/kernels/codegen_internal.h
@@ -1394,7 +1394,8 @@ ARROW_EXPORT
std::shared_ptr<DataType> CommonTemporal(const ValueDescr* begin, size_t count);
ARROW_EXPORT
-TimeUnit::type CommonTemporalResolution(const ValueDescr* begin, size_t count);
+bool CommonTemporalResolution(const ValueDescr* begin, size_t count,
+ TimeUnit::type* finest_unit);
ARROW_EXPORT
std::shared_ptr<DataType> CommonBinary(const ValueDescr* begin, size_t count);
diff --git a/cpp/src/arrow/compute/kernels/codegen_internal_test.cc b/cpp/src/arrow/compute/kernels/codegen_internal_test.cc
index 46d31c8ae4..6fb84cf55b 100644
--- a/cpp/src/arrow/compute/kernels/codegen_internal_test.cc
+++ b/cpp/src/arrow/compute/kernels/codegen_internal_test.cc
@@ -137,6 +137,8 @@ TEST(TestDispatchBest, CommonTemporal) {
args = {timestamp(TimeUnit::SECOND, "UTC"), timestamp(TimeUnit::NANO, "UTC")};
AssertTypeEqual(timestamp(TimeUnit::NANO, "UTC"),
CommonTemporal(args.data(), args.size()));
+ args = {timestamp(TimeUnit::SECOND), date32()};
+ AssertTypeEqual(timestamp(TimeUnit::SECOND), CommonTemporal(args.data(), args.size()));
args = {date32(), timestamp(TimeUnit::NANO)};
AssertTypeEqual(timestamp(TimeUnit::NANO), CommonTemporal(args.data(), args.size()));
args = {date64(), timestamp(TimeUnit::SECOND)};
@@ -161,53 +163,80 @@ TEST(TestDispatchBest, CommonTemporal) {
TEST(TestDispatchBest, CommonTemporalResolution) {
std::vector<ValueDescr> args;
std::string tz = "Pacific/Marquesas";
+ TimeUnit::type ty;
args = {date32(), date32()};
- ASSERT_EQ(TimeUnit::SECOND, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::SECOND, ty);
args = {date32(), date64()};
- ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MILLI, ty);
+ args = {date32(), timestamp(TimeUnit::SECOND)};
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::SECOND, ty);
args = {time32(TimeUnit::MILLI), date32()};
- ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MILLI, ty);
args = {time32(TimeUnit::MILLI), time32(TimeUnit::SECOND)};
- ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MILLI, ty);
args = {time32(TimeUnit::MILLI), time64(TimeUnit::MICRO)};
- ASSERT_EQ(TimeUnit::MICRO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MICRO, ty);
args = {time64(TimeUnit::NANO), time64(TimeUnit::MICRO)};
- ASSERT_EQ(TimeUnit::NANO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::NANO, ty);
args = {duration(TimeUnit::MILLI), duration(TimeUnit::MICRO)};
- ASSERT_EQ(TimeUnit::MICRO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MICRO, ty);
args = {duration(TimeUnit::MILLI), date32()};
- ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MILLI, ty);
args = {date64(), duration(TimeUnit::SECOND)};
- ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MILLI, ty);
args = {duration(TimeUnit::SECOND), time32(TimeUnit::SECOND)};
- ASSERT_EQ(TimeUnit::SECOND, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::SECOND, ty);
args = {duration(TimeUnit::SECOND), time64(TimeUnit::NANO)};
- ASSERT_EQ(TimeUnit::NANO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::NANO, ty);
args = {time64(TimeUnit::MICRO), duration(TimeUnit::NANO)};
- ASSERT_EQ(TimeUnit::NANO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::NANO, ty);
args = {timestamp(TimeUnit::SECOND, tz), timestamp(TimeUnit::MICRO)};
- ASSERT_EQ(TimeUnit::MICRO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MICRO, ty);
args = {date32(), timestamp(TimeUnit::MICRO, tz)};
- ASSERT_EQ(TimeUnit::MICRO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MICRO, ty);
args = {timestamp(TimeUnit::MICRO, tz), date64()};
- ASSERT_EQ(TimeUnit::MICRO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MICRO, ty);
args = {time32(TimeUnit::MILLI), timestamp(TimeUnit::MICRO, tz)};
- ASSERT_EQ(TimeUnit::MICRO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MICRO, ty);
args = {timestamp(TimeUnit::MICRO, tz), time64(TimeUnit::NANO)};
- ASSERT_EQ(TimeUnit::NANO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::NANO, ty);
args = {timestamp(TimeUnit::SECOND, tz), duration(TimeUnit::MILLI)};
- ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MILLI, ty);
args = {timestamp(TimeUnit::SECOND, "UTC"), timestamp(TimeUnit::SECOND, tz)};
- ASSERT_EQ(TimeUnit::SECOND, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::SECOND, ty);
args = {time32(TimeUnit::MILLI), duration(TimeUnit::SECOND)};
- ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MILLI, ty);
args = {time64(TimeUnit::MICRO), duration(TimeUnit::NANO)};
- ASSERT_EQ(TimeUnit::NANO, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::NANO, ty);
args = {duration(TimeUnit::SECOND), int64()};
- ASSERT_EQ(TimeUnit::SECOND, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::SECOND, ty);
args = {duration(TimeUnit::MILLI), timestamp(TimeUnit::SECOND, tz)};
- ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ASSERT_EQ(TimeUnit::MILLI, ty);
}
TEST(TestDispatchBest, ReplaceTemporalTypes) {
@@ -216,67 +245,68 @@ TEST(TestDispatchBest, ReplaceTemporalTypes) {
TimeUnit::type ty;
args = {date32(), date32()};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, timestamp(TimeUnit::SECOND));
AssertTypeEqual(args[1].type, timestamp(TimeUnit::SECOND));
args = {date64(), time32(TimeUnit::SECOND)};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, timestamp(TimeUnit::MILLI));
AssertTypeEqual(args[1].type, time32(TimeUnit::MILLI));
args = {duration(TimeUnit::SECOND), date64()};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, duration(TimeUnit::MILLI));
AssertTypeEqual(args[1].type, timestamp(TimeUnit::MILLI));
args = {timestamp(TimeUnit::MICRO, tz), timestamp(TimeUnit::NANO)};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, timestamp(TimeUnit::NANO, tz));
AssertTypeEqual(args[1].type, timestamp(TimeUnit::NANO));
args = {timestamp(TimeUnit::MICRO, tz), time64(TimeUnit::NANO)};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, timestamp(TimeUnit::NANO, tz));
AssertTypeEqual(args[1].type, time64(TimeUnit::NANO));
args = {timestamp(TimeUnit::SECOND, tz), date64()};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, timestamp(TimeUnit::MILLI, tz));
AssertTypeEqual(args[1].type, timestamp(TimeUnit::MILLI));
args = {timestamp(TimeUnit::SECOND, "UTC"), timestamp(TimeUnit::SECOND, tz)};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, timestamp(TimeUnit::SECOND, "UTC"));
AssertTypeEqual(args[1].type, timestamp(TimeUnit::SECOND, tz));
args = {time32(TimeUnit::SECOND), duration(TimeUnit::SECOND)};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, time32(TimeUnit::SECOND));
AssertTypeEqual(args[1].type, duration(TimeUnit::SECOND));
args = {time64(TimeUnit::MICRO), duration(TimeUnit::SECOND)};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, time64(TimeUnit::MICRO));
AssertTypeEqual(args[1].type, duration(TimeUnit::MICRO));
args = {time32(TimeUnit::SECOND), duration(TimeUnit::NANO)};
- ty = CommonTemporalResolution(args.data(), args.size());
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, time64(TimeUnit::NANO));
AssertTypeEqual(args[1].type, duration(TimeUnit::NANO));
args = {duration(TimeUnit::SECOND), int64()};
- ReplaceTemporalTypes(CommonTemporalResolution(args.data(), args.size()), &args);
+ ASSERT_TRUE(CommonTemporalResolution(args.data(), args.size(), &ty));
+ ReplaceTemporalTypes(ty, &args);
AssertTypeEqual(args[0].type, duration(TimeUnit::SECOND));
AssertTypeEqual(args[1].type, int64());
}
diff --git a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
index bfafb6fcc1..103f8e66c5 100644
--- a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
@@ -1818,11 +1818,11 @@ struct ArithmeticFunction : ScalarFunction {
// Only promote types for binary functions
if (values->size() == 2) {
ReplaceNullWithOtherType(values);
-
- if (auto type = CommonTemporalResolution(values->data(), values->size())) {
- ReplaceTemporalTypes(type, values);
- } else if (auto type = CommonNumeric(*values)) {
- ReplaceTypes(type, values);
+ TimeUnit::type finest_unit;
+ if (CommonTemporalResolution(values->data(), values->size(), &finest_unit)) {
+ ReplaceTemporalTypes(finest_unit, values);
+ } else if (auto numeric_type = CommonNumeric(*values)) {
+ ReplaceTypes(numeric_type, values);
}
}
diff --git a/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc b/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
index f2915951cb..a52d69c36c 100644
--- a/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
@@ -1234,6 +1234,84 @@ TEST_F(ScalarTemporalTest, TestTemporalSubtractDate) {
}
}
+TEST_F(ScalarTemporalTest, TestTemporalSubtractTimestampAndDate) {
+ std::string seconds_between_date_and_time =
+ "[59, 84203, 3560, 12800, 3905, 7810, 11715, 15620, "
+ "19525, 23430, 27335, 31240, 35145, 0, 0, 3723, null]";
+ std::string milliseconds_between_date_and_time =
+ "[59000, 84203000, 3560000, 12800000, 3905000, 7810000, 11715000, 15620000, "
+ "19525000, 23430000, 27335000, 31240000, 35145000, 0, 0, 3723000, null]";
+ std::string microseconds_between_date_and_time =
+ "[59000000, 84203000000, 3560000000, 12800000000, 3905000000, 7810000000, "
+ "11715000000, 15620000000, 19525000000, 23430000000, 27335000000, 31240000000, "
+ "35145000000, 0, 0, 3723000000, null]";
+ std::string nanoseconds_between_date_and_time =
+ "[59000000000, 84203000000000, 3560000000000, 12800000000000, 3905000000000, "
+ "7810000000000, 11715000000000, 15620000000000, 19525000000000, 23430000000000, "
+ "27335000000000, 31240000000000, 35145000000000, 0, 0, 3723000000000, null]";
+ std::string seconds_between_date_and_time2 =
+ "[-59, -84203, -3560, -12800, -3905, -7810, -11715, -15620, "
+ "-19525, -23430, -27335, -31240, -35145, 0, 0, -3723, null]";
+ std::string milliseconds_between_date_and_time2 =
+ "[-59000, -84203000, -3560000, -12800000, -3905000, -7810000, -11715000,"
+ "-15620000, -19525000, -23430000, -27335000, -31240000, -35145000, 0, 0, "
+ "-3723000, null]";
+ std::string microseconds_between_date_and_time2 =
+ "[-59000000, -84203000000, -3560000000, -12800000000, -3905000000, -7810000000, "
+ "-11715000000, -15620000000, -19525000000, -23430000000, -27335000000,"
+ "-31240000000, -35145000000, 0, 0, -3723000000, null]";
+ std::string nanoseconds_between_date_and_time2 =
+ "[-59000000000, -84203000000000, -3560000000000, -12800000000000, "
+ "-3905000000000, -7810000000000, -11715000000000, -15620000000000, "
+ "-19525000000000, -23430000000000, -27335000000000, -31240000000000, "
+ "-35145000000000, 0, 0, -3723000000000, null]";
+
+ auto arr_date32s = ArrayFromJSON(date32(), date32s);
+ auto arr_date32s2 = ArrayFromJSON(date32(), date32s2);
+ auto arr_date64s = ArrayFromJSON(date64(), date64s);
+ auto arr_date64s2 = ArrayFromJSON(date64(), date64s2);
+ auto timestamp_s = ArrayFromJSON(timestamp(TimeUnit::SECOND), times_seconds_precision);
+ auto timestamp_ms = ArrayFromJSON(timestamp(TimeUnit::MILLI), times_seconds_precision);
+ auto timestamp_us = ArrayFromJSON(timestamp(TimeUnit::MICRO), times_seconds_precision);
+ auto timestamp_ns = ArrayFromJSON(timestamp(TimeUnit::NANO), times_seconds_precision);
+ auto between_s =
+ ArrayFromJSON(duration(TimeUnit::SECOND), seconds_between_date_and_time);
+ auto between_ms =
+ ArrayFromJSON(duration(TimeUnit::MILLI), milliseconds_between_date_and_time);
+ auto between_us =
+ ArrayFromJSON(duration(TimeUnit::MICRO), microseconds_between_date_and_time);
+ auto between_ns =
+ ArrayFromJSON(duration(TimeUnit::NANO), nanoseconds_between_date_and_time);
+ auto between_s2 =
+ ArrayFromJSON(duration(TimeUnit::SECOND), seconds_between_date_and_time2);
+ auto between_ms2 =
+ ArrayFromJSON(duration(TimeUnit::MILLI), milliseconds_between_date_and_time2);
+ auto between_us2 =
+ ArrayFromJSON(duration(TimeUnit::MICRO), microseconds_between_date_and_time2);
+ auto between_ns2 =
+ ArrayFromJSON(duration(TimeUnit::NANO), nanoseconds_between_date_and_time2);
+
+ for (auto op : {"subtract", "subtract_checked"}) {
+ CheckScalarBinary(op, timestamp_s, arr_date32s, between_s);
+ CheckScalarBinary(op, timestamp_ms, arr_date32s, between_ms);
+ CheckScalarBinary(op, timestamp_us, arr_date32s, between_us);
+ CheckScalarBinary(op, timestamp_ns, arr_date32s, between_ns);
+ CheckScalarBinary(op, timestamp_s, arr_date64s, between_ms);
+ CheckScalarBinary(op, timestamp_ms, arr_date64s, between_ms);
+ CheckScalarBinary(op, timestamp_us, arr_date64s, between_us);
+ CheckScalarBinary(op, timestamp_ns, arr_date64s, between_ns);
+
+ CheckScalarBinary(op, arr_date32s, timestamp_s, between_s2);
+ CheckScalarBinary(op, arr_date32s, timestamp_ms, between_ms2);
+ CheckScalarBinary(op, arr_date32s, timestamp_us, between_us2);
+ CheckScalarBinary(op, arr_date32s, timestamp_ns, between_ns2);
+ CheckScalarBinary(op, arr_date64s, timestamp_s, between_ms2);
+ CheckScalarBinary(op, arr_date64s, timestamp_ms, between_ms2);
+ CheckScalarBinary(op, arr_date64s, timestamp_us, between_us2);
+ CheckScalarBinary(op, arr_date64s, timestamp_ns, between_ns2);
+ }
+}
+
TEST_F(ScalarTemporalTest, TestTemporalSubtractTimestamp) {
for (auto op : {"subtract", "subtract_checked"}) {
for (auto tz : {"", "UTC", "Pacific/Marquesas"}) {