Skip to content

Commit 282b582

Browse files
authored
feat: add literal cast to date (#270)
1 parent 033fa2d commit 282b582

File tree

2 files changed

+55
-4
lines changed

2 files changed

+55
-4
lines changed

src/iceberg/expression/literal.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "iceberg/util/checked_cast.h"
2828
#include "iceberg/util/conversions.h"
2929
#include "iceberg/util/macros.h"
30+
#include "iceberg/util/temporal_util.h"
3031

3132
namespace iceberg {
3233

@@ -209,8 +210,10 @@ Result<Literal> LiteralCaster::CastFromTimestamp(
209210
auto timestamp_val = std::get<int64_t>(literal.value_);
210211

211212
switch (target_type->type_id()) {
212-
case TypeId::kDate:
213-
return NotImplemented("Cast from Timestamp to Date is not implemented yet");
213+
case TypeId::kDate: {
214+
ICEBERG_ASSIGN_OR_RAISE(auto days, TemporalUtils::ExtractDay(literal));
215+
return Literal::Date(std::get<int32_t>(days.value()));
216+
}
214217
case TypeId::kTimestampTz:
215218
return Literal::TimestampTz(timestamp_val);
216219
default:
@@ -224,8 +227,10 @@ Result<Literal> LiteralCaster::CastFromTimestampTz(
224227
auto micros = std::get<int64_t>(literal.value_);
225228

226229
switch (target_type->type_id()) {
227-
case TypeId::kDate:
228-
return NotImplemented("Cast from TimestampTz to Date is not implemented yet");
230+
case TypeId::kDate: {
231+
ICEBERG_ASSIGN_OR_RAISE(auto days, TemporalUtils::ExtractDay(literal));
232+
return Literal::Date(std::get<int32_t>(days.value()));
233+
}
229234
case TypeId::kTimestamp:
230235
return Literal::Timestamp(micros);
231236
default:

src/iceberg/test/literal_test.cc

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "iceberg/type.h"
2929
#include "matchers.h"
30+
#include "temporal_test_helper.h"
3031

3132
namespace iceberg {
3233

@@ -689,6 +690,51 @@ INSTANTIATE_TEST_SUITE_P(
689690
.source_literal = Literal::Long(42L),
690691
.target_type = timestamp_tz(),
691692
.expected_literal = Literal::TimestampTz(42L)},
693+
CastLiteralTestParam{
694+
.test_name = "TimestampToDate",
695+
.source_literal =
696+
Literal::Timestamp(TemporalTestHelper::CreateTimestamp({.year = 2021,
697+
.month = 6,
698+
.day = 1,
699+
.hour = 11,
700+
.minute = 43,
701+
.second = 20})),
702+
.target_type = date(),
703+
.expected_literal = Literal::Date(
704+
TemporalTestHelper::CreateDate({.year = 2021, .month = 6, .day = 1}))},
705+
CastLiteralTestParam{
706+
.test_name = "TimestampTzToDate",
707+
.source_literal = Literal::TimestampTz(
708+
TemporalTestHelper::CreateTimestampTz({.year = 2021,
709+
.month = 1,
710+
.day = 1,
711+
.hour = 7,
712+
.minute = 43,
713+
.second = 20,
714+
.tz_offset_minutes = 480})),
715+
.target_type = date(),
716+
.expected_literal = Literal::Date(
717+
TemporalTestHelper::CreateDate({.year = 2020, .month = 12, .day = 31}))},
718+
CastLiteralTestParam{.test_name = "EpochToDate",
719+
.source_literal = Literal::Timestamp(
720+
TemporalTestHelper::CreateTimestamp({.year = 1970,
721+
.month = 1,
722+
.day = 1,
723+
.hour = 0,
724+
.minute = 0,
725+
.second = 0})),
726+
.target_type = date(),
727+
.expected_literal = Literal::Date(0)},
728+
CastLiteralTestParam{.test_name = "TimestampBeforeEpochToDate",
729+
.source_literal = Literal::Timestamp(
730+
TemporalTestHelper::CreateTimestamp({.year = 1969,
731+
.month = 12,
732+
.day = 31,
733+
.hour = 23,
734+
.minute = 59,
735+
.second = 59})),
736+
.target_type = date(),
737+
.expected_literal = Literal::Date(-1)},
692738
// Float cast tests
693739
CastLiteralTestParam{.test_name = "FloatToDouble",
694740
.source_literal = Literal::Float(2.0f),

0 commit comments

Comments
 (0)