Skip to content

Commit 1aa76cf

Browse files
authored
Fix rounding of negative hour transform (#1128)
## Which issue does this PR close? <!-- We generally require a GitHub issue to be filed for all bug fixes and enhancements and this helps us generate change logs for our releases. You can link an issue to this PR using the GitHub syntax. For example `Closes #123` indicates that this PR will close issue #123. --> - Closes #. ## What changes are included in this PR? <!-- Provide a summary of the modifications in this PR. List the main changes such as new features, bug fixes, refactoring, or any other updates. --> ## Are these changes tested? <!-- Specify what test covers (unit test, integration test, etc.). If tests are not included in your PR, please explain why (for example, are they covered by existing tests)? -->
1 parent ac10ee4 commit 1aa76cf

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

bindings/python/tests/test_transform.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,15 @@ def test_day_transform():
9090

9191

9292
def test_hour_transform():
93-
arr = pa.array([datetime(1970, 1, 1, 19, 1, 23), datetime(2000, 3, 1, 12, 1, 23)])
93+
arr = pa.array(
94+
[
95+
datetime(1970, 1, 1, 19, 1, 23),
96+
datetime(2000, 3, 1, 12, 1, 23),
97+
datetime(22, 5, 1, 22, 1, 1), # Negative
98+
]
99+
)
94100
result = transform.hour(arr)
95-
expected = pa.array([19, 264420], type=pa.int32())
101+
expected = pa.array([19, 264420, -17072905], type=pa.int32())
96102
assert result == expected
97103

98104

crates/iceberg/src/transform/temporal.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ use super::TransformFunction;
3030
use crate::spec::{Datum, PrimitiveLiteral, PrimitiveType};
3131
use crate::{Error, ErrorKind, Result};
3232

33-
/// Hour in one second.
34-
const HOUR_PER_SECOND: f64 = 1.0_f64 / 3600.0_f64;
33+
/// Microseconds in one hour.
34+
const MICROSECONDS_PER_HOUR: i64 = 3_600_000_000;
35+
/// Nanoseconds in one hour.
36+
const NANOSECONDS_PER_HOUR: i64 = 3_600_000_000_000;
3537
/// Year of unix epoch.
3638
const UNIX_EPOCH_YEAR: i32 = 1970;
3739
/// One second in micros.
@@ -335,12 +337,12 @@ pub struct Hour;
335337
impl Hour {
336338
#[inline]
337339
fn hour_timestamp_micro(v: i64) -> i32 {
338-
(v as f64 / 1000.0 / 1000.0 * HOUR_PER_SECOND) as i32
340+
(v / MICROSECONDS_PER_HOUR) as i32
339341
}
340342

341343
#[inline]
342344
fn hour_timestamp_nano(v: i64) -> i32 {
343-
(v as f64 / 1_000_000.0 / 1000.0 * HOUR_PER_SECOND) as i32
345+
(v / NANOSECONDS_PER_HOUR) as i32
344346
}
345347
}
346348

@@ -2761,9 +2763,11 @@ mod test {
27612763
// Test TimestampMicrosecond
27622764
test_timestamp_and_tz_transform("2017-12-01 18:00:00.00", &hour, Datum::int(420042));
27632765
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));
27642767

27652768
// Test TimestampNanosecond
27662769
test_timestamp_ns_and_tz_transform("2017-12-01 18:00:00.00", &hour, Datum::int(420042));
27672770
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));
27682772
}
27692773
}

0 commit comments

Comments
 (0)