From c0d2517cae0e395cac697057c8882731831a0ebd Mon Sep 17 00:00:00 2001 From: Junwang Zhao Date: Tue, 21 Oct 2025 23:47:04 +0800 Subject: [PATCH 1/2] feat: add literal cast to date --- src/iceberg/expression/literal.cc | 13 +++++++++---- src/iceberg/test/literal_test.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/iceberg/expression/literal.cc b/src/iceberg/expression/literal.cc index aea719c84..a1222ff69 100644 --- a/src/iceberg/expression/literal.cc +++ b/src/iceberg/expression/literal.cc @@ -27,6 +27,7 @@ #include "iceberg/util/checked_cast.h" #include "iceberg/util/conversions.h" #include "iceberg/util/macros.h" +#include "iceberg/util/temporal_util.h" namespace iceberg { @@ -209,8 +210,10 @@ Result LiteralCaster::CastFromTimestamp( auto timestamp_val = std::get(literal.value_); switch (target_type->type_id()) { - case TypeId::kDate: - return NotImplemented("Cast from Timestamp to Date is not implemented yet"); + case TypeId::kDate: { + ICEBERG_ASSIGN_OR_RAISE(auto days, TemporalUtils::ExtractDay(literal)); + return Literal::Date(std::get(days.value())); + } case TypeId::kTimestampTz: return Literal::TimestampTz(timestamp_val); default: @@ -224,8 +227,10 @@ Result LiteralCaster::CastFromTimestampTz( auto micros = std::get(literal.value_); switch (target_type->type_id()) { - case TypeId::kDate: - return NotImplemented("Cast from TimestampTz to Date is not implemented yet"); + case TypeId::kDate: { + ICEBERG_ASSIGN_OR_RAISE(auto days, TemporalUtils::ExtractDay(literal)); + return Literal::Date(std::get(days.value())); + } case TypeId::kTimestamp: return Literal::Timestamp(micros); default: diff --git a/src/iceberg/test/literal_test.cc b/src/iceberg/test/literal_test.cc index 0dd291d5c..cd5bef72b 100644 --- a/src/iceberg/test/literal_test.cc +++ b/src/iceberg/test/literal_test.cc @@ -27,6 +27,7 @@ #include "iceberg/type.h" #include "matchers.h" +#include "temporal_test_helper.h" namespace iceberg { @@ -689,6 +690,31 @@ INSTANTIATE_TEST_SUITE_P( .source_literal = Literal::Long(42L), .target_type = timestamp_tz(), .expected_literal = Literal::TimestampTz(42L)}, + CastLiteralTestParam{ + .test_name = "TimestampToDate", + .source_literal = + Literal::Timestamp(TemporalTestHelper::CreateTimestamp({.year = 2021, + .month = 6, + .day = 1, + .hour = 11, + .minute = 43, + .second = 20})), + .target_type = date(), + .expected_literal = Literal::Date( + TemporalTestHelper::CreateDate({.year = 2021, .month = 6, .day = 1}))}, + CastLiteralTestParam{ + .test_name = "TimestampTzToDate", + .source_literal = Literal::TimestampTz( + TemporalTestHelper::CreateTimestampTz({.year = 2021, + .month = 1, + .day = 1, + .hour = 7, + .minute = 43, + .second = 20, + .tz_offset_minutes = 480})), + .target_type = date(), + .expected_literal = Literal::Date( + TemporalTestHelper::CreateDate({.year = 2020, .month = 12, .day = 31}))}, // Float cast tests CastLiteralTestParam{.test_name = "FloatToDouble", .source_literal = Literal::Float(2.0f), From 13bce28c4e7a6164e6b88e1a39ef4b3eea237df0 Mon Sep 17 00:00:00 2001 From: Junwang Zhao Date: Thu, 23 Oct 2025 08:44:29 +0800 Subject: [PATCH 2/2] fix: add a timestamp before UNIX epoch --- src/iceberg/test/literal_test.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/iceberg/test/literal_test.cc b/src/iceberg/test/literal_test.cc index cd5bef72b..ca2a40621 100644 --- a/src/iceberg/test/literal_test.cc +++ b/src/iceberg/test/literal_test.cc @@ -715,6 +715,26 @@ INSTANTIATE_TEST_SUITE_P( .target_type = date(), .expected_literal = Literal::Date( TemporalTestHelper::CreateDate({.year = 2020, .month = 12, .day = 31}))}, + CastLiteralTestParam{.test_name = "EpochToDate", + .source_literal = Literal::Timestamp( + TemporalTestHelper::CreateTimestamp({.year = 1970, + .month = 1, + .day = 1, + .hour = 0, + .minute = 0, + .second = 0})), + .target_type = date(), + .expected_literal = Literal::Date(0)}, + CastLiteralTestParam{.test_name = "TimestampBeforeEpochToDate", + .source_literal = Literal::Timestamp( + TemporalTestHelper::CreateTimestamp({.year = 1969, + .month = 12, + .day = 31, + .hour = 23, + .minute = 59, + .second = 59})), + .target_type = date(), + .expected_literal = Literal::Date(-1)}, // Float cast tests CastLiteralTestParam{.test_name = "FloatToDouble", .source_literal = Literal::Float(2.0f),