@@ -178,6 +178,9 @@ where
178178 T : Timelike + Add < Duration , Output = T > + Sub < Duration , Output = T > ,
179179{
180180 if let Some ( span) = duration. num_nanoseconds ( ) {
181+ if span < 0 {
182+ return Err ( RoundingError :: DurationExceedsLimit ) ;
183+ }
181184 if naive. timestamp ( ) . abs ( ) > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
182185 return Err ( RoundingError :: TimestampExceedsLimit ) ;
183186 }
@@ -217,6 +220,9 @@ where
217220 T : Timelike + Add < Duration , Output = T > + Sub < Duration , Output = T > ,
218221{
219222 if let Some ( span) = duration. num_nanoseconds ( ) {
223+ if span < 0 {
224+ return Err ( RoundingError :: DurationExceedsLimit ) ;
225+ }
220226 if naive. timestamp ( ) . abs ( ) > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
221227 return Err ( RoundingError :: TimestampExceedsLimit ) ;
222228 }
@@ -304,10 +310,10 @@ impl std::error::Error for RoundingError {
304310
305311#[ cfg( test) ]
306312mod tests {
307- use super :: { Duration , DurationRound , SubsecRound } ;
313+ use super :: { Duration , DurationRound , RoundingError , SubsecRound } ;
308314 use crate :: offset:: { FixedOffset , TimeZone , Utc } ;
309- use crate :: NaiveDate ;
310315 use crate :: Timelike ;
316+ use crate :: { NaiveDate , NaiveDateTime } ;
311317
312318 #[ test]
313319 fn test_round_subsecs ( ) {
@@ -760,4 +766,19 @@ mod tests {
760766 "1969-12-12 12:10:00 UTC"
761767 ) ;
762768 }
769+
770+ #[ test]
771+ fn issue1010 ( ) {
772+ let dt = NaiveDateTime :: from_timestamp_opt ( -4227854320 , 1678774288 ) . unwrap ( ) ;
773+ let span = Duration :: microseconds ( -7019067213869040 ) ;
774+ assert_eq ! ( dt. duration_trunc( span) , Err ( RoundingError :: DurationExceedsLimit ) ) ;
775+
776+ let dt = NaiveDateTime :: from_timestamp_opt ( 320041586 , 1920103021 ) . unwrap ( ) ;
777+ let span = Duration :: nanoseconds ( -8923838508697114584 ) ;
778+ assert_eq ! ( dt. duration_round( span) , Err ( RoundingError :: DurationExceedsLimit ) ) ;
779+
780+ let dt = NaiveDateTime :: from_timestamp_opt ( -2621440 , 0 ) . unwrap ( ) ;
781+ let span = Duration :: nanoseconds ( -9223372036854771421 ) ;
782+ assert_eq ! ( dt. duration_round( span) , Err ( RoundingError :: DurationExceedsLimit ) ) ;
783+ }
763784}
0 commit comments