readableDuration function

String readableDuration(
  1. Duration duration, {
  2. int? precision,
})

Returns a Duration as a human-readable string.

precision specifies the maximum number of fractional digits to show after the decimal point in the number of seconds. If null, the maximum precision will be used.

Trailing zeroes from any fractional portion are always discarded.

Example outputs:

1d2h34m56.789s
1d
2h58s
2h0.2s

Implementation

String readableDuration(Duration duration, {int? precision}) {
  if (duration.inMicroseconds == 0) {
    return '0s';
  }

  var sign = '';
  if (duration.isNegative) {
    sign = '-';
    duration = -duration;
  }

  if (precision != null && precision < 6) {
    if (precision < 0) {
      throw ArgumentError(
        'readableDuration: precision must be non-negative.',
      );
    }
    duration = Duration(
      microseconds: duration.inMicroseconds
          .roundToMultipleOf(math.pow(10, 6 - precision) as int),
    );
  }

  var days = duration.inDays;
  var hours = duration.inHours % Duration.hoursPerDay;
  var minutes = duration.inMinutes % Duration.minutesPerHour;
  var seconds = duration.inSeconds % Duration.secondsPerMinute;
  var microseconds = duration.inMicroseconds % Duration.microsecondsPerSecond;

  var secondsString = '';
  if (microseconds > 0) {
    // Strip off trailing zeroes from the fractional portion.
    var fractionalSecondsString =
        microseconds.padLeft(6).replaceAll(RegExp(r'0+$'), '');
    secondsString = '$seconds.${fractionalSecondsString}s';
  } else if (seconds > 0) {
    secondsString = '${seconds}s';
  }

  var components = <String>[
    sign,
    if (days > 0) '${days}d',
    if (hours > 0) '${hours}h',
    if (minutes > 0) '${minutes}m',
    secondsString,
  ];

  return components.join();
}