@@ -183,13 +183,42 @@ impl FromStr for Duration {
183
183
}
184
184
}
185
185
186
+ #[ cfg( feature = "chrono" ) ]
187
+ mod chrono {
188
+ use :: chrono:: TimeDelta ;
189
+
190
+ use super :: * ;
191
+
192
+ impl From < :: chrono:: TimeDelta > for Duration {
193
+ fn from ( value : :: chrono:: TimeDelta ) -> Self {
194
+ let mut result = Self {
195
+ seconds : value. num_seconds ( ) ,
196
+ nanos : value. subsec_nanos ( ) ,
197
+ } ;
198
+ result. normalize ( ) ;
199
+ result
200
+ }
201
+ }
202
+
203
+ impl TryFrom < Duration > for :: chrono:: TimeDelta {
204
+ type Error = DurationError ;
205
+
206
+ fn try_from ( mut value : Duration ) -> Result < TimeDelta , duration:: DurationError > {
207
+ value. normalize ( ) ;
208
+ let seconds = TimeDelta :: try_seconds ( value. seconds ) . ok_or ( DurationError :: OutOfRange ) ?;
209
+ let nanos = TimeDelta :: nanoseconds ( value. nanos . into ( ) ) ;
210
+ seconds. checked_add ( & nanos) . ok_or ( DurationError :: OutOfRange )
211
+ }
212
+ }
213
+ }
214
+
186
215
#[ cfg( kani) ]
187
216
mod proofs {
188
217
use super :: * ;
189
218
190
219
#[ cfg( feature = "std" ) ]
191
220
#[ kani:: proof]
192
- fn check_duration_roundtrip ( ) {
221
+ fn check_duration_std_roundtrip ( ) {
193
222
let seconds = kani:: any ( ) ;
194
223
let nanos = kani:: any ( ) ;
195
224
kani:: assume ( nanos < 1_000_000_000 ) ;
@@ -218,7 +247,7 @@ mod proofs {
218
247
219
248
#[ cfg( feature = "std" ) ]
220
249
#[ kani:: proof]
221
- fn check_duration_roundtrip_nanos ( ) {
250
+ fn check_duration_std_roundtrip_nanos ( ) {
222
251
let seconds = 0 ;
223
252
let nanos = kani:: any ( ) ;
224
253
let std_duration = std:: time:: Duration :: new ( seconds, nanos) ;
@@ -243,6 +272,31 @@ mod proofs {
243
272
) )
244
273
}
245
274
}
275
+
276
+ #[ cfg( feature = "chrono" ) ]
277
+ #[ kani:: proof]
278
+ fn check_duration_chrono_roundtrip ( ) {
279
+ let seconds = kani:: any ( ) ;
280
+ let nanos = kani:: any ( ) ;
281
+ let prost_duration = Duration { seconds, nanos } ;
282
+ match :: chrono:: TimeDelta :: try_from ( prost_duration) {
283
+ Err ( DurationError :: OutOfRange ) => {
284
+ // Test case not valid: duration out of range
285
+ return ;
286
+ }
287
+ Err ( err) => {
288
+ panic ! ( "Unexpected error: {err}" )
289
+ }
290
+ Ok ( chrono_duration) => {
291
+ let mut normalized_prost_duration = prost_duration;
292
+ normalized_prost_duration. normalize ( ) ;
293
+ assert_eq ! (
294
+ Duration :: try_from( chrono_duration) . unwrap( ) ,
295
+ normalized_prost_duration
296
+ ) ;
297
+ }
298
+ }
299
+ }
246
300
}
247
301
248
302
#[ cfg( test) ]
0 commit comments