@@ -13,7 +13,7 @@ use super::{date, relative, time, weekday};
1313#[ derive( Debug , Default ) ]
1414pub struct DateTimeBuilder {
1515 base : Option < DateTime < FixedOffset > > ,
16- timestamp : Option < i32 > ,
16+ timestamp : Option < f64 > ,
1717 date : Option < date:: Date > ,
1818 time : Option < time:: Time > ,
1919 weekday : Option < weekday:: Weekday > ,
@@ -35,7 +35,7 @@ impl DateTimeBuilder {
3535
3636 /// Timestamp value is exclusive to other date/time components. Caller of
3737 /// the builder must ensure that it is not combined with other items.
38- pub ( super ) fn set_timestamp ( mut self , ts : i32 ) -> Result < Self , & ' static str > {
38+ pub ( super ) fn set_timestamp ( mut self , ts : f64 ) -> Result < Self , & ' static str > {
3939 self . timestamp = Some ( ts) ;
4040 Ok ( self )
4141 }
@@ -117,10 +117,24 @@ impl DateTimeBuilder {
117117 ) ?;
118118
119119 if let Some ( ts) = self . timestamp {
120- dt = chrono:: Utc
121- . timestamp_opt ( ts. into ( ) , 0 )
122- . unwrap ( )
123- . with_timezone ( & dt. timezone ( ) ) ;
120+ // TODO: How to make the fract -> nanosecond conversion more precise?
121+ // Maybe considering using the
122+ // [rust_decimal](https://crates.io/crates/rust_decimal) crate?
123+ match chrono:: Utc . timestamp_opt ( ts as i64 , ( ts. fract ( ) * 10f64 . powi ( 9 ) ) . round ( ) as u32 )
124+ {
125+ chrono:: MappedLocalTime :: Single ( t) => {
126+ // If the timestamp is valid, we can use it directly.
127+ dt = t. with_timezone ( & dt. timezone ( ) ) ;
128+ }
129+ chrono:: MappedLocalTime :: Ambiguous ( earliest, _latest) => {
130+ // TODO: When there is a fold in the local time, which value
131+ // do we choose? For now, we use the earliest one.
132+ dt = earliest. with_timezone ( & dt. timezone ( ) ) ;
133+ }
134+ chrono:: MappedLocalTime :: None => {
135+ return None ; // Invalid timestamp
136+ }
137+ }
124138 }
125139
126140 if let Some ( date:: Date { year, month, day } ) = self . date {
0 commit comments