diff --git a/src/iceberg/test/eval_expr_test.cc b/src/iceberg/test/eval_expr_test.cc index 880f1ffb6..39cb2a973 100644 --- a/src/iceberg/test/eval_expr_test.cc +++ b/src/iceberg/test/eval_expr_test.cc @@ -161,7 +161,7 @@ TEST_F(BoundExpressionTest, YearTransform) { // Evaluate (2021) ICEBERG_UNWRAP_OR_FAIL(auto result, bound_transform->Evaluate(*struct_like)); EXPECT_FALSE(result.IsNull()); - EXPECT_EQ(std::get(result.value()), 2021); // Year value + EXPECT_EQ(std::get(result.value()), 2021 - 1970); // Year value } TEST_F(BoundExpressionTest, MonthTransform) { diff --git a/src/iceberg/test/transform_test.cc b/src/iceberg/test/transform_test.cc index 7f0514df4..47a1e87e6 100644 --- a/src/iceberg/test/transform_test.cc +++ b/src/iceberg/test/transform_test.cc @@ -459,7 +459,7 @@ INSTANTIATE_TEST_SUITE_P( .hour = 11, .minute = 43, .second = 20})), - .expected = Literal::Int(2021)}, + .expected = Literal::Int(2021 - 1970)}, TransformParam{ .str = "TimestampTz", // 2021-01-01T07:43:20+08:00, which is 2020-12-31T23:43:20Z @@ -472,12 +472,12 @@ INSTANTIATE_TEST_SUITE_P( .minute = 43, .second = 20, .tz_offset_minutes = 480})), - .expected = Literal::Int(2020)}, + .expected = Literal::Int(2020 - 1970)}, TransformParam{.str = "Date", .source_type = iceberg::date(), .source = Literal::Date(TemporalTestHelper::CreateDate( {.year = 2052, .month = 2, .day = 20})), - .expected = Literal::Int(2052)}), + .expected = Literal::Int(2052 - 1970)}), [](const ::testing::TestParamInfo& info) { return info.param.str; }); class MonthTransformTest : public ::testing::TestWithParam {}; @@ -2061,7 +2061,8 @@ TEST_F(TransformProjectStrictTest, YearStrictLessThan) { std::move(projected)); EXPECT_EQ(unbound_projected->op(), Expression::Operation::kLt); EXPECT_EQ(unbound_projected->literals().size(), 1); - EXPECT_EQ(std::get(unbound_projected->literals().front().value()), 2021); + EXPECT_EQ(std::get(unbound_projected->literals().front().value()), + 2021 - 1970); } TEST_F(TransformProjectStrictTest, YearStrictGreaterThanOrEqual) { @@ -2085,7 +2086,8 @@ TEST_F(TransformProjectStrictTest, YearStrictGreaterThanOrEqual) { std::move(projected)); EXPECT_EQ(unbound_projected->op(), Expression::Operation::kGt); EXPECT_EQ(unbound_projected->literals().size(), 1); - EXPECT_EQ(std::get(unbound_projected->literals().front().value()), 2020); + EXPECT_EQ(std::get(unbound_projected->literals().front().value()), + 2020 - 1970); } TEST_F(TransformProjectStrictTest, YearStrictNotEqual) { @@ -2109,7 +2111,8 @@ TEST_F(TransformProjectStrictTest, YearStrictNotEqual) { std::move(projected)); EXPECT_EQ(unbound_projected->op(), Expression::Operation::kNotEq); EXPECT_EQ(unbound_projected->literals().size(), 1); - EXPECT_EQ(std::get(unbound_projected->literals().front().value()), 2021); + EXPECT_EQ(std::get(unbound_projected->literals().front().value()), + 2021 - 1970); } TEST_F(TransformProjectStrictTest, MonthStrictLessThan) { @@ -2218,7 +2221,8 @@ TEST_F(TransformProjectStrictTest, YearStrictUpperBound) { std::move(projected)); EXPECT_EQ(unbound_projected->op(), Expression::Operation::kLt); EXPECT_EQ(unbound_projected->literals().size(), 1); - EXPECT_EQ(std::get(unbound_projected->literals().front().value()), 2018); + EXPECT_EQ(std::get(unbound_projected->literals().front().value()), + 2018 - 1970); } TEST_F(TransformProjectStrictTest, VoidStrictReturnsNull) { diff --git a/src/iceberg/transform.h b/src/iceberg/transform.h index 1044e264f..36da46d91 100644 --- a/src/iceberg/transform.h +++ b/src/iceberg/transform.h @@ -111,25 +111,25 @@ class ICEBERG_EXPORT Transform : public util::Formattable { /// \brief Creates a shared singleton instance of the Year transform. /// - /// Extracts the year portion from a date or timestamp. + /// Extracts the number of years from a date or timestamp since the epoch. /// \return A shared pointer to the Year transform. static std::shared_ptr Year(); /// \brief Creates a shared singleton instance of the Month transform. /// - /// Extracts the month portion from a date or timestamp. + /// Extracts the number of months from a date or timestamp since the epoch. /// \return A shared pointer to the Month transform. static std::shared_ptr Month(); /// \brief Creates a shared singleton instance of the Day transform. /// - /// Extracts the day portion from a date or timestamp. + /// Extracts the number of days from a date or timestamp since the epoch. /// \return A shared pointer to the Day transform. static std::shared_ptr Day(); /// \brief Creates a shared singleton instance of the Hour transform. /// - /// Extracts the hour portion from a timestamp. + /// Extracts the number of hours from a timestamp since the epoch. /// \return A shared pointer to the Hour transform. static std::shared_ptr Hour(); diff --git a/src/iceberg/transform_function.h b/src/iceberg/transform_function.h index c8670824c..a44e6c7a1 100644 --- a/src/iceberg/transform_function.h +++ b/src/iceberg/transform_function.h @@ -100,7 +100,8 @@ class ICEBERG_EXPORT TruncateTransform : public TransformFunction { int32_t width_; }; -/// \brief Year transform that extracts the year component from timestamp inputs. +/// \brief Year transform that extracts the number of years from timestamp inputs since +/// the epoch. class ICEBERG_EXPORT YearTransform : public TransformFunction { public: /// \param source_type Must be a timestamp type. @@ -119,7 +120,8 @@ class ICEBERG_EXPORT YearTransform : public TransformFunction { std::shared_ptr const& source_type); }; -/// \brief Month transform that extracts the month component from timestamp inputs. +/// \brief Month transform that extracts the number of months from timestamp inputs since +/// the epoch. class ICEBERG_EXPORT MonthTransform : public TransformFunction { public: /// \param source_type Must be a timestamp type. @@ -138,7 +140,8 @@ class ICEBERG_EXPORT MonthTransform : public TransformFunction { std::shared_ptr const& source_type); }; -/// \brief Day transform that extracts the day of the month from timestamp inputs. +/// \brief Day transform that extracts the number of days from timestamp inputs since the +/// epoch. class ICEBERG_EXPORT DayTransform : public TransformFunction { public: /// \param source_type Must be a timestamp type. @@ -161,7 +164,8 @@ class ICEBERG_EXPORT DayTransform : public TransformFunction { std::shared_ptr const& source_type); }; -/// \brief Hour transform that extracts the hour component from timestamp inputs. +/// \brief Hour transform that extracts the number of hours from timestamp inputs since +/// the epoch. class ICEBERG_EXPORT HourTransform : public TransformFunction { public: /// \param source_type Must be a timestamp type. diff --git a/src/iceberg/util/temporal_util.cc b/src/iceberg/util/temporal_util.cc index 0112e4925..05aafb961 100644 --- a/src/iceberg/util/temporal_util.cc +++ b/src/iceberg/util/temporal_util.cc @@ -68,14 +68,14 @@ template <> Result ExtractYearImpl(const Literal& literal) { auto value = std::get(literal.value()); auto ymd = DateToYmd(value); - return Literal::Int(static_cast(ymd.year())); + return Literal::Int((ymd.year() - kEpochYmd.year()).count()); } template <> Result ExtractYearImpl(const Literal& literal) { auto value = std::get(literal.value()); auto ymd = TimestampToYmd(value); - return Literal::Int(static_cast(ymd.year())); + return Literal::Int((ymd.year() - kEpochYmd.year()).count()); } template <>