durationParts
Breaks a duration in milliseconds into its units and returns them, leaving the caller to decide how to write them.
duration joins them into a string with English unit names and an s for the plural, which is a rule only English follows. Polish has three plural forms and Arabic six, and no language outside English builds them by appending s. This function hands back the pieces so a formatter that knows the language can put them together.
Parameters
| Name | Type | Required | Default |
|---|---|---|---|
milliseconds | numbernumfloat | ● | – |
| The duration to break up. | |||
options named keyword | DurationPartsOptions | – | – |
See the table below. These are the options of duration that decide which units are used; the ones that only decide how the pieces are written are left out. | |||
namedThese parameters are passed as named parameters.
keywordThese parameters are passed as keyword arguments, or as a single dict in their place.
DurationPartsOptions| Name | Type | Required | Default |
|---|---|---|---|
withZeroValue | booleanbool | – | falseFalse |
| Include units with a value of 0 below the largest unit. | |||
withMilliSeconds | booleanbool | – | falseFalse |
| Include the millisecond unit. | |||
maxUnitCount | numberint | – | – |
| Maximum number of units to return, counted from the largest. | |||
unit | DurationUnitName | – | – |
Express the whole duration with this one unit, which allows a fractional value. | |||
Returns
DurationPart[]
List<DurationPart>
list
DurationPart| Name | Type | Required | Default |
|---|---|---|---|
value | numbernumfloat | – | – |
How many of unit the duration holds. Whole in the normal case, and possibly fractional when a single unit was asked for. | |||
unit | DurationUnitName | – | – |
One of Year, Month, Day, Hour, Minute, Second and Millisecond. Use it to look up a unit name of your own. | |||
A duration of zero returns an empty list, the same case in which duration returns an empty string.
Examples
durationParts(604800000); // [{ value: 7, unit: 'Day' }]
durationParts(1234567890);
// [{ value: 14, unit: 'Day' }, { value: 6, unit: 'Hour' }, { value: 56, unit: 'Minute' }, { value: 7, unit: 'Second' }]
durationParts(1234567890, { maxUnitCount: 2 });
// [{ value: 14, unit: 'Day' }, { value: 6, unit: 'Hour' }]
durationParts(1500, { unit: 'Second' }); // [{ value: 1.5, unit: 'Second' }]final List<DurationPart> parts = durationParts(1234567890);
parts[0].value; // 14
parts[0].unit; // 'Day'
durationParts(1234567890, maxUnitCount: 2).length; // 2
durationParts(1500, unit: 'Second')[0].value; // 1.5durationParts(604800000) # [{'value': 7, 'unit': 'Day'}]
durationParts(1234567890)
# [{'value': 14, 'unit': 'Day'}, {'value': 6, 'unit': 'Hour'}, {'value': 56, 'unit': 'Minute'}, {'value': 7, 'unit': 'Second'}]
durationParts(1234567890, {'maxUnitCount': 2})
# [{'value': 14, 'unit': 'Day'}, {'value': 6, 'unit': 'Hour'}]
durationParts(1500, unit='Second') # [{'value': 1.5, 'unit': 'Second'}]Writing the duration in the reader's language
Map unit onto the unit names your formatter expects, and let it write the rest.
Intl.DurationFormat takes the units as an object and produces the whole string, including the separator each language uses.
const UNITS = {
Year: 'years',
Month: 'months',
Day: 'days',
Hour: 'hours',
Minute: 'minutes',
Second: 'seconds',
Millisecond: 'milliseconds'
};
function localizedDuration(milliseconds, locale) {
const value = {};
for (const part of durationParts(milliseconds)) {
value[UNITS[part.unit]] = part.value;
}
return new Intl.DurationFormat(locale, { style: 'long' }).format(value);
}
localizedDuration(1234567890, 'de'); // '14 Tage, 6 Stunden, 56 Minuten und 7 Sekunden'
localizedDuration(1234567890, 'fr'); // '14 jours, 6 heures, 56 minutes et 7 secondes'
localizedDuration(1234567890, 'ko'); // '14일 6시간 56분 7초'Intl.DurationFormat is newer than the rest of Intl, so check for it before calling it. Intl.NumberFormat with style: 'unit' covers the same seven units one at a time and has been available for far longer.
Add intl for the number, and take the unit name from your own translations. A language with more than two plural forms needs Intl.plural, which is why the count and the name are kept apart here.
const Map<String, String> unitKeys = {
'Day': 'duration.day',
'Hour': 'duration.hour',
'Minute': 'duration.minute',
'Second': 'duration.second',
};
String localizedDuration(int milliseconds, String locale) {
return durationParts(milliseconds)
.map((DurationPart part) =>
translatePlural(unitKeys[part.unit]!, part.value.toInt(), locale))
.join(' ');
}Add babel, whose format_unit knows the unit names and the plural rules for each language.
from babel.units import format_unit
unitKeys = {
'Day': 'duration-day',
'Hour': 'duration-hour',
'Minute': 'duration-minute',
'Second': 'duration-second',
}
def localizedDuration(milliseconds: float, locale: str) -> str:
return ' '.join(
format_unit(part['value'], unitKeys[part['unit']], locale=locale)
for part in durationParts(milliseconds)
)