@@ -38,14 +38,15 @@ use serde::ser::SerializeStruct;
38
38
use serde:: { Deserialize , Serialize } ;
39
39
use serde_bytes:: ByteBuf ;
40
40
use serde_json:: { Map as JsonMap , Number , Value as JsonValue } ;
41
+ use timestamp:: nanoseconds_to_datetime;
41
42
use uuid:: Uuid ;
42
43
43
44
use super :: datatypes:: { PrimitiveType , Type } ;
44
45
use crate :: error:: Result ;
45
46
use crate :: spec:: values:: date:: { date_from_naive_date, days_to_date, unix_epoch} ;
46
47
use crate :: spec:: values:: time:: microseconds_to_time;
47
48
use crate :: spec:: values:: timestamp:: microseconds_to_datetime;
48
- use crate :: spec:: values:: timestamptz:: microseconds_to_datetimetz;
49
+ use crate :: spec:: values:: timestamptz:: { microseconds_to_datetimetz, nanoseconds_to_datetimetz } ;
49
50
use crate :: spec:: MAX_DECIMAL_PRECISION ;
50
51
use crate :: { ensure_data_valid, Error , ErrorKind } ;
51
52
@@ -326,6 +327,12 @@ impl Display for Datum {
326
327
( PrimitiveType :: Timestamptz , PrimitiveLiteral :: Long ( val) ) => {
327
328
write ! ( f, "{}" , microseconds_to_datetimetz( * val) )
328
329
}
330
+ ( PrimitiveType :: TimestampNs , PrimitiveLiteral :: Long ( val) ) => {
331
+ write ! ( f, "{}" , nanoseconds_to_datetime( * val) )
332
+ }
333
+ ( PrimitiveType :: TimestamptzNs , PrimitiveLiteral :: Long ( val) ) => {
334
+ write ! ( f, "{}" , nanoseconds_to_datetimetz( * val) )
335
+ }
329
336
( _, PrimitiveLiteral :: String ( val) ) => write ! ( f, r#""{}""# , val) ,
330
337
( PrimitiveType :: Uuid , PrimitiveLiteral :: UInt128 ( val) ) => {
331
338
write ! ( f, "{}" , Uuid :: from_u128( * val) )
@@ -401,6 +408,12 @@ impl Datum {
401
408
PrimitiveType :: Timestamptz => {
402
409
PrimitiveLiteral :: Long ( i64:: from_le_bytes ( bytes. try_into ( ) ?) )
403
410
}
411
+ PrimitiveType :: TimestampNs => {
412
+ PrimitiveLiteral :: Long ( i64:: from_le_bytes ( bytes. try_into ( ) ?) )
413
+ }
414
+ PrimitiveType :: TimestamptzNs => {
415
+ PrimitiveLiteral :: Long ( i64:: from_le_bytes ( bytes. try_into ( ) ?) )
416
+ }
404
417
PrimitiveType :: String => {
405
418
PrimitiveLiteral :: String ( std:: str:: from_utf8 ( bytes) ?. to_string ( ) )
406
419
}
@@ -734,6 +747,23 @@ impl Datum {
734
747
}
735
748
}
736
749
750
+ /// Creates a timestamp from unix epoch in nanoseconds.
751
+ ///
752
+ /// Example:
753
+ ///
754
+ /// ```rust
755
+ /// use iceberg::spec::Datum;
756
+ /// let t = Datum::timestamp_nanos(1000);
757
+ ///
758
+ /// assert_eq!(&format!("{t}"), "1970-01-01 00:00:00.000001");
759
+ /// ```
760
+ pub fn timestamp_nanos ( value : i64 ) -> Self {
761
+ Self {
762
+ r#type : PrimitiveType :: TimestampNs ,
763
+ literal : PrimitiveLiteral :: Long ( value) ,
764
+ }
765
+ }
766
+
737
767
/// Creates a timestamp from [`DateTime`].
738
768
///
739
769
/// Example:
@@ -792,6 +822,23 @@ impl Datum {
792
822
}
793
823
}
794
824
825
+ /// Creates a timestamp with timezone from unix epoch in nanoseconds.
826
+ ///
827
+ /// Example:
828
+ ///
829
+ /// ```rust
830
+ /// use iceberg::spec::Datum;
831
+ /// let t = Datum::timestamptz_nanos(1000);
832
+ ///
833
+ /// assert_eq!(&format!("{t}"), "1970-01-01 00:00:00.000001 UTC");
834
+ /// ```
835
+ pub fn timestamptz_nanos ( value : i64 ) -> Self {
836
+ Self {
837
+ r#type : PrimitiveType :: TimestamptzNs ,
838
+ literal : PrimitiveLiteral :: Long ( value) ,
839
+ }
840
+ }
841
+
795
842
/// Creates a timestamp with timezone from [`DateTime`].
796
843
/// Example:
797
844
///
@@ -1805,6 +1852,18 @@ impl Literal {
1805
1852
. format ( "%Y-%m-%dT%H:%M:%S%.f+00:00" )
1806
1853
. to_string ( ) ,
1807
1854
) ) ,
1855
+ ( PrimitiveType :: TimestampNs , PrimitiveLiteral :: Long ( val) ) => Ok ( JsonValue :: String (
1856
+ timestamp:: nanoseconds_to_datetime ( val)
1857
+ . format ( "%Y-%m-%dT%H:%M:%S%.f" )
1858
+ . to_string ( ) ,
1859
+ ) ) ,
1860
+ ( PrimitiveType :: TimestamptzNs , PrimitiveLiteral :: Long ( val) ) => {
1861
+ Ok ( JsonValue :: String (
1862
+ timestamptz:: nanoseconds_to_datetimetz ( val)
1863
+ . format ( "%Y-%m-%dT%H:%M:%S%.f+00:00" )
1864
+ . to_string ( ) ,
1865
+ ) )
1866
+ }
1808
1867
( PrimitiveType :: String , PrimitiveLiteral :: String ( val) ) => {
1809
1868
Ok ( JsonValue :: String ( val. clone ( ) ) )
1810
1869
}
@@ -1958,6 +2017,10 @@ mod timestamp {
1958
2017
// This shouldn't fail until the year 262000
1959
2018
DateTime :: from_timestamp_micros ( micros) . unwrap ( ) . naive_utc ( )
1960
2019
}
2020
+
2021
+ pub ( crate ) fn nanoseconds_to_datetime ( nanos : i64 ) -> NaiveDateTime {
2022
+ DateTime :: from_timestamp_nanos ( nanos) . naive_utc ( )
2023
+ }
1961
2024
}
1962
2025
1963
2026
mod timestamptz {
@@ -1972,6 +2035,12 @@ mod timestamptz {
1972
2035
1973
2036
DateTime :: from_timestamp ( secs, rem as u32 * 1_000 ) . unwrap ( )
1974
2037
}
2038
+
2039
+ pub ( crate ) fn nanoseconds_to_datetimetz ( nanos : i64 ) -> DateTime < Utc > {
2040
+ let ( secs, rem) = ( nanos / 1_000_000_000 , nanos % 1_000_000_000 ) ;
2041
+
2042
+ DateTime :: from_timestamp ( secs, rem as u32 ) . unwrap ( )
2043
+ }
1975
2044
}
1976
2045
1977
2046
mod _serde {
0 commit comments