@@ -13,7 +13,7 @@ use super::{date, relative, time, weekday};
13
13
#[ derive( Debug , Default ) ]
14
14
pub struct DateTimeBuilder {
15
15
base : Option < DateTime < FixedOffset > > ,
16
- timestamp : Option < i32 > ,
16
+ timestamp : Option < f64 > ,
17
17
date : Option < date:: Date > ,
18
18
time : Option < time:: Time > ,
19
19
weekday : Option < weekday:: Weekday > ,
@@ -35,7 +35,7 @@ impl DateTimeBuilder {
35
35
36
36
/// Timestamp value is exclusive to other date/time components. Caller of
37
37
/// 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 > {
39
39
self . timestamp = Some ( ts) ;
40
40
Ok ( self )
41
41
}
@@ -117,10 +117,24 @@ impl DateTimeBuilder {
117
117
) ?;
118
118
119
119
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
+ }
124
138
}
125
139
126
140
if let Some ( date:: Date { year, month, day } ) = self . date {
0 commit comments