You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by xu...@apache.org on 2025/03/24 02:04:16 UTC

(iceberg-rust) branch main updated: Fix rounding of negative hour transform (#1128)

This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-rust.git


The following commit(s) were added to refs/heads/main by this push:
     new 1aa76cf1 Fix rounding of negative hour transform (#1128)
1aa76cf1 is described below

commit 1aa76cf16fce2410fe63ac5a16c1c1fed32960ad
Author: Fokko Driesprong <fo...@apache.org>
AuthorDate: Mon Mar 24 03:04:11 2025 +0100

    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)?
    -->
---
 bindings/python/tests/test_transform.py  | 10 ++++++++--
 crates/iceberg/src/transform/temporal.rs | 12 ++++++++----
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/bindings/python/tests/test_transform.py b/bindings/python/tests/test_transform.py
index 4a90df08..22397754 100644
--- a/bindings/python/tests/test_transform.py
+++ b/bindings/python/tests/test_transform.py
@@ -90,9 +90,15 @@ def test_day_transform():
 
 
 def test_hour_transform():
-    arr = pa.array([datetime(1970, 1, 1, 19, 1, 23), datetime(2000, 3, 1, 12, 1, 23)])
+    arr = pa.array(
+        [
+            datetime(1970, 1, 1, 19, 1, 23),
+            datetime(2000, 3, 1, 12, 1, 23),
+            datetime(22, 5, 1, 22, 1, 1),  # Negative
+        ]
+    )
     result = transform.hour(arr)
-    expected = pa.array([19, 264420], type=pa.int32())
+    expected = pa.array([19, 264420, -17072905], type=pa.int32())
     assert result == expected
 
 
diff --git a/crates/iceberg/src/transform/temporal.rs b/crates/iceberg/src/transform/temporal.rs
index 5dd4ab06..c88e5438 100644
--- a/crates/iceberg/src/transform/temporal.rs
+++ b/crates/iceberg/src/transform/temporal.rs
@@ -30,8 +30,10 @@ use super::TransformFunction;
 use crate::spec::{Datum, PrimitiveLiteral, PrimitiveType};
 use crate::{Error, ErrorKind, Result};
 
-/// Hour in one second.
-const HOUR_PER_SECOND: f64 = 1.0_f64 / 3600.0_f64;
+/// Microseconds in one hour.
+const MICROSECONDS_PER_HOUR: i64 = 3_600_000_000;
+/// Nanoseconds in one hour.
+const NANOSECONDS_PER_HOUR: i64 = 3_600_000_000_000;
 /// Year of unix epoch.
 const UNIX_EPOCH_YEAR: i32 = 1970;
 /// One second in micros.
@@ -335,12 +337,12 @@ pub struct Hour;
 impl Hour {
     #[inline]
     fn hour_timestamp_micro(v: i64) -> i32 {
-        (v as f64 / 1000.0 / 1000.0 * HOUR_PER_SECOND) as i32
+        (v / MICROSECONDS_PER_HOUR) as i32
     }
 
     #[inline]
     fn hour_timestamp_nano(v: i64) -> i32 {
-        (v as f64 / 1_000_000.0 / 1000.0 * HOUR_PER_SECOND) as i32
+        (v / NANOSECONDS_PER_HOUR) as i32
     }
 }
 
@@ -2761,9 +2763,11 @@ mod test {
         // Test TimestampMicrosecond
         test_timestamp_and_tz_transform("2017-12-01 18:00:00.00", &hour, Datum::int(420042));
         test_timestamp_and_tz_transform("1969-12-31 23:00:00.00", &hour, Datum::int(-1));
+        test_timestamp_and_tz_transform("0022-05-01 22:01:01.00", &hour, Datum::int(-17072905));
 
         // Test TimestampNanosecond
         test_timestamp_ns_and_tz_transform("2017-12-01 18:00:00.00", &hour, Datum::int(420042));
         test_timestamp_ns_and_tz_transform("1969-12-31 23:00:00.00", &hour, Datum::int(-1));
+        test_timestamp_ns_and_tz_transform("1900-05-01 22:01:01.00", &hour, Datum::int(-610705));
     }
 }