Skip to content

Commit 7eae524

Browse files
authored
Fix hour transform (#1146)
## Which issue does this PR close? Seems like we're rounding towards zero by default by Rust. While we want to `floor` the value. Checked against the reference implementation: ![image](https://github.com/user-attachments/assets/48f8ac2e-c124-4b53-9888-40e3fa7e6cd2)
1 parent 4efcd86 commit 7eae524

File tree

2 files changed

+35
-48
lines changed

2 files changed

+35
-48
lines changed

bindings/python/tests/test_transform.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def test_hour_transform():
9898
]
9999
)
100100
result = transform.hour(arr)
101-
expected = pa.array([19, 264420, -17072905], type=pa.int32())
101+
expected = pa.array([19, 264420, -17072906], type=pa.int32())
102102
assert result == expected
103103

104104

crates/iceberg/src/transform/temporal.rs

Lines changed: 34 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -337,12 +337,12 @@ pub struct Hour;
337337
impl Hour {
338338
#[inline]
339339
fn hour_timestamp_micro(v: i64) -> i32 {
340-
(v / MICROSECONDS_PER_HOUR) as i32
340+
v.div_euclid(MICROSECONDS_PER_HOUR) as i32
341341
}
342342

343343
#[inline]
344344
fn hour_timestamp_nano(v: i64) -> i32 {
345-
(v / NANOSECONDS_PER_HOUR) as i32
345+
v.div_euclid(NANOSECONDS_PER_HOUR) as i32
346346
}
347347
}
348348

@@ -2390,18 +2390,8 @@ mod test {
23902390
transform: &BoxedTransformFunction,
23912391
expect: Datum,
23922392
) {
2393-
let timestamp = Datum::timestamp_micros(
2394-
NaiveDateTime::parse_from_str(time, "%Y-%m-%d %H:%M:%S.%f")
2395-
.unwrap()
2396-
.and_utc()
2397-
.timestamp_micros(),
2398-
);
2399-
let timestamp_tz = Datum::timestamptz_micros(
2400-
NaiveDateTime::parse_from_str(time, "%Y-%m-%d %H:%M:%S.%f")
2401-
.unwrap()
2402-
.and_utc()
2403-
.timestamp_micros(),
2404-
);
2393+
let timestamp = Datum::timestamp_from_str(time).unwrap();
2394+
let timestamp_tz = Datum::timestamptz_from_str(time.to_owned() + " +00:00").unwrap();
24052395
let res = transform.transform_literal(&timestamp).unwrap().unwrap();
24062396
assert_eq!(res, expect);
24072397
let res = transform.transform_literal(&timestamp_tz).unwrap().unwrap();
@@ -2432,20 +2422,8 @@ mod test {
24322422
transform: &BoxedTransformFunction,
24332423
expect: Datum,
24342424
) {
2435-
let timestamp_ns = Datum::timestamp_nanos(
2436-
NaiveDateTime::parse_from_str(time, "%Y-%m-%d %H:%M:%S.%f")
2437-
.unwrap()
2438-
.and_utc()
2439-
.timestamp_nanos_opt()
2440-
.unwrap(),
2441-
);
2442-
let timestamptz_ns = Datum::timestamptz_nanos(
2443-
NaiveDateTime::parse_from_str(time, "%Y-%m-%d %H:%M:%S.%f")
2444-
.unwrap()
2445-
.and_utc()
2446-
.timestamp_nanos_opt()
2447-
.unwrap(),
2448-
);
2425+
let timestamp_ns = Datum::timestamp_from_str(time).unwrap();
2426+
let timestamptz_ns = Datum::timestamptz_from_str(time.to_owned() + " +00:00").unwrap();
24492427
let res = transform.transform_literal(&timestamp_ns).unwrap().unwrap();
24502428
assert_eq!(res, expect);
24512429
let res = transform
@@ -2485,15 +2463,15 @@ mod test {
24852463
&year,
24862464
Datum::int(1970 - super::UNIX_EPOCH_YEAR),
24872465
);
2488-
test_timestamp_and_tz_transform("1969-01-01 00:00:00.00", &year, Datum::int(-1));
2466+
test_timestamp_and_tz_transform("1969-01-01T00:00:00.000000", &year, Datum::int(-1));
24892467

24902468
// Test TimestampNanosecond
24912469
test_timestamp_ns_and_tz_transform_using_i64(
24922470
186280000000,
24932471
&year,
24942472
Datum::int(1970 - super::UNIX_EPOCH_YEAR),
24952473
);
2496-
test_timestamp_ns_and_tz_transform("1969-01-01 00:00:00.00", &year, Datum::int(-1));
2474+
test_timestamp_ns_and_tz_transform("1969-01-01T00:00:00.000000", &year, Datum::int(-1));
24972475
}
24982476

24992477
#[test]
@@ -2584,21 +2562,21 @@ mod test {
25842562
&month,
25852563
Datum::int((1970 - super::UNIX_EPOCH_YEAR) * 12),
25862564
);
2587-
test_timestamp_and_tz_transform("1969-12-01 23:00:00.00", &month, Datum::int(-1));
2588-
test_timestamp_and_tz_transform("2017-12-01 00:00:00.00", &month, Datum::int(575));
2589-
test_timestamp_and_tz_transform("1970-01-01 00:00:00.00", &month, Datum::int(0));
2590-
test_timestamp_and_tz_transform("1969-12-31 00:00:00.00", &month, Datum::int(-1));
2565+
test_timestamp_and_tz_transform("1969-12-01T23:00:00.000000", &month, Datum::int(-1));
2566+
test_timestamp_and_tz_transform("2017-12-01T00:00:00.000000", &month, Datum::int(575));
2567+
test_timestamp_and_tz_transform("1970-01-01T00:00:00.000000", &month, Datum::int(0));
2568+
test_timestamp_and_tz_transform("1969-12-31T00:00:00.000000", &month, Datum::int(-1));
25912569

25922570
// Test TimestampNanosecond
25932571
test_timestamp_ns_and_tz_transform_using_i64(
25942572
186280000000,
25952573
&month,
25962574
Datum::int((1970 - super::UNIX_EPOCH_YEAR) * 12),
25972575
);
2598-
test_timestamp_ns_and_tz_transform("1969-12-01 23:00:00.00", &month, Datum::int(-1));
2599-
test_timestamp_ns_and_tz_transform("2017-12-01 00:00:00.00", &month, Datum::int(575));
2600-
test_timestamp_ns_and_tz_transform("1970-01-01 00:00:00.00", &month, Datum::int(0));
2601-
test_timestamp_ns_and_tz_transform("1969-12-31 00:00:00.00", &month, Datum::int(-1));
2576+
test_timestamp_ns_and_tz_transform("1969-12-01T23:00:00.000000", &month, Datum::int(-1));
2577+
test_timestamp_ns_and_tz_transform("2017-12-01T00:00:00.000000", &month, Datum::int(575));
2578+
test_timestamp_ns_and_tz_transform("1970-01-01T00:00:00.000000", &month, Datum::int(0));
2579+
test_timestamp_ns_and_tz_transform("1969-12-31T00:00:00.000000", &month, Datum::int(-1));
26022580
}
26032581

26042582
#[test]
@@ -2689,12 +2667,12 @@ mod test {
26892667
// Test TimestampMicrosecond
26902668
test_timestamp_and_tz_transform_using_i64(1512151975038194, &day, Datum::date(17501));
26912669
test_timestamp_and_tz_transform_using_i64(-115200000000, &day, Datum::date(-2));
2692-
test_timestamp_and_tz_transform("2017-12-01 10:30:42.123", &day, Datum::date(17501));
2670+
test_timestamp_and_tz_transform("2017-12-01T10:30:42.123000", &day, Datum::date(17501));
26932671

26942672
// Test TimestampNanosecond
26952673
test_timestamp_ns_and_tz_transform_using_i64(1512151975038194, &day, Datum::date(17));
26962674
test_timestamp_ns_and_tz_transform_using_i64(-115200000000, &day, Datum::date(-1));
2697-
test_timestamp_ns_and_tz_transform("2017-12-01 10:30:42.123", &day, Datum::date(17501));
2675+
test_timestamp_ns_and_tz_transform("2017-12-01T10:30:42.123000", &day, Datum::date(17501));
26982676
}
26992677

27002678
#[test]
@@ -2760,14 +2738,23 @@ mod test {
27602738
fn test_transform_hours_literal() {
27612739
let hour = Box::new(super::Hour) as BoxedTransformFunction;
27622740

2763-
// Test TimestampMicrosecond
2764-
test_timestamp_and_tz_transform("2017-12-01 18:00:00.00", &hour, Datum::int(420042));
2765-
test_timestamp_and_tz_transform("1969-12-31 23:00:00.00", &hour, Datum::int(-1));
2766-
test_timestamp_and_tz_transform("0022-05-01 22:01:01.00", &hour, Datum::int(-17072905));
2741+
test_timestamp_and_tz_transform("2017-12-01T18:00:00.000000", &hour, Datum::int(420042));
2742+
test_timestamp_and_tz_transform("1970-01-01T22:01:01.000000", &hour, Datum::int(22));
2743+
test_timestamp_and_tz_transform("1969-12-31T23:00:00.000000", &hour, Datum::int(-1));
2744+
test_timestamp_and_tz_transform("1969-12-31T22:01:01.000000", &hour, Datum::int(-2));
2745+
test_timestamp_and_tz_transform("0022-05-01T22:01:01.000000", &hour, Datum::int(-17072906));
27672746

27682747
// Test TimestampNanosecond
2769-
test_timestamp_ns_and_tz_transform("2017-12-01 18:00:00.00", &hour, Datum::int(420042));
2770-
test_timestamp_ns_and_tz_transform("1969-12-31 23:00:00.00", &hour, Datum::int(-1));
2771-
test_timestamp_ns_and_tz_transform("1900-05-01 22:01:01.00", &hour, Datum::int(-610705));
2748+
test_timestamp_ns_and_tz_transform(
2749+
"2017-12-01T18:00:00.0000000000",
2750+
&hour,
2751+
Datum::int(420042),
2752+
);
2753+
test_timestamp_ns_and_tz_transform("1969-12-31T23:00:00.0000000000", &hour, Datum::int(-1));
2754+
test_timestamp_ns_and_tz_transform(
2755+
"1900-05-01T22:01:01.0000000000",
2756+
&hour,
2757+
Datum::int(-610706),
2758+
);
27722759
}
27732760
}

0 commit comments

Comments
 (0)