You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ap...@apache.org on 2022/07/05 16:40:06 UTC
[arrow] branch master updated: ARROW-16932: [C++] Rounding RoundTemporalOptions.calendar_based_origin doesn't correctly offset non-UTC results (#13462)
This is an automated email from the ASF dual-hosted git repository.
apitrou 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 c1a1f47b8a ARROW-16932: [C++] Rounding RoundTemporalOptions.calendar_based_origin doesn't correctly offset non-UTC results (#13462)
c1a1f47b8a is described below
commit c1a1f47b8a2772fc270832902e7d788ee467ea08
Author: Rok Mihevc <ro...@mihevc.org>
AuthorDate: Tue Jul 5 18:40:00 2022 +0200
ARROW-16932: [C++] Rounding RoundTemporalOptions.calendar_based_origin doesn't correctly offset non-UTC results (#13462)
When rounding to some calendar units the result will be offset in UTC instead of the local timezone. [See discussion](https://github.com/apache/arrow/pull/12154#issuecomment-1169578666).
This adds a fix and C++ test cases.
Lead-authored-by: Rok <ro...@mihevc.org>
Co-authored-by: Rok Mihevc <ro...@mihevc.org>
Signed-off-by: Antoine Pitrou <an...@python.org>
---
.../arrow/compute/kernels/scalar_temporal_test.cc | 619 +++++++++++++++------
.../arrow/compute/kernels/scalar_temporal_unary.cc | 52 +-
2 files changed, 484 insertions(+), 187 deletions(-)
diff --git a/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc b/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
index 45bd7819c4..ab1f349c16 100644
--- a/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
@@ -418,6 +418,122 @@ class ScalarTemporalTest : public ::testing::Test {
}
};
+class ScalarTemporalTestStrictCeil : public ScalarTemporalTest {
+ public:
+ RoundTemporalOptions round_to_1_nanoseconds = RoundTemporalOptions(
+ 1, CalendarUnit::NANOSECOND, /*week_starts_monday=*/true,
+ /*ceil_is_strictly_greater=*/true, /*calendar_based_origin=*/false);
+ RoundTemporalOptions round_to_1_microseconds =
+ RoundTemporalOptions(1, CalendarUnit::MICROSECOND, true, true, false);
+ RoundTemporalOptions round_to_1_milliseconds =
+ RoundTemporalOptions(1, CalendarUnit::MILLISECOND, true, true, false);
+ RoundTemporalOptions round_to_1_seconds =
+ RoundTemporalOptions(1, CalendarUnit::SECOND, true, true, false);
+ RoundTemporalOptions round_to_1_minutes =
+ RoundTemporalOptions(1, CalendarUnit::MINUTE, true, true, false);
+ RoundTemporalOptions round_to_1_hours =
+ RoundTemporalOptions(1, CalendarUnit::HOUR, true, true, false);
+ RoundTemporalOptions round_to_1_days =
+ RoundTemporalOptions(1, CalendarUnit::DAY, true, true, false);
+ RoundTemporalOptions round_to_1_weeks =
+ RoundTemporalOptions(1, CalendarUnit::WEEK, true, true, false);
+ RoundTemporalOptions round_to_1_weeks_sunday =
+ RoundTemporalOptions(1, CalendarUnit::WEEK, false, true, false);
+ RoundTemporalOptions round_to_1_months =
+ RoundTemporalOptions(1, CalendarUnit::MONTH, true, true, false);
+ RoundTemporalOptions round_to_1_quarters =
+ RoundTemporalOptions(1, CalendarUnit::QUARTER, true, true, false);
+ RoundTemporalOptions round_to_1_years =
+ RoundTemporalOptions(1, CalendarUnit::YEAR, true, true, false);
+
+ RoundTemporalOptions round_to_15_nanoseconds =
+ RoundTemporalOptions(15, CalendarUnit::NANOSECOND, true, true, false);
+ RoundTemporalOptions round_to_15_microseconds =
+ RoundTemporalOptions(15, CalendarUnit::MICROSECOND, true, true, false);
+ RoundTemporalOptions round_to_15_milliseconds =
+ RoundTemporalOptions(15, CalendarUnit::MILLISECOND, true, true, false);
+ RoundTemporalOptions round_to_13_seconds =
+ RoundTemporalOptions(13, CalendarUnit::SECOND, true, true, false);
+ RoundTemporalOptions round_to_13_minutes =
+ RoundTemporalOptions(13, CalendarUnit::MINUTE, true, true, false);
+ RoundTemporalOptions round_to_15_hours =
+ RoundTemporalOptions(15, CalendarUnit::HOUR, true, true, false);
+ RoundTemporalOptions round_to_15_days =
+ RoundTemporalOptions(15, CalendarUnit::DAY, true, true, false);
+ RoundTemporalOptions round_to_3_weeks =
+ RoundTemporalOptions(3, CalendarUnit::WEEK, true, true, false);
+ RoundTemporalOptions round_to_3_weeks_sunday =
+ RoundTemporalOptions(3, CalendarUnit::WEEK, false, true, false);
+ RoundTemporalOptions round_to_5_months =
+ RoundTemporalOptions(5, CalendarUnit::MONTH, true, true, false);
+ RoundTemporalOptions round_to_15_months =
+ RoundTemporalOptions(15, CalendarUnit::MONTH, true, true, false);
+ RoundTemporalOptions round_to_3_quarters =
+ RoundTemporalOptions(3, CalendarUnit::QUARTER, true, true, false);
+ RoundTemporalOptions round_to_15_quarters =
+ RoundTemporalOptions(15, CalendarUnit::QUARTER, true, true, false);
+ RoundTemporalOptions round_to_15_years =
+ RoundTemporalOptions(15, CalendarUnit::YEAR, true, true, false);
+};
+
+class ScalarTemporalTestMultipleSinceGreaterUnit : public ScalarTemporalTest {
+ public:
+ RoundTemporalOptions round_to_1_nanoseconds = RoundTemporalOptions(
+ 1, CalendarUnit::NANOSECOND, /*week_starts_monday=*/true,
+ /*ceil_is_strictly_greater=*/true, /*calendar_based_origin=*/true);
+ RoundTemporalOptions round_to_1_microseconds =
+ RoundTemporalOptions(1, CalendarUnit::MICROSECOND, true, true, true);
+ RoundTemporalOptions round_to_1_milliseconds =
+ RoundTemporalOptions(1, CalendarUnit::MILLISECOND, true, true, true);
+ RoundTemporalOptions round_to_1_seconds =
+ RoundTemporalOptions(1, CalendarUnit::SECOND, true, true, true);
+ RoundTemporalOptions round_to_1_minutes =
+ RoundTemporalOptions(1, CalendarUnit::MINUTE, true, true, true);
+ RoundTemporalOptions round_to_1_hours =
+ RoundTemporalOptions(1, CalendarUnit::HOUR, true, true, true);
+ RoundTemporalOptions round_to_1_days =
+ RoundTemporalOptions(1, CalendarUnit::DAY, true, true, true);
+ RoundTemporalOptions round_to_1_weeks =
+ RoundTemporalOptions(1, CalendarUnit::WEEK, true, true, true);
+ RoundTemporalOptions round_to_1_weeks_sunday =
+ RoundTemporalOptions(1, CalendarUnit::WEEK, false, true, true);
+ RoundTemporalOptions round_to_1_months =
+ RoundTemporalOptions(1, CalendarUnit::MONTH, true, true, true);
+ RoundTemporalOptions round_to_1_quarters =
+ RoundTemporalOptions(1, CalendarUnit::QUARTER, true, true, true);
+ RoundTemporalOptions round_to_1_years =
+ RoundTemporalOptions(1, CalendarUnit::YEAR, true, true, true);
+
+ RoundTemporalOptions round_to_15_nanoseconds =
+ RoundTemporalOptions(15, CalendarUnit::NANOSECOND, true, true, true);
+ RoundTemporalOptions round_to_15_microseconds =
+ RoundTemporalOptions(15, CalendarUnit::MICROSECOND, true, true, true);
+ RoundTemporalOptions round_to_15_milliseconds =
+ RoundTemporalOptions(15, CalendarUnit::MILLISECOND, true, true, true);
+ RoundTemporalOptions round_to_13_seconds =
+ RoundTemporalOptions(13, CalendarUnit::SECOND, true, true, true);
+ RoundTemporalOptions round_to_13_minutes =
+ RoundTemporalOptions(13, CalendarUnit::MINUTE, true, true, true);
+ RoundTemporalOptions round_to_15_hours =
+ RoundTemporalOptions(15, CalendarUnit::HOUR, true, true, true);
+ RoundTemporalOptions round_to_15_days =
+ RoundTemporalOptions(15, CalendarUnit::DAY, true, true, true);
+ RoundTemporalOptions round_to_3_weeks =
+ RoundTemporalOptions(3, CalendarUnit::WEEK, true, true, true);
+ RoundTemporalOptions round_to_3_weeks_sunday =
+ RoundTemporalOptions(3, CalendarUnit::WEEK, false, true, true);
+ RoundTemporalOptions round_to_5_months =
+ RoundTemporalOptions(5, CalendarUnit::MONTH, true, true, true);
+ RoundTemporalOptions round_to_15_months =
+ RoundTemporalOptions(15, CalendarUnit::MONTH, true, true, true);
+ RoundTemporalOptions round_to_3_quarters =
+ RoundTemporalOptions(3, CalendarUnit::QUARTER, true, true, true);
+ RoundTemporalOptions round_to_15_quarters =
+ RoundTemporalOptions(15, CalendarUnit::QUARTER, true, true, true);
+ RoundTemporalOptions round_to_15_years =
+ RoundTemporalOptions(15, CalendarUnit::YEAR, true, true, true);
+};
+
TEST_F(ScalarTemporalTest, TestTemporalComponentExtractionAllTemporalTypes) {
std::vector<std::shared_ptr<DataType>> units = {date32(), date64(),
timestamp(TimeUnit::NANO)};
@@ -2229,57 +2345,8 @@ TEST_F(ScalarTemporalTest, TestCeilTemporal) {
CheckScalarUnary(op, unit, times, unit, ceil_15_years, &round_to_15_years);
}
-TEST_F(ScalarTemporalTest, TestCeilTemporalStrictCeil) {
+TEST_F(ScalarTemporalTestStrictCeil, TestCeilTemporalStrictCeil) {
std::string op = "ceil_temporal";
- RoundTemporalOptions round_to_1_nanoseconds =
- RoundTemporalOptions(1, CalendarUnit::NANOSECOND, true, true, false);
- RoundTemporalOptions round_to_1_microseconds =
- RoundTemporalOptions(1, CalendarUnit::MICROSECOND, true, true, false);
- RoundTemporalOptions round_to_1_milliseconds =
- RoundTemporalOptions(1, CalendarUnit::MILLISECOND, true, true, false);
- RoundTemporalOptions round_to_1_seconds =
- RoundTemporalOptions(1, CalendarUnit::SECOND, true, true, false);
- RoundTemporalOptions round_to_1_minutes =
- RoundTemporalOptions(1, CalendarUnit::MINUTE, true, true, false);
- RoundTemporalOptions round_to_1_hours =
- RoundTemporalOptions(1, CalendarUnit::HOUR, true, true, false);
- RoundTemporalOptions round_to_1_days =
- RoundTemporalOptions(1, CalendarUnit::DAY, true, true, false);
- RoundTemporalOptions round_to_1_weeks =
- RoundTemporalOptions(1, CalendarUnit::WEEK, true, true, false);
- RoundTemporalOptions round_to_1_weeks_sunday =
- RoundTemporalOptions(1, CalendarUnit::WEEK, false, true, false);
- RoundTemporalOptions round_to_1_months =
- RoundTemporalOptions(1, CalendarUnit::MONTH, true, true, false);
- RoundTemporalOptions round_to_1_quarters =
- RoundTemporalOptions(1, CalendarUnit::QUARTER, true, true, false);
- RoundTemporalOptions round_to_1_years =
- RoundTemporalOptions(1, CalendarUnit::YEAR, true, true, false);
-
- RoundTemporalOptions round_to_15_nanoseconds =
- RoundTemporalOptions(15, CalendarUnit::NANOSECOND, true, true, false);
- RoundTemporalOptions round_to_15_microseconds =
- RoundTemporalOptions(15, CalendarUnit::MICROSECOND, true, true, false);
- RoundTemporalOptions round_to_15_milliseconds =
- RoundTemporalOptions(15, CalendarUnit::MILLISECOND, true, true, false);
- RoundTemporalOptions round_to_13_seconds =
- RoundTemporalOptions(13, CalendarUnit::SECOND, true, true, false);
- RoundTemporalOptions round_to_13_minutes =
- RoundTemporalOptions(13, CalendarUnit::MINUTE, true, true, false);
- RoundTemporalOptions round_to_15_hours =
- RoundTemporalOptions(15, CalendarUnit::HOUR, true, true, false);
- RoundTemporalOptions round_to_15_days =
- RoundTemporalOptions(15, CalendarUnit::DAY, true, true, false);
- RoundTemporalOptions round_to_15_weeks =
- RoundTemporalOptions(15, CalendarUnit::WEEK, true, true, false);
- RoundTemporalOptions round_to_15_weeks_sunday =
- RoundTemporalOptions(15, CalendarUnit::WEEK, false, true, false);
- RoundTemporalOptions round_to_15_months =
- RoundTemporalOptions(15, CalendarUnit::MONTH, true, true, false);
- RoundTemporalOptions round_to_15_quarters =
- RoundTemporalOptions(15, CalendarUnit::QUARTER, true, true, false);
- RoundTemporalOptions round_to_15_years =
- RoundTemporalOptions(15, CalendarUnit::YEAR, true, true, false);
const char* ceil_1_nanosecond =
R"(["1970-01-01 00:00:59.123456790", "2000-02-29 23:23:24.000000000",
@@ -2413,16 +2480,16 @@ TEST_F(ScalarTemporalTest, TestCeilTemporalStrictCeil) {
"2020-01-09", "2020-01-09", "2010-01-01", "2010-01-16", "2010-01-16",
"2010-01-16", "2006-01-07", "2006-01-07", "2009-01-06", "2009-01-06",
"2012-01-06", null])";
- const char* ceil_15_weeks =
- R"(["1970-04-13", "2000-03-06", "1899-04-10", "2033-07-11", "2020-01-06",
- "2020-01-06", "2020-01-06", "2010-03-29", "2010-03-29", "2010-03-29",
- "2010-03-29", "2006-03-20", "2006-03-20", "2009-02-02", "2009-02-02",
- "2012-04-02", null])";
- const char* ceil_15_weeks_sunday =
- R"(["1970-04-12", "2000-03-05", "1899-04-09", "2033-07-10", "2020-01-05",
- "2020-01-05", "2020-01-05", "2010-03-28", "2010-03-28", "2010-03-28",
- "2010-03-28", "2006-03-19", "2006-03-19", "2009-02-01", "2009-02-01",
- "2012-04-01", null])";
+ const char* ceil_3_weeks =
+ R"(["1970-01-19", "2000-03-06", "1899-01-16", "2033-05-30", "2020-01-06",
+ "2020-01-06", "2020-01-06", "2010-01-04", "2010-01-04", "2010-01-04",
+ "2010-01-25", "2006-01-16", "2006-01-16", "2009-01-12", "2009-01-12",
+ "2012-01-09", null])";
+ const char* ceil_3_weeks_sunday =
+ R"(["1970-01-18", "2000-03-05", "1899-01-15", "2033-05-29", "2020-01-05",
+ "2020-01-05", "2020-01-05", "2010-01-03", "2010-01-03", "2010-01-24",
+ "2010-01-24", "2006-01-15", "2006-01-15", "2009-01-11", "2009-01-11",
+ "2012-01-08", null])";
const char* ceil_15_months =
R"(["1971-04-01", "2001-04-01", "1900-01-01", "2033-10-01", "2021-04-01",
"2020-01-01", "2020-01-01", "2010-01-01", "2011-04-01", "2011-04-01",
@@ -2460,40 +2527,15 @@ TEST_F(ScalarTemporalTest, TestCeilTemporalStrictCeil) {
CheckScalarUnary(op, unit, times, unit, ceil_13_minute, &round_to_13_minutes);
CheckScalarUnary(op, unit, times, unit, ceil_15_hour, &round_to_15_hours);
CheckScalarUnary(op, unit, times, unit, ceil_15_day, &round_to_15_days);
- CheckScalarUnary(op, unit, times, unit, ceil_15_weeks, &round_to_15_weeks);
- CheckScalarUnary(op, unit, times, unit, ceil_15_weeks_sunday,
- &round_to_15_weeks_sunday);
+ CheckScalarUnary(op, unit, times, unit, ceil_3_weeks, &round_to_3_weeks);
+ CheckScalarUnary(op, unit, times, unit, ceil_3_weeks_sunday, &round_to_3_weeks_sunday);
CheckScalarUnary(op, unit, times, unit, ceil_15_months, &round_to_15_months);
CheckScalarUnary(op, unit, times, unit, ceil_15_quarters, &round_to_15_quarters);
CheckScalarUnary(op, unit, times, unit, ceil_15_years, &round_to_15_years);
}
-TEST_F(ScalarTemporalTest, TestCeilTemporalMultipleSinceGreaterUnit) {
+TEST_F(ScalarTemporalTestMultipleSinceGreaterUnit, CeilUTC) {
std::string op = "ceil_temporal";
- RoundTemporalOptions round_to_15_nanoseconds =
- RoundTemporalOptions(15, CalendarUnit::NANOSECOND, true, true, true);
- RoundTemporalOptions round_to_15_microseconds =
- RoundTemporalOptions(15, CalendarUnit::MICROSECOND, true, true, true);
- RoundTemporalOptions round_to_15_milliseconds =
- RoundTemporalOptions(15, CalendarUnit::MILLISECOND, true, true, true);
- RoundTemporalOptions round_to_13_seconds =
- RoundTemporalOptions(13, CalendarUnit::SECOND, true, true, true);
- RoundTemporalOptions round_to_13_minutes =
- RoundTemporalOptions(13, CalendarUnit::MINUTE, true, true, true);
- RoundTemporalOptions round_to_15_hours =
- RoundTemporalOptions(15, CalendarUnit::HOUR, true, true, true);
- RoundTemporalOptions round_to_15_days =
- RoundTemporalOptions(15, CalendarUnit::DAY, true, true, true);
- RoundTemporalOptions round_to_15_weeks =
- RoundTemporalOptions(15, CalendarUnit::WEEK, true, true, true);
- RoundTemporalOptions round_to_15_weeks_sunday =
- RoundTemporalOptions(15, CalendarUnit::WEEK, false, true, true);
- RoundTemporalOptions round_to_15_months =
- RoundTemporalOptions(15, CalendarUnit::MONTH, true, true, true);
- RoundTemporalOptions round_to_15_quarters =
- RoundTemporalOptions(15, CalendarUnit::QUARTER, true, true, true);
- RoundTemporalOptions round_to_15_years =
- RoundTemporalOptions(15, CalendarUnit::YEAR, true, true, true);
// Data for tests below was generaed via lubridate with the exception
// of week data because lubridate currently does not support rounding to
@@ -2551,16 +2593,16 @@ TEST_F(ScalarTemporalTest, TestCeilTemporalMultipleSinceGreaterUnit) {
"2020-01-16", "2020-01-15", "2019-12-31", "2010-01-15",
"2010-01-16", "2010-01-16", "2010-01-16", "2006-01-16",
"2006-01-15", "2008-12-31", "2008-12-31", "2012-01-16", null])";
- const char* ceil_15_weeks =
- R"(["1970-04-13", "2000-04-17", "1899-04-17", "2033-08-01", "2020-04-13",
- "2020-04-13", "2020-04-13", "2010-04-19", "2010-04-19", "2010-04-19",
- "2010-04-19", "2006-04-17", "2006-04-17", "2009-02-23", "2009-04-13",
- "2012-04-16", null])";
- const char* ceil_15_weeks_sunday =
- R"(["1970-04-19", "2000-04-16", "1899-04-16", "2033-07-31", "2020-04-12",
- "2020-04-12", "2020-04-12", "2010-04-18", "2010-04-18", "2010-04-18",
- "2010-04-18", "2006-04-16", "2006-04-16", "2009-04-19", "2009-04-19",
- "2012-04-15", null])";
+ const char* ceil_3_weeks =
+ R"(["1970-01-19", "2000-03-06", "1899-01-23", "2033-05-30", "2020-01-20",
+ "2020-01-20", "2020-01-20", "2010-01-25", "2010-01-25", "2010-01-25",
+ "2010-01-25", "2006-01-23", "2006-01-23", "2009-01-12", "2009-01-19",
+ "2012-01-23", null])";
+ const char* ceil_3_weeks_sunday =
+ R"(["1970-01-25", "2000-03-05", "1899-01-22", "2033-05-29", "2020-01-19",
+ "2020-01-19", "2020-01-19", "2010-01-24", "2010-01-24", "2010-01-24",
+ "2010-01-24", "2006-01-22", "2006-01-22", "2009-01-25", "2009-01-25",
+ "2012-01-22", null])";
const char* ceil_15_months =
R"(["1971-04-01", "2001-04-01", "1900-04-01", "2034-04-01",
"2021-04-01", "2020-04-01", "2020-04-01", "2010-04-01",
@@ -2585,16 +2627,112 @@ TEST_F(ScalarTemporalTest, TestCeilTemporalMultipleSinceGreaterUnit) {
CheckScalarUnary(op, unit, times, unit, ceil_13_minute, &round_to_13_minutes);
CheckScalarUnary(op, unit, times, unit, ceil_15_hour, &round_to_15_hours);
CheckScalarUnary(op, unit, times, unit, ceil_15_day, &round_to_15_days);
- CheckScalarUnary(op, unit, times, unit, ceil_15_weeks, &round_to_15_weeks);
- CheckScalarUnary(op, unit, times, unit, ceil_15_weeks_sunday,
- &round_to_15_weeks_sunday);
+ CheckScalarUnary(op, unit, times, unit, ceil_3_weeks, &round_to_3_weeks);
+ CheckScalarUnary(op, unit, times, unit, ceil_3_weeks_sunday, &round_to_3_weeks_sunday);
CheckScalarUnary(op, unit, times, unit, ceil_15_months, &round_to_15_months);
CheckScalarUnary(op, unit, times, unit, ceil_15_quarters, &round_to_15_quarters);
CheckScalarUnary(op, unit, times, unit, ceil_15_years, &round_to_15_years);
}
+TEST_F(ScalarTemporalTestMultipleSinceGreaterUnit, CeilZoned) {
+ std::string op = "ceil_temporal";
+
+ // Data for tests below was generated via lubridate with the exception
+ // of week data because lubridate currently does not support rounding to
+ // multiple of week.
+ const char* ceil_15_nanosecond =
+ R"(["1970-01-01 00:00:59.123456795", "2000-02-29 23:23:24.000000005",
+ "1899-01-01 00:59:20.001001015", "2033-05-18 03:33:20.000000015",
+ "2020-01-01 01:05:05.001000015", "2019-12-31 02:10:10.002000015",
+ "2019-12-30 03:15:15.003000015", "2009-12-31 04:20:20.004132015",
+ "2010-01-01 05:25:25.005321015", "2010-01-03 06:30:30.006163015",
+ "2010-01-04 07:35:35.000000015", "2006-01-01 08:40:40.000000015",
+ "2005-12-31 09:45:45.000000015", "2008-12-28 00:00:00.000000015",
+ "2008-12-29 00:00:00.000000015", "2012-01-01 01:02:03.000000015", null])";
+ const char* ceil_15_microsecond =
+ R"(["1970-01-01 00:00:59.123465", "2000-02-29 23:23:24.000005",
+ "1899-01-01 00:59:20.001015", "2033-05-18 03:33:20.000015",
+ "2020-01-01 01:05:05.001015", "2019-12-31 02:10:10.002015",
+ "2019-12-30 03:15:15.003015", "2009-12-31 04:20:20.004135",
+ "2010-01-01 05:25:25.005330", "2010-01-03 06:30:30.006165",
+ "2010-01-04 07:35:35.000015", "2006-01-01 08:40:40.000015",
+ "2005-12-31 09:45:45.000015", "2008-12-28 00:00:00.000015",
+ "2008-12-29 00:00:00.000015", "2012-01-01 01:02:03.000015", null])";
+ const char* ceil_15_millisecond =
+ R"(["1970-01-01 00:00:59.135", "2000-02-29 23:23:24.005",
+ "1899-01-01 00:59:20.015", "2033-05-18 03:33:20.015",
+ "2020-01-01 01:05:05.015", "2019-12-31 02:10:10.015",
+ "2019-12-30 03:15:15.015", "2009-12-31 04:20:20.015",
+ "2010-01-01 05:25:25.015", "2010-01-03 06:30:30.015",
+ "2010-01-04 07:35:35.015", "2006-01-01 08:40:40.015",
+ "2005-12-31 09:45:45.015", "2008-12-28 00:00:00.015",
+ "2008-12-29 00:00:00.015", "2012-01-01 01:02:03.015", null])";
+ const char* ceil_13_second = R"([
+ "1970-01-01 00:01:05", "2000-02-29 23:23:26", "1899-01-01 00:59:26", "2033-05-18 03:33:26",
+ "2020-01-01 01:05:13", "2019-12-31 02:10:13", "2019-12-30 03:15:26", "2009-12-31 04:20:26",
+ "2010-01-01 05:25:26", "2010-01-03 06:30:39", "2010-01-04 07:35:39", "2006-01-01 08:40:52",
+ "2005-12-31 09:45:52", "2008-12-28 00:00:13", "2008-12-29 00:00:13", "2012-01-01 01:02:13", null])";
+ const char* ceil_13_minute = R"([
+ "1970-01-01 00:09:00", "2000-02-29 23:35:00", "1899-01-01 01:05:00", "2033-05-18 03:43:00",
+ "2020-01-01 01:09:00", "2019-12-31 02:22:00", "2019-12-30 03:22:00", "2009-12-31 04:22:00",
+ "2010-01-01 05:35:00", "2010-01-03 06:43:00", "2010-01-04 07:43:00", "2006-01-01 08:43:00",
+ "2005-12-31 09:56:00", "2008-12-28 00:09:00", "2008-12-29 00:09:00", "2012-01-01 01:09:00", null])";
+ const char* ceil_15_hour = R"([
+ "1970-01-01 05:30:00", "2000-03-01 04:30:00", "1899-01-01 06:00:00", "2033-05-18 05:30:00",
+ "2020-01-01 04:30:00", "2019-12-31 04:30:00", "2019-12-30 04:30:00", "2009-12-31 04:30:00",
+ "2010-01-01 19:30:00", "2010-01-03 19:30:00", "2010-01-04 19:30:00", "2006-01-01 19:30:00",
+ "2005-12-31 19:30:00", "2008-12-28 04:30:00", "2008-12-29 04:30:00", "2012-01-01 04:30:00", null])";
+ const char* ceil_15_day = R"([
+ "1970-01-15 14:30:00", "2000-03-15 13:30:00", "1899-01-15 15:00:00", "2033-05-30 14:30:00",
+ "2020-01-15 13:30:00", "2020-01-14 13:30:00", "2019-12-30 13:30:00", "2010-01-14 13:30:00",
+ "2010-01-15 13:30:00", "2010-01-15 13:30:00", "2010-01-15 13:30:00", "2006-01-15 13:30:00",
+ "2006-01-14 13:30:00", "2008-12-30 13:30:00", "2008-12-30 13:30:00", "2012-01-15 13:30:00", null])";
+ const char* ceil_3_weeks = R"([
+ "1970-01-18 14:30:00", "2000-03-05 13:30:00", "1899-01-22 15:00:00", "2033-05-29 14:30:00",
+ "2020-01-19 13:30:00", "2020-01-19 13:30:00", "2020-01-19 13:30:00", "2010-01-24 13:30:00",
+ "2010-01-24 13:30:00", "2010-01-24 13:30:00", "2010-01-24 13:30:00", "2006-01-22 13:30:00",
+ "2006-01-22 13:30:00", "2009-01-11 13:30:00", "2009-01-18 13:30:00", "2012-01-22 13:30:00", null])";
+ const char* ceil_3_weeks_sunday = R"([
+ "1970-01-24 14:30:00", "2000-03-25 13:30:00", "1899-01-21 15:00:00", "2033-05-28 14:30:00",
+ "2020-01-18 13:30:00", "2020-01-18 13:30:00", "2020-01-18 13:30:00", "2010-01-23 13:30:00",
+ "2010-01-23 13:30:00", "2010-01-23 13:30:00", "2010-01-23 13:30:00", "2006-01-21 13:30:00",
+ "2006-01-21 13:30:00", "2009-01-24 13:30:00", "2009-01-24 13:30:00", "2012-01-21 13:30:00", null])";
+ const char* ceil_5_months = R"([
+ "1970-05-31 14:30:00", "2000-05-31 14:30:00", "1899-05-31 14:30:00", "2033-05-31 14:30:00",
+ "2020-05-31 14:30:00", "2020-03-31 13:30:00", "2020-03-31 13:30:00", "2010-03-31 13:30:00",
+ "2010-05-31 14:30:00", "2010-05-31 14:30:00", "2010-05-31 14:30:00", "2006-05-31 14:30:00",
+ "2006-03-31 13:30:00", "2009-03-31 13:30:00", "2009-03-31 13:30:00", "2012-05-31 14:30:00", null])";
+ const char* ceil_3_quarters = R"([
+ "1970-09-30 14:30:00", "2000-09-30 14:30:00", "1899-09-30 14:30:00", "2033-09-30 14:30:00",
+ "2020-09-30 14:30:00", "2020-06-30 14:30:00", "2020-06-30 14:30:00", "2010-06-30 14:30:00",
+ "2010-09-30 14:30:00", "2010-09-30 14:30:00", "2010-09-30 14:30:00", "2006-09-30 14:30:00",
+ "2006-06-30 14:30:00", "2009-06-30 14:30:00", "2009-06-30 14:30:00", "2012-09-30 14:30:00", null])";
+ const char* ceil_15_years = R"([
+ "1979-12-31 13:30:00", "2009-12-31 13:30:00", "1904-12-31 14:30:00", "2039-12-31 13:30:00",
+ "2024-12-31 13:30:00", "2024-12-31 13:30:00", "2024-12-31 13:30:00", "2009-12-31 13:30:00",
+ "2024-12-31 13:30:00", "2024-12-31 13:30:00", "2024-12-31 13:30:00", "2009-12-31 13:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2024-12-31 13:30:00", null])";
+
+ // Australia/Broken_Hill timezone is defined as UTC+9:30 and UTC+10:30 during DST.
+ // DST runs from first Sunday in October to first Sunday in April.
+ auto unit = timestamp(TimeUnit::NANO, "Australia/Broken_Hill");
+ CheckScalarUnary(op, unit, times, unit, ceil_15_nanosecond, &round_to_15_nanoseconds);
+ CheckScalarUnary(op, unit, times, unit, ceil_15_microsecond, &round_to_15_microseconds);
+ CheckScalarUnary(op, unit, times, unit, ceil_15_millisecond, &round_to_15_milliseconds);
+ CheckScalarUnary(op, unit, times, unit, ceil_13_second, &round_to_13_seconds);
+ CheckScalarUnary(op, unit, times, unit, ceil_13_minute, &round_to_13_minutes);
+ CheckScalarUnary(op, unit, times, unit, ceil_15_hour, &round_to_15_hours);
+ CheckScalarUnary(op, unit, times, unit, ceil_15_day, &round_to_15_days);
+ CheckScalarUnary(op, unit, times, unit, ceil_3_weeks, &round_to_3_weeks);
+ CheckScalarUnary(op, unit, times, unit, ceil_3_weeks_sunday, &round_to_3_weeks_sunday);
+ CheckScalarUnary(op, unit, times, unit, ceil_5_months, &round_to_5_months);
+ CheckScalarUnary(op, unit, times, unit, ceil_3_quarters, &round_to_3_quarters);
+ CheckScalarUnary(op, unit, times, unit, ceil_15_years, &round_to_15_years);
+}
+
TEST_F(ScalarTemporalTest, TestFloorTemporal) {
std::string op = "floor_temporal";
+
const char* floor_1_nanosecond =
R"(["1970-01-01 00:00:59.123456789", "2000-02-29 23:23:23.999999999",
"1899-01-01 00:59:20.001001001", "2033-05-18 03:33:20.000000000",
@@ -2784,32 +2922,8 @@ TEST_F(ScalarTemporalTest, TestFloorTemporal) {
CheckScalarUnary(op, unit, times, unit, floor_15_years, &round_to_15_years);
}
-TEST_F(ScalarTemporalTest, TestFloorTemporalMultipleSinceGreaterUnit) {
+TEST_F(ScalarTemporalTestMultipleSinceGreaterUnit, FloorUTC) {
std::string op = "floor_temporal";
- RoundTemporalOptions round_to_15_nanoseconds =
- RoundTemporalOptions(15, CalendarUnit::NANOSECOND, true, true, true);
- RoundTemporalOptions round_to_15_microseconds =
- RoundTemporalOptions(15, CalendarUnit::MICROSECOND, true, true, true);
- RoundTemporalOptions round_to_15_milliseconds =
- RoundTemporalOptions(15, CalendarUnit::MILLISECOND, true, true, true);
- RoundTemporalOptions round_to_13_seconds =
- RoundTemporalOptions(13, CalendarUnit::SECOND, true, true, true);
- RoundTemporalOptions round_to_13_minutes =
- RoundTemporalOptions(13, CalendarUnit::MINUTE, true, true, true);
- RoundTemporalOptions round_to_15_hours =
- RoundTemporalOptions(15, CalendarUnit::HOUR, true, true, true);
- RoundTemporalOptions round_to_15_days =
- RoundTemporalOptions(15, CalendarUnit::DAY, true, true, true);
- RoundTemporalOptions round_to_15_weeks =
- RoundTemporalOptions(15, CalendarUnit::WEEK, true, true, true);
- RoundTemporalOptions round_to_15_weeks_sunday =
- RoundTemporalOptions(15, CalendarUnit::WEEK, false, true, true);
- RoundTemporalOptions round_to_15_months =
- RoundTemporalOptions(15, CalendarUnit::MONTH, true, true, true);
- RoundTemporalOptions round_to_15_quarters =
- RoundTemporalOptions(15, CalendarUnit::QUARTER, true, true, true);
- RoundTemporalOptions round_to_15_years =
- RoundTemporalOptions(15, CalendarUnit::YEAR, true, true, true);
// Data for tests below was generaed via lubridate with the exception
// of week data because lubridate currently does not support rounding to
@@ -2867,13 +2981,13 @@ TEST_F(ScalarTemporalTest, TestFloorTemporalMultipleSinceGreaterUnit) {
"2020-01-01", "2019-12-31", "2019-12-16", "2009-12-31",
"2010-01-01", "2010-01-01", "2010-01-01", "2006-01-01",
"2005-12-31", "2008-12-16", "2008-12-16", "2012-01-01", null])";
- const char* floor_15_weeks =
- R"(["1969-12-29", "2000-01-03", "1899-01-02", "2033-04-18",
+ const char* floor_3_weeks =
+ R"(["1969-12-29", "2000-02-14", "1899-01-02", "2033-05-09",
"2019-12-30", "2019-12-30", "2019-12-30", "2010-01-04",
"2010-01-04", "2010-01-04", "2010-01-04", "2006-01-02",
- "2006-01-02", "2008-11-10", "2008-12-29", "2012-01-02", null])";
- const char* floor_15_weeks_sunday =
- R"(["1970-01-04", "2000-01-02", "1899-01-01", "2033-04-17",
+ "2006-01-02", "2008-12-22", "2008-12-29", "2012-01-02", null])";
+ const char* floor_3_weeks_sunday =
+ R"(["1970-01-04", "2000-02-13", "1899-01-01", "2033-05-08",
"2019-12-29", "2019-12-29", "2019-12-29", "2010-01-03",
"2010-01-03", "2010-01-03", "2010-01-03", "2006-01-01",
"2006-01-01", "2009-01-04", "2009-01-04", "2012-01-01", null])";
@@ -2903,16 +3017,114 @@ TEST_F(ScalarTemporalTest, TestFloorTemporalMultipleSinceGreaterUnit) {
CheckScalarUnary(op, unit, times, unit, floor_13_minute, &round_to_13_minutes);
CheckScalarUnary(op, unit, times, unit, floor_15_hour, &round_to_15_hours);
CheckScalarUnary(op, unit, times, unit, floor_15_day, &round_to_15_days);
- CheckScalarUnary(op, unit, times, unit, floor_15_weeks, &round_to_15_weeks);
- CheckScalarUnary(op, unit, times, unit, floor_15_weeks_sunday,
- &round_to_15_weeks_sunday);
+ CheckScalarUnary(op, unit, times, unit, floor_3_weeks, &round_to_3_weeks);
+ CheckScalarUnary(op, unit, times, unit, floor_3_weeks_sunday, &round_to_3_weeks_sunday);
CheckScalarUnary(op, unit, times, unit, floor_15_months, &round_to_15_months);
CheckScalarUnary(op, unit, times, unit, floor_15_quarters, &round_to_15_quarters);
CheckScalarUnary(op, unit, times, unit, floor_15_years, &round_to_15_years);
}
+TEST_F(ScalarTemporalTestMultipleSinceGreaterUnit, FloorZoned) {
+ std::string op = "floor_temporal";
+
+ // Data for tests below was generated via lubridate with the exception
+ // of week data because lubridate currently does not support rounding to
+ // multiple of week.
+ const char* floor_15_nanosecond =
+ R"(["1970-01-01 00:00:59.123456780", "2000-02-29 23:23:23.999999990",
+ "1899-01-01 00:59:20.001001000", "2033-05-18 03:33:20.000000000",
+ "2020-01-01 01:05:05.001000000", "2019-12-31 02:10:10.002000000",
+ "2019-12-30 03:15:15.003000000", "2009-12-31 04:20:20.004132000",
+ "2010-01-01 05:25:25.005321000", "2010-01-03 06:30:30.006163000",
+ "2010-01-04 07:35:35.000000000", "2006-01-01 08:40:40.000000000",
+ "2005-12-31 09:45:45.000000000", "2008-12-28 00:00:00.000000000",
+ "2008-12-29 00:00:00.000000000", "2012-01-01 01:02:03.000000000", null])";
+ const char* floor_15_microsecond =
+ R"(["1970-01-01 00:00:59.123450", "2000-02-29 23:23:23.999990",
+ "1899-01-01 00:59:20.001000", "2033-05-18 03:33:20.000000",
+ "2020-01-01 01:05:05.001000", "2019-12-31 02:10:10.002000",
+ "2019-12-30 03:15:15.003000", "2009-12-31 04:20:20.004120",
+ "2010-01-01 05:25:25.005315", "2010-01-03 06:30:30.006150",
+ "2010-01-04 07:35:35.000000", "2006-01-01 08:40:40.000000",
+ "2005-12-31 09:45:45.000000", "2008-12-28 00:00:00.000000",
+ "2008-12-29 00:00:00.000000", "2012-01-01 01:02:03.000000", null])";
+ const char* floor_15_millisecond =
+ R"(["1970-01-01 00:00:59.120", "2000-02-29 23:23:23.990",
+ "1899-01-01 00:59:20.000", "2033-05-18 03:33:20.000",
+ "2020-01-01 01:05:05.000", "2019-12-31 02:10:10.000",
+ "2019-12-30 03:15:15.000", "2009-12-31 04:20:20.000",
+ "2010-01-01 05:25:25.000", "2010-01-03 06:30:30.000",
+ "2010-01-04 07:35:35.000", "2006-01-01 08:40:40.000",
+ "2005-12-31 09:45:45.000", "2008-12-28 00:00:00.000",
+ "2008-12-29 00:00:00.000", "2012-01-01 01:02:03.000", null])";
+ const char* floor_13_second = R"([
+ "1970-01-01 00:00:52", "2000-02-29 23:23:13", "1899-01-01 00:59:13", "2033-05-18 03:33:13",
+ "2020-01-01 01:05:00", "2019-12-31 02:10:00", "2019-12-30 03:15:13", "2009-12-31 04:20:13",
+ "2010-01-01 05:25:13", "2010-01-03 06:30:26", "2010-01-04 07:35:26", "2006-01-01 08:40:39",
+ "2005-12-31 09:45:39", "2008-12-28 00:00:00", "2008-12-29 00:00:00", "2012-01-01 01:02:00", null])";
+ const char* floor_13_minute = R"([
+ "1969-12-31 23:56:00", "2000-02-29 23:22:00", "1899-01-01 00:52:00", "2033-05-18 03:30:00",
+ "2020-01-01 00:56:00", "2019-12-31 02:09:00", "2019-12-30 03:09:00", "2009-12-31 04:09:00",
+ "2010-01-01 05:22:00", "2010-01-03 06:30:00", "2010-01-04 07:30:00", "2006-01-01 08:30:00",
+ "2005-12-31 09:43:00", "2008-12-27 23:56:00", "2008-12-28 23:56:00", "2012-01-01 00:56:00", null])";
+ const char* floor_15_hour = R"([
+ "1969-12-31 14:30:00", "2000-02-29 13:30:00", "1898-12-31 15:00:00", "2033-05-17 14:30:00",
+ "2019-12-31 13:30:00", "2019-12-30 13:30:00", "2019-12-29 13:30:00", "2009-12-30 13:30:00",
+ "2010-01-01 04:30:00", "2010-01-03 04:30:00", "2010-01-04 04:30:00", "2006-01-01 04:30:00",
+ "2005-12-31 04:30:00", "2008-12-27 13:30:00", "2008-12-28 13:30:00", "2011-12-31 13:30:00", null])";
+ const char* floor_15_day = R"([
+ "1969-12-31 14:30:00", "2000-02-29 13:30:00", "1898-12-31 15:00:00", "2033-05-15 14:30:00",
+ "2019-12-31 13:30:00", "2019-12-30 13:30:00", "2019-12-15 13:30:00", "2009-12-30 13:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2005-12-31 13:30:00",
+ "2005-12-30 13:30:00", "2008-12-15 13:30:00", "2008-12-15 13:30:00", "2011-12-31 13:30:00", null])";
+ const char* floor_3_weeks = R"([
+ "1969-12-28 14:30:00", "2000-02-13 13:30:00", "1899-01-01 15:00:00", "2033-05-08 14:30:00",
+ "2019-12-29 13:30:00", "2019-12-29 13:30:00", "2019-12-29 13:30:00", "2010-01-03 13:30:00",
+ "2010-01-03 13:30:00", "2010-01-03 13:30:00", "2010-01-03 13:30:00", "2006-01-01 13:30:00",
+ "2006-01-01 13:30:00", "2008-12-21 13:30:00", "2008-12-28 13:30:00", "2012-01-01 13:30:00", null])";
+ const char* floor_3_weeks_sunday = R"([
+ "1970-01-03 14:30:00", "2000-03-04 13:30:00", "1898-12-31 15:00:00", "2033-05-07 14:30:00",
+ "2019-12-28 13:30:00", "2019-12-28 13:30:00", "2019-12-28 13:30:00", "2010-01-02 13:30:00",
+ "2010-01-02 13:30:00", "2010-01-02 13:30:00", "2010-01-02 13:30:00", "2005-12-31 13:30:00",
+ "2005-12-31 13:30:00", "2009-01-03 13:30:00", "2009-01-03 13:30:00", "2011-12-31 13:30:00", null])";
+ const char* floor_5_months = R"([
+ "1969-12-31 14:30:00", "1999-12-31 13:30:00", "1898-12-31 15:00:00", "2032-12-31 13:30:00",
+ "2019-12-31 13:30:00", "2019-10-31 13:30:00", "2019-10-31 13:30:00", "2009-10-31 13:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2005-12-31 13:30:00",
+ "2005-10-31 13:30:00", "2008-10-31 13:30:00", "2008-10-31 13:30:00", "2011-12-31 13:30:00", null])";
+ const char* floor_3_quarters = R"([
+ "1969-12-31 14:30:00", "1999-12-31 13:30:00", "1898-12-31 15:00:00", "2032-12-31 13:30:00",
+ "2019-12-31 13:30:00", "2019-09-30 14:30:00", "2019-09-30 14:30:00", "2009-09-30 14:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2005-12-31 13:30:00",
+ "2005-09-30 14:30:00", "2008-09-30 14:30:00", "2008-09-30 14:30:00", "2011-12-31 13:30:00", null])";
+ const char* floor_15_years = R"([
+ "1964-12-31 14:30:00", "1994-12-31 13:30:00", "1889-12-31 14:34:12", "2024-12-31 13:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "1994-12-31 13:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "1994-12-31 13:30:00",
+ "1994-12-31 13:30:00", "1994-12-31 13:30:00", "1994-12-31 13:30:00", "2009-12-31 13:30:00", null])";
+
+ // Australia/Broken_Hill timezone is defined as UTC+9:30 and UTC+10:30 during DST.
+ // DST runs from first Sunday in October to first Sunday in April.
+ auto unit = timestamp(TimeUnit::NANO, "Australia/Broken_Hill");
+ CheckScalarUnary(op, unit, times, unit, floor_15_nanosecond, &round_to_15_nanoseconds);
+ CheckScalarUnary(op, unit, times, unit, floor_15_microsecond,
+ &round_to_15_microseconds);
+ CheckScalarUnary(op, unit, times, unit, floor_15_millisecond,
+ &round_to_15_milliseconds);
+ CheckScalarUnary(op, unit, times, unit, floor_13_second, &round_to_13_seconds);
+ CheckScalarUnary(op, unit, times, unit, floor_13_minute, &round_to_13_minutes);
+ CheckScalarUnary(op, unit, times, unit, floor_15_hour, &round_to_15_hours);
+ CheckScalarUnary(op, unit, times, unit, floor_15_day, &round_to_15_days);
+ CheckScalarUnary(op, unit, times, unit, floor_3_weeks, &round_to_3_weeks);
+ CheckScalarUnary(op, unit, times, unit, floor_3_weeks_sunday, &round_to_3_weeks_sunday);
+ CheckScalarUnary(op, unit, times, unit, floor_5_months, &round_to_5_months);
+ CheckScalarUnary(op, unit, times, unit, floor_3_quarters, &round_to_3_quarters);
+ CheckScalarUnary(op, unit, times, unit, floor_15_years, &round_to_15_years);
+}
+
TEST_F(ScalarTemporalTest, TestRoundTemporal) {
std::string op = "round_temporal";
+
const char* round_1_nanoseconds =
R"(["1970-01-01 00:00:59.123456789", "2000-02-29 23:23:23.999999999",
"1899-01-01 00:59:20.001001001", "2033-05-18 03:33:20.000000000",
@@ -3123,32 +3335,8 @@ TEST_F(ScalarTemporalTest, TestCeilFloorRoundTemporalBrussels) {
CheckScalarUnary("round_temporal", unit, times, unit, round_2_hours, &round_to_2_hours);
}
-TEST_F(ScalarTemporalTest, TestRoundTemporalMultipleSinceGreaterUnit) {
+TEST_F(ScalarTemporalTestMultipleSinceGreaterUnit, RoundUTC) {
std::string op = "round_temporal";
- RoundTemporalOptions round_to_15_nanoseconds =
- RoundTemporalOptions(15, CalendarUnit::NANOSECOND, true, true, true);
- RoundTemporalOptions round_to_15_microseconds =
- RoundTemporalOptions(15, CalendarUnit::MICROSECOND, true, true, true);
- RoundTemporalOptions round_to_15_milliseconds =
- RoundTemporalOptions(15, CalendarUnit::MILLISECOND, true, true, true);
- RoundTemporalOptions round_to_13_seconds =
- RoundTemporalOptions(13, CalendarUnit::SECOND, true, true, true);
- RoundTemporalOptions round_to_13_minutes =
- RoundTemporalOptions(13, CalendarUnit::MINUTE, true, true, true);
- RoundTemporalOptions round_to_15_hours =
- RoundTemporalOptions(15, CalendarUnit::HOUR, true, true, true);
- RoundTemporalOptions round_to_15_days =
- RoundTemporalOptions(15, CalendarUnit::DAY, true, true, true);
- RoundTemporalOptions round_to_15_weeks =
- RoundTemporalOptions(15, CalendarUnit::WEEK, true, true, true);
- RoundTemporalOptions round_to_15_weeks_sunday =
- RoundTemporalOptions(15, CalendarUnit::WEEK, false, true, true);
- RoundTemporalOptions round_to_5_months =
- RoundTemporalOptions(5, CalendarUnit::MONTH, true, true, true);
- RoundTemporalOptions round_to_15_quarters =
- RoundTemporalOptions(15, CalendarUnit::QUARTER, true, true, true);
- RoundTemporalOptions round_to_15_years =
- RoundTemporalOptions(15, CalendarUnit::YEAR, true, true, true);
// Data for tests below was generaed via lubridate with the exception
// of week data because lubridate currently does not support rounding to
@@ -3206,13 +3394,13 @@ TEST_F(ScalarTemporalTest, TestRoundTemporalMultipleSinceGreaterUnit) {
"2020-01-01", "2019-12-31", "2019-12-31", "2009-12-31",
"2010-01-01", "2010-01-01", "2010-01-01", "2006-01-01",
"2005-12-31", "2008-12-31", "2008-12-31", "2012-01-01", null])";
- const char* round_15_weeks =
- R"(["1969-12-29", "2000-04-17", "1899-01-02", "2033-04-18",
+ const char* round_3_weeks =
+ R"(["1969-12-29", "2000-03-06", "1899-01-02", "2033-05-09",
"2019-12-30", "2019-12-30", "2019-12-30", "2010-01-04",
"2010-01-04", "2010-01-04", "2010-01-04", "2006-01-02",
- "2006-01-02", "2008-11-10", "2008-12-29", "2012-01-02", null])";
- const char* round_15_weeks_sunday =
- R"(["1970-01-04", "2000-04-16", "1899-01-01", "2033-04-17",
+ "2006-01-02", "2008-12-22", "2008-12-29", "2012-01-02", null])";
+ const char* round_3_weeks_sunday =
+ R"(["1970-01-04", "2000-03-05", "1899-01-01", "2033-05-08",
"2019-12-29", "2019-12-29", "2019-12-29", "2010-01-03",
"2010-01-03", "2010-01-03", "2010-01-03", "2006-01-01",
"2006-01-01", "2009-01-04", "2009-01-04", "2012-01-01", null])";
@@ -3241,14 +3429,111 @@ TEST_F(ScalarTemporalTest, TestRoundTemporalMultipleSinceGreaterUnit) {
CheckScalarUnary(op, unit, times, unit, round_13_minute, &round_to_13_minutes);
CheckScalarUnary(op, unit, times, unit, round_15_hour, &round_to_15_hours);
CheckScalarUnary(op, unit, times, unit, round_15_day, &round_to_15_days);
- CheckScalarUnary(op, unit, times, unit, round_15_weeks, &round_to_15_weeks);
- CheckScalarUnary(op, unit, times, unit, round_15_weeks_sunday,
- &round_to_15_weeks_sunday);
+ CheckScalarUnary(op, unit, times, unit, round_3_weeks, &round_to_3_weeks);
+ CheckScalarUnary(op, unit, times, unit, round_3_weeks_sunday, &round_to_3_weeks_sunday);
CheckScalarUnary(op, unit, times, unit, round_5_months, &round_to_5_months);
CheckScalarUnary(op, unit, times, unit, round_15_quarters, &round_to_15_quarters);
CheckScalarUnary(op, unit, times, unit, round_15_years, &round_to_15_years);
}
+TEST_F(ScalarTemporalTestMultipleSinceGreaterUnit, RoundZoned) {
+ std::string op = "round_temporal";
+
+ // Data for tests below was generated via lubridate with the exception
+ // of week data because lubridate currently does not support rounding to
+ // multiple of week.
+ const char* round_15_nanosecond =
+ R"(["1970-01-01 00:00:59.123456795", "2000-02-29 23:23:24.000000005",
+ "1899-01-01 00:59:20.001001000", "2033-05-18 03:33:20.000000000",
+ "2020-01-01 01:05:05.001000000", "2019-12-31 02:10:10.002000000",
+ "2019-12-30 03:15:15.003000000", "2009-12-31 04:20:20.004132000",
+ "2010-01-01 05:25:25.005321000", "2010-01-03 06:30:30.006163000",
+ "2010-01-04 07:35:35.000000000", "2006-01-01 08:40:40.000000000",
+ "2005-12-31 09:45:45.000000000", "2008-12-28 00:00:00.000000000",
+ "2008-12-29 00:00:00.000000000", "2012-01-01 01:02:03.000000000", null])";
+ const char* round_15_microsecond =
+ R"(["1970-01-01 00:00:59.123450", "2000-02-29 23:23:24.000005",
+ "1899-01-01 00:59:20.001000", "2033-05-18 03:33:20.000000",
+ "2020-01-01 01:05:05.001000", "2019-12-31 02:10:10.002000",
+ "2019-12-30 03:15:15.003000", "2009-12-31 04:20:20.004135",
+ "2010-01-01 05:25:25.005315", "2010-01-03 06:30:30.006165",
+ "2010-01-04 07:35:35.000000", "2006-01-01 08:40:40.000000",
+ "2005-12-31 09:45:45.000000", "2008-12-28 00:00:00.000000",
+ "2008-12-29 00:00:00.000000", "2012-01-01 01:02:03.000000", null])";
+ const char* round_15_millisecond =
+ R"(["1970-01-01 00:00:59.120", "2000-02-29 23:23:24.005",
+ "1899-01-01 00:59:20.000", "2033-05-18 03:33:20.000",
+ "2020-01-01 01:05:05.000", "2019-12-31 02:10:10.000",
+ "2019-12-30 03:15:15.000", "2009-12-31 04:20:20.000",
+ "2010-01-01 05:25:25.000", "2010-01-03 06:30:30.000",
+ "2010-01-04 07:35:35.000", "2006-01-01 08:40:40.000",
+ "2005-12-31 09:45:45.000", "2008-12-28 00:00:00.000",
+ "2008-12-29 00:00:00.000", "2012-01-01 01:02:03.000", null])";
+ const char* round_13_second = R"([
+ "1970-01-01 00:01:05", "2000-02-29 23:23:26", "1899-01-01 00:59:26", "2033-05-18 03:33:26",
+ "2020-01-01 01:05:00", "2019-12-31 02:10:13", "2019-12-30 03:15:13", "2009-12-31 04:20:26",
+ "2010-01-01 05:25:26", "2010-01-03 06:30:26", "2010-01-04 07:35:39", "2006-01-01 08:40:39",
+ "2005-12-31 09:45:39", "2008-12-28 00:00:00", "2008-12-29 00:00:00", "2012-01-01 01:02:00", null])";
+ const char* round_13_minute = R"([
+ "1969-12-31 23:56:00", "2000-02-29 23:22:00", "1899-01-01 01:05:00", "2033-05-18 03:30:00",
+ "2020-01-01 01:09:00", "2019-12-31 02:09:00", "2019-12-30 03:09:00", "2009-12-31 04:22:00",
+ "2010-01-01 05:22:00", "2010-01-03 06:30:00", "2010-01-04 07:30:00", "2006-01-01 08:43:00",
+ "2005-12-31 09:43:00", "2008-12-27 23:56:00", "2008-12-28 23:56:00", "2012-01-01 00:56:00", null])";
+ const char* round_15_hour = R"([
+ "1970-01-01 05:30:00", "2000-03-01 04:30:00", "1899-01-01 06:00:00", "2033-05-18 05:30:00",
+ "2020-01-01 04:30:00", "2019-12-31 04:30:00", "2019-12-30 04:30:00", "2009-12-31 04:30:00",
+ "2010-01-01 04:30:00", "2010-01-03 04:30:00", "2010-01-04 04:30:00", "2006-01-01 04:30:00",
+ "2005-12-31 04:30:00", "2008-12-28 04:30:00", "2008-12-29 04:30:00", "2012-01-01 04:30:00", null])";
+ const char* round_15_day = R"([
+ "1969-12-31 14:30:00", "2000-02-29 13:30:00", "1898-12-31 15:00:00", "2033-05-15 14:30:00",
+ "2019-12-31 13:30:00", "2019-12-30 13:30:00", "2019-12-30 13:30:00", "2009-12-30 13:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2005-12-31 13:30:00",
+ "2005-12-30 13:30:00", "2008-12-30 13:30:00", "2008-12-30 13:30:00", "2011-12-31 13:30:00", null])";
+ const char* round_3_weeks = R"([
+ "1969-12-28 14:30:00", "2000-03-05 13:30:00", "1899-01-01 15:00:00", "2033-05-08 14:30:00",
+ "2019-12-29 13:30:00", "2019-12-29 13:30:00", "2019-12-29 13:30:00", "2010-01-03 13:30:00",
+ "2010-01-03 13:30:00", "2010-01-03 13:30:00", "2010-01-03 13:30:00", "2006-01-01 13:30:00",
+ "2006-01-01 13:30:00", "2008-12-21 13:30:00", "2008-12-28 13:30:00", "2012-01-01 13:30:00",null])";
+ const char* round_3_weeks_sunday = R"([
+ "1970-01-03 14:30:00", "2000-03-04 13:30:00", "1898-12-31 15:00:00", "2033-05-28 14:30:00",
+ "2019-12-28 13:30:00", "2019-12-28 13:30:00", "2019-12-28 13:30:00", "2010-01-02 13:30:00",
+ "2010-01-02 13:30:00", "2010-01-02 13:30:00", "2010-01-02 13:30:00", "2005-12-31 13:30:00",
+ "2005-12-31 13:30:00", "2009-01-03 13:30:00", "2009-01-03 13:30:00", "2011-12-31 13:30:00", null])";
+ const char* round_5_months = R"([
+ "1969-12-31 14:30:00", "1999-12-31 13:30:00", "1898-12-31 15:00:00", "2033-05-31 14:30:00",
+ "2019-12-31 13:30:00", "2019-10-31 13:30:00", "2019-10-31 13:30:00", "2009-10-31 13:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2005-12-31 13:30:00",
+ "2005-10-31 13:30:00", "2008-10-31 13:30:00", "2008-10-31 13:30:00", "2011-12-31 13:30:00", null])";
+ const char* round_3_quarters = R"([
+ "1969-12-31 14:30:00", "1999-12-31 13:30:00", "1898-12-31 15:00:00", "2033-09-30 14:30:00",
+ "2019-12-31 13:30:00", "2019-09-30 14:30:00", "2019-09-30 14:30:00", "2009-09-30 14:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2005-12-31 13:30:00",
+ "2005-09-30 14:30:00", "2008-09-30 14:30:00", "2008-09-30 14:30:00", "2011-12-31 13:30:00", null])";
+ const char* round_15_years = R"([
+ "1964-12-31 14:30:00", "1994-12-31 13:30:00", "1904-12-31 14:30:00", "2039-12-31 13:30:00",
+ "2024-12-31 13:30:00", "2024-12-31 13:30:00", "2024-12-31 13:30:00", "2009-12-31 13:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00",
+ "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", "2009-12-31 13:30:00", null])";
+
+ // Australia/Broken_Hill timezone is defined as UTC+9:30 and UTC+10:30 during DST.
+ // DST runs from first Sunday in October to first Sunday in April.
+ auto unit = timestamp(TimeUnit::NANO, "Australia/Broken_Hill");
+ CheckScalarUnary(op, unit, times, unit, round_15_nanosecond, &round_to_15_nanoseconds);
+ CheckScalarUnary(op, unit, times, unit, round_15_microsecond,
+ &round_to_15_microseconds);
+ CheckScalarUnary(op, unit, times, unit, round_15_millisecond,
+ &round_to_15_milliseconds);
+ CheckScalarUnary(op, unit, times, unit, round_13_second, &round_to_13_seconds);
+ CheckScalarUnary(op, unit, times, unit, round_13_minute, &round_to_13_minutes);
+ CheckScalarUnary(op, unit, times, unit, round_15_hour, &round_to_15_hours);
+ CheckScalarUnary(op, unit, times, unit, round_15_day, &round_to_15_days);
+ CheckScalarUnary(op, unit, times, unit, round_3_weeks, &round_to_3_weeks);
+ CheckScalarUnary(op, unit, times, unit, round_3_weeks_sunday, &round_to_3_weeks_sunday);
+ CheckScalarUnary(op, unit, times, unit, round_5_months, &round_to_5_months);
+ CheckScalarUnary(op, unit, times, unit, round_3_quarters, &round_to_3_quarters);
+ CheckScalarUnary(op, unit, times, unit, round_15_years, &round_to_15_years);
+}
+
TEST_F(ScalarTemporalTest, TestCeilFloorRoundTemporalKolkata) {
// Kolkata timezone was defined as UTC+5:21:10 from 1871 to 1906 when it changed to
// IST (UTC+05:30) without DST. This test is to check rounding is done in historical
diff --git a/cpp/src/arrow/compute/kernels/scalar_temporal_unary.cc b/cpp/src/arrow/compute/kernels/scalar_temporal_unary.cc
index 96b9390840..f8da1338b5 100644
--- a/cpp/src/arrow/compute/kernels/scalar_temporal_unary.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_temporal_unary.cc
@@ -706,14 +706,14 @@ year_month_day GetFlooredYmd(int64_t arg, const int multiple,
// covered here.
switch (options.unit) {
case compute::CalendarUnit::MONTH: {
- const auto m =
- static_cast<uint32_t>(ymd.month()) / options.multiple * options.multiple;
- return year_month_day(ymd.year() / 1 / 1) + months{m};
+ const auto m = (static_cast<uint32_t>(ymd.month()) - 1) / options.multiple *
+ options.multiple;
+ return year_month_day(ymd.year() / jan / 1) + months{m};
}
case compute::CalendarUnit::QUARTER: {
- const auto m = static_cast<uint32_t>(ymd.month()) / (options.multiple * 3) *
+ const auto m = (static_cast<uint32_t>(ymd.month()) - 1) / (options.multiple * 3) *
(options.multiple * 3);
- return year_month_day(ymd.year() / 1 / 1) + months{m};
+ return year_month_day(ymd.year() / jan / 1) + months{m};
}
default:
return ymd;
@@ -945,14 +945,16 @@ struct CeilTemporal {
year_month_day ymd = GetFlooredYmd<Duration, Localizer>(arg, options.multiple,
options, localizer_);
ymd += months{options.multiple};
- t = localizer_.ConvertDays(ymd.year() / ymd.month() / 1).time_since_epoch();
+ t = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(ymd.year() / ymd.month() / 1).time_since_epoch(), st);
break;
}
case compute::CalendarUnit::QUARTER: {
year_month_day ymd = GetFlooredYmd<Duration, Localizer>(arg, 3 * options.multiple,
options, localizer_);
ymd += months{3 * options.multiple};
- t = localizer_.ConvertDays(ymd.year() / ymd.month() / 1).time_since_epoch();
+ t = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(ymd.year() / ymd.month() / 1).time_since_epoch(), st);
break;
}
case compute::CalendarUnit::YEAR: {
@@ -960,7 +962,8 @@ struct CeilTemporal {
floor<days>(localizer_.template ConvertTimePoint<Duration>(arg)));
year y{(static_cast<int32_t>(ymd.year()) / options.multiple + 1) *
options.multiple};
- t = localizer_.ConvertDays(y / jan / 1).time_since_epoch();
+ t = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(y / jan / 1).time_since_epoch(), st);
break;
}
default:
@@ -1020,20 +1023,23 @@ struct FloorTemporal {
case compute::CalendarUnit::MONTH: {
year_month_day ymd = GetFlooredYmd<Duration, Localizer>(arg, options.multiple,
options, localizer_);
- t = localizer_.ConvertDays(ymd.year() / ymd.month() / 1).time_since_epoch();
+ t = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(ymd.year() / ymd.month() / 1).time_since_epoch(), st);
break;
}
case compute::CalendarUnit::QUARTER: {
year_month_day ymd = GetFlooredYmd<Duration, Localizer>(arg, 3 * options.multiple,
options, localizer_);
- t = localizer_.ConvertDays(ymd.year() / ymd.month() / 1).time_since_epoch();
+ t = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(ymd.year() / ymd.month() / 1).time_since_epoch(), st);
break;
}
case compute::CalendarUnit::YEAR: {
year_month_day ymd(
floor<days>(localizer_.template ConvertTimePoint<Duration>(arg)));
year y{(static_cast<int32_t>(ymd.year()) / options.multiple) * options.multiple};
- t = localizer_.ConvertDays(y / jan / 1).time_since_epoch();
+ t = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(y / jan / 1).time_since_epoch(), st);
break;
}
default:
@@ -1095,11 +1101,13 @@ struct RoundTemporal {
year_month_day ymd = GetFlooredYmd<Duration, Localizer>(arg, options.multiple,
options, localizer_);
- auto f = localizer_.ConvertDays(ymd.year() / ymd.month() / 1);
+ auto f = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(ymd.year() / ymd.month() / 1).time_since_epoch(), st);
ymd += months{options.multiple};
- auto c = localizer_.ConvertDays(ymd.year() / ymd.month() / 1);
+ auto c = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(ymd.year() / ymd.month() / 1).time_since_epoch(), st);
- t = (t0 - f >= c - t0) ? c.time_since_epoch() : f.time_since_epoch();
+ t = (t0.time_since_epoch() - f >= c - t0.time_since_epoch()) ? c : f;
break;
}
case compute::CalendarUnit::QUARTER: {
@@ -1107,21 +1115,25 @@ struct RoundTemporal {
year_month_day ymd = GetFlooredYmd<Duration, Localizer>(arg, 3 * options.multiple,
options, localizer_);
- auto f = localizer_.ConvertDays(ymd.year() / ymd.month() / 1);
+ auto f = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(ymd.year() / ymd.month() / 1).time_since_epoch(), st);
ymd += months{3 * options.multiple};
- auto c = localizer_.ConvertDays(ymd.year() / ymd.month() / 1);
+ auto c = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(ymd.year() / ymd.month() / 1).time_since_epoch(), st);
- t = (t0 - f >= c - t0) ? c.time_since_epoch() : f.time_since_epoch();
+ t = (t0.time_since_epoch() - f >= c - t0.time_since_epoch()) ? c : f;
break;
}
case compute::CalendarUnit::YEAR: {
auto t0 = localizer_.template ConvertTimePoint<Duration>(arg);
year_month_day ymd(floor<days>(t0));
year y{(static_cast<int32_t>(ymd.year()) / options.multiple) * options.multiple};
- auto f = localizer_.ConvertDays(y / jan / 1);
- auto c = localizer_.ConvertDays((y + years{options.multiple}) / jan / 1);
+ auto f = localizer_.template ConvertLocalToSys<Duration>(
+ local_days(y / jan / 1).time_since_epoch(), st);
+ auto c = localizer_.template ConvertLocalToSys<Duration>(
+ local_days((y + years{options.multiple}) / jan / 1).time_since_epoch(), st);
- t = (t0 - f >= c - t0) ? c.time_since_epoch() : f.time_since_epoch();
+ t = (t0.time_since_epoch() - f >= c - t0.time_since_epoch()) ? c : f;
break;
}
default: