duration function
Displays the given millisecond value in human-readable time.
For example, the value of 604800000 (7 days) is displayed as 7 Days.
A month is treated as 30 days and a year as 365 days.
useShortString:Days->D,Hours->H,Minutes->M,Seconds->S,Months->Mo,Years->Y,Milliseconds->ms.useSpace: Insert a space between value and unit (e.g.1Days->1 Days).withZeroValue: Include units with a value of 0 below the largest unit.separator: Joins each unit (e.g.-->1 Hour-10 Minutes).withMilliSeconds: Include the millisecond unit (defaultfalse).maxUnitCount: Maximum number of units to display, counted from the largest.unit: Show the whole duration with a single unit (e.g.Hour->48 Hours,0.5 Hours).
Implementation
String duration(
num milliseconds, {
bool useShortString = false,
bool useSpace = true,
bool withZeroValue = false,
String separator = ' ',
bool withMilliSeconds = false,
int? maxUnitCount,
String? unit,
}) {
// Single-unit mode: express the whole duration with one unit (fractions allowed).
if (unit != null) {
String name = unit.toLowerCase();
if (name.endsWith('s')) {
name = name.substring(0, name.length - 1);
}
Map<String, dynamic>? target;
for (final u in _durationUnits) {
if ((u['name'] as String).toLowerCase() == name) {
target = u;
break;
}
}
if (target != null) {
final num value = double.parse(
(milliseconds / (target['ms'] as int)).toStringAsFixed(6));
return _durationLabel(value, target, useShortString, useSpace);
}
}
final List<Map<String, dynamic>> activeUnits = withMilliSeconds
? _durationUnits
: _durationUnits.where((u) => u['name'] != 'Millisecond').toList();
final List<Map<String, dynamic>> values = [];
num remaining = milliseconds;
for (final u in activeUnits) {
final int value = (remaining / (u['ms'] as int)).floor();
remaining -= value * (u['ms'] as int);
values.add({'value': value, 'unit': u});
}
// Skip leading units that are zero; keep interior/trailing zeros only when requested.
int firstNonZero = -1;
for (int i = 0; i < values.length; i++) {
if (values[i]['value'] != 0) {
firstNonZero = i;
break;
}
}
if (firstNonZero == -1) {
return '';
}
List<Map<String, dynamic>> selected = values.sublist(firstNonZero);
if (!withZeroValue) {
selected = selected.where((v) => v['value'] != 0).toList();
}
List<String> result = selected
.map((v) => _durationLabel(v['value'] as num,
v['unit'] as Map<String, dynamic>, useShortString, useSpace))
.toList();
if (maxUnitCount != null && maxUnitCount >= 0) {
result = result.take(maxUnitCount).toList();
}
return result.join(separator);
}