@@ -22,6 +22,7 @@ use crate::format::{Fixed, Item, Numeric, Pad};
2222use crate :: naive:: { Days , IsoWeek , NaiveDate , NaiveTime } ;
2323use crate :: oldtime:: Duration as OldDuration ;
2424use crate :: { DateTime , Datelike , LocalResult , Months , TimeZone , Timelike , Weekday } ;
25+ use core:: cmp:: Ordering ;
2526
2627#[ cfg( feature = "rustc-serialize" ) ]
2728pub ( super ) mod rustc_serialize;
@@ -138,31 +139,41 @@ impl NaiveDateTime {
138139 ///
139140 /// ```
140141 /// use chrono::NaiveDateTime;
141- /// let timestamp_millis: i64 = 1662921288 ; //Sunday, September 11, 2022 6:34:48 PM
142+ /// let timestamp_millis: i64 = 1662921288000 ; //Sunday, September 11, 2022 6:34:48 PM
142143 /// let naive_datetime = NaiveDateTime::from_timestamp_millis(timestamp_millis);
143144 /// assert!(naive_datetime.is_some());
144145 /// assert_eq!(timestamp_millis, naive_datetime.unwrap().timestamp_millis());
145146 ///
146147 /// // Negative timestamps (before the UNIX epoch) are supported as well.
147- /// let timestamp_millis: i64 = -2208936075 ; //Mon Jan 01 1900 14:38:45 GMT+0000
148+ /// let timestamp_millis: i64 = -2208936075000 ; //Mon Jan 01 1900 14:38:45 GMT+0000
148149 /// let naive_datetime = NaiveDateTime::from_timestamp_millis(timestamp_millis);
149150 /// assert!(naive_datetime.is_some());
150151 /// assert_eq!(timestamp_millis, naive_datetime.unwrap().timestamp_millis());
151152 /// ```
152153 #[ inline]
153154 pub fn from_timestamp_millis ( millis : i64 ) -> Option < NaiveDateTime > {
154- let mut secs = millis / 1000 ;
155- if millis < 0 {
156- secs = secs. checked_sub ( 1 ) ?;
155+ let ( secs, subsec_millis) = ( millis / 1000 , millis % 1000 ) ;
156+
157+ match subsec_millis. cmp ( & 0 ) {
158+ Ordering :: Less => {
159+ // in the case where our subsec part is negative, then we are actually in the earlier second
160+ // hence we subtract one from the seconds part, and we then add a whole second worth of nanos
161+ // to our nanos part. Due to the use of u32 datatype, it is more convenient to subtract
162+ // the absolute value of the subsec nanos from a whole second worth of nanos
163+ let nsecs = u32:: try_from ( subsec_millis. abs ( ) ) . ok ( ) ? * NANOS_IN_MILLISECOND ;
164+ NaiveDateTime :: from_timestamp_opt (
165+ secs. checked_sub ( 1 ) ?,
166+ NANOS_IN_SECOND . checked_sub ( nsecs) ?,
167+ )
168+ }
169+ Ordering :: Equal => NaiveDateTime :: from_timestamp_opt ( secs, 0 ) ,
170+ Ordering :: Greater => {
171+ // convert the subsec millis into nanosecond scale so they can be supplied
172+ // as the nanoseconds parameter
173+ let nsecs = u32:: try_from ( subsec_millis) . ok ( ) ? * NANOS_IN_MILLISECOND ;
174+ NaiveDateTime :: from_timestamp_opt ( secs, nsecs)
175+ }
157176 }
158-
159- let nsecs = ( millis % 1000 ) . abs ( ) ;
160- let mut nsecs = u32:: try_from ( nsecs) . ok ( ) ? * NANOS_IN_MILLISECOND ;
161- if secs < 0 {
162- nsecs = NANOS_IN_SECOND . checked_sub ( nsecs) ?;
163- }
164-
165- NaiveDateTime :: from_timestamp_opt ( secs, nsecs)
166177 }
167178
168179 /// Makes a new `NaiveDateTime` corresponding to a UTC date and time,
0 commit comments