@@ -24,16 +24,37 @@ pub struct HumanDuration(pub Duration);
2424
2525impl fmt:: Display for HumanDuration {
2626 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
27+ if self . 0 == Duration :: ZERO {
28+ return write ! ( f, "0 seconds" ) ;
29+ }
30+
2731 let mut idx = 0 ;
2832 for ( i, & ( cur, _, _) ) in UNITS . iter ( ) . enumerate ( ) {
2933 idx = i;
3034 match UNITS . get ( i + 1 ) {
35+ // Stop if value minus half of the next smaller unit is above 1.5x current unit
3136 Some ( & next) if self . 0 . saturating_add ( next. 0 / 2 ) >= cur + cur / 2 => break ,
3237 _ => continue ,
3338 }
3439 }
3540
3641 let ( unit, name, alt) = UNITS [ idx] ;
42+ if self . 0 < Duration :: new ( 1 , 900_000_000 ) {
43+ let precision = if self . 0 > Duration :: from_millis ( 150 ) {
44+ 1
45+ } else if self . 0 > Duration :: from_millis ( 15 ) {
46+ 2
47+ } else {
48+ 3
49+ } ;
50+
51+ let s = self . 0 . as_secs_f64 ( ) ;
52+ return match f. alternate ( ) {
53+ true => write ! ( f, "{s:.*}s" , precision) ,
54+ false => write ! ( f, "{s:.*} seconds" , precision) ,
55+ } ;
56+ }
57+
3758 // FIXME when `div_duration_f64` is stable
3859 let mut t = ( self . 0 . as_secs_f64 ( ) / unit. as_secs_f64 ( ) ) . round ( ) as usize ;
3960 if idx < UNITS . len ( ) - 1 {
@@ -231,22 +252,25 @@ mod tests {
231252 "0 seconds" ,
232253 format!( "{}" , HumanDuration ( Duration :: from_secs( 0 ) ) )
233254 ) ;
234- assert_eq ! ( "0 seconds" , format!( "{}" , HumanDuration ( MILLI ) ) ) ;
235- assert_eq ! ( "0 seconds" , format!( "{}" , HumanDuration ( 499 * MILLI ) ) ) ;
236- assert_eq ! ( "1 second" , format!( "{}" , HumanDuration ( 500 * MILLI ) ) ) ;
237- assert_eq ! ( "1 second" , format!( "{}" , HumanDuration ( 999 * MILLI ) ) ) ;
255+ assert_eq ! ( "0.001 seconds" , format!( "{}" , HumanDuration ( MILLI ) ) ) ;
256+ assert_eq ! ( "0.008 seconds" , format!( "{}" , HumanDuration ( 8 * MILLI ) ) ) ;
257+ assert_eq ! ( "0.011 seconds" , format!( "{}" , HumanDuration ( 11 * MILLI ) ) ) ;
258+ assert_eq ! ( "0.02 seconds" , format!( "{}" , HumanDuration ( 17 * MILLI ) ) ) ;
259+ assert_eq ! ( "0.5 seconds" , format!( "{}" , HumanDuration ( 499 * MILLI ) ) ) ;
260+ assert_eq ! ( "0.5 seconds" , format!( "{}" , HumanDuration ( 500 * MILLI ) ) ) ;
261+ assert_eq ! ( "1.0 seconds" , format!( "{}" , HumanDuration ( 999 * MILLI ) ) ) ;
238262 }
239263
240264 #[ test]
241265 fn human_duration_less_than_two_seconds ( ) {
242- assert_eq ! ( "1 second " , format!( "{}" , HumanDuration ( 1499 * MILLI ) ) ) ;
243- assert_eq ! ( "2 seconds" , format!( "{}" , HumanDuration ( 1500 * MILLI ) ) ) ;
266+ assert_eq ! ( "1.5 seconds " , format!( "{}" , HumanDuration ( 1499 * MILLI ) ) ) ;
267+ assert_eq ! ( "1.5 seconds" , format!( "{}" , HumanDuration ( 1500 * MILLI ) ) ) ;
244268 assert_eq ! ( "2 seconds" , format!( "{}" , HumanDuration ( 1999 * MILLI ) ) ) ;
245269 }
246270
247271 #[ test]
248272 fn human_duration_one_unit ( ) {
249- assert_eq ! ( "1 second " , format!( "{}" , HumanDuration ( SECOND ) ) ) ;
273+ assert_eq ! ( "1.0 seconds " , format!( "{}" , HumanDuration ( SECOND ) ) ) ;
250274 assert_eq ! ( "60 seconds" , format!( "{}" , HumanDuration ( MINUTE ) ) ) ;
251275 assert_eq ! ( "60 minutes" , format!( "{}" , HumanDuration ( HOUR ) ) ) ;
252276 assert_eq ! ( "24 hours" , format!( "{}" , HumanDuration ( DAY ) ) ) ;
0 commit comments