@@ -38,14 +38,15 @@ use serde::ser::SerializeStruct;
3838use serde:: { Deserialize , Serialize } ;
3939use serde_bytes:: ByteBuf ;
4040use serde_json:: { Map as JsonMap , Number , Value as JsonValue } ;
41+ use timestamp:: nanoseconds_to_datetime;
4142use uuid:: Uuid ;
4243
4344use super :: datatypes:: { PrimitiveType , Type } ;
4445use crate :: error:: Result ;
4546use crate :: spec:: values:: date:: { date_from_naive_date, days_to_date, unix_epoch} ;
4647use crate :: spec:: values:: time:: microseconds_to_time;
4748use 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 } ;
4950use crate :: spec:: MAX_DECIMAL_PRECISION ;
5051use crate :: { ensure_data_valid, Error , ErrorKind } ;
5152
@@ -326,6 +327,12 @@ impl Display for Datum {
326327 ( PrimitiveType :: Timestamptz , PrimitiveLiteral :: Long ( val) ) => {
327328 write ! ( f, "{}" , microseconds_to_datetimetz( * val) )
328329 }
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+ }
329336 ( _, PrimitiveLiteral :: String ( val) ) => write ! ( f, r#""{}""# , val) ,
330337 ( PrimitiveType :: Uuid , PrimitiveLiteral :: UInt128 ( val) ) => {
331338 write ! ( f, "{}" , Uuid :: from_u128( * val) )
@@ -401,6 +408,12 @@ impl Datum {
401408 PrimitiveType :: Timestamptz => {
402409 PrimitiveLiteral :: Long ( i64:: from_le_bytes ( bytes. try_into ( ) ?) )
403410 }
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+ }
404417 PrimitiveType :: String => {
405418 PrimitiveLiteral :: String ( std:: str:: from_utf8 ( bytes) ?. to_string ( ) )
406419 }
@@ -734,6 +747,23 @@ impl Datum {
734747 }
735748 }
736749
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+
737767 /// Creates a timestamp from [`DateTime`].
738768 ///
739769 /// Example:
@@ -792,6 +822,23 @@ impl Datum {
792822 }
793823 }
794824
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+
795842 /// Creates a timestamp with timezone from [`DateTime`].
796843 /// Example:
797844 ///
@@ -1805,6 +1852,18 @@ impl Literal {
18051852 . format ( "%Y-%m-%dT%H:%M:%S%.f+00:00" )
18061853 . to_string ( ) ,
18071854 ) ) ,
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+ }
18081867 ( PrimitiveType :: String , PrimitiveLiteral :: String ( val) ) => {
18091868 Ok ( JsonValue :: String ( val. clone ( ) ) )
18101869 }
@@ -1958,6 +2017,10 @@ mod timestamp {
19582017 // This shouldn't fail until the year 262000
19592018 DateTime :: from_timestamp_micros ( micros) . unwrap ( ) . naive_utc ( )
19602019 }
2020+
2021+ pub ( crate ) fn nanoseconds_to_datetime ( nanos : i64 ) -> NaiveDateTime {
2022+ DateTime :: from_timestamp_nanos ( nanos) . naive_utc ( )
2023+ }
19612024}
19622025
19632026mod timestamptz {
@@ -1972,6 +2035,12 @@ mod timestamptz {
19722035
19732036 DateTime :: from_timestamp ( secs, rem as u32 * 1_000 ) . unwrap ( )
19742037 }
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+ }
19752044}
19762045
19772046mod _serde {
0 commit comments