105 lines
2.5 KiB
JavaScript
105 lines
2.5 KiB
JavaScript
|
import { defaultLocale } from "./_lib/defaultLocale.mjs";
|
||
|
import { getDefaultOptions } from "./_lib/defaultOptions.mjs";
|
||
|
|
||
|
/**
|
||
|
* The {@link formatDuration} function options.
|
||
|
*/
|
||
|
|
||
|
const defaultFormat = [
|
||
|
"years",
|
||
|
"months",
|
||
|
"weeks",
|
||
|
"days",
|
||
|
"hours",
|
||
|
"minutes",
|
||
|
"seconds",
|
||
|
];
|
||
|
|
||
|
/**
|
||
|
* @name formatDuration
|
||
|
* @category Common Helpers
|
||
|
* @summary Formats a duration in human-readable format
|
||
|
*
|
||
|
* @description
|
||
|
* Return human-readable duration string i.e. "9 months 2 days"
|
||
|
*
|
||
|
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
|
||
|
*
|
||
|
* @param duration - The duration to format
|
||
|
* @param options - An object with options.
|
||
|
*
|
||
|
* @returns The formatted date string
|
||
|
*
|
||
|
* @example
|
||
|
* // Format full duration
|
||
|
* formatDuration({
|
||
|
* years: 2,
|
||
|
* months: 9,
|
||
|
* weeks: 1,
|
||
|
* days: 7,
|
||
|
* hours: 5,
|
||
|
* minutes: 9,
|
||
|
* seconds: 30
|
||
|
* })
|
||
|
* //=> '2 years 9 months 1 week 7 days 5 hours 9 minutes 30 seconds'
|
||
|
*
|
||
|
* @example
|
||
|
* // Format partial duration
|
||
|
* formatDuration({ months: 9, days: 2 })
|
||
|
* //=> '9 months 2 days'
|
||
|
*
|
||
|
* @example
|
||
|
* // Customize the format
|
||
|
* formatDuration(
|
||
|
* {
|
||
|
* years: 2,
|
||
|
* months: 9,
|
||
|
* weeks: 1,
|
||
|
* days: 7,
|
||
|
* hours: 5,
|
||
|
* minutes: 9,
|
||
|
* seconds: 30
|
||
|
* },
|
||
|
* { format: ['months', 'weeks'] }
|
||
|
* ) === '9 months 1 week'
|
||
|
*
|
||
|
* @example
|
||
|
* // Customize the zeros presence
|
||
|
* formatDuration({ years: 0, months: 9 })
|
||
|
* //=> '9 months'
|
||
|
* formatDuration({ years: 0, months: 9 }, { zero: true })
|
||
|
* //=> '0 years 9 months'
|
||
|
*
|
||
|
* @example
|
||
|
* // Customize the delimiter
|
||
|
* formatDuration({ years: 2, months: 9, weeks: 3 }, { delimiter: ', ' })
|
||
|
* //=> '2 years, 9 months, 3 weeks'
|
||
|
*/
|
||
|
export function formatDuration(duration, options) {
|
||
|
const defaultOptions = getDefaultOptions();
|
||
|
const locale = options?.locale ?? defaultOptions.locale ?? defaultLocale;
|
||
|
const format = options?.format ?? defaultFormat;
|
||
|
const zero = options?.zero ?? false;
|
||
|
const delimiter = options?.delimiter ?? " ";
|
||
|
|
||
|
if (!locale.formatDistance) {
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
const result = format
|
||
|
.reduce((acc, unit) => {
|
||
|
const token = `x${unit.replace(/(^.)/, (m) => m.toUpperCase())}`;
|
||
|
const value = duration[unit];
|
||
|
if (value !== undefined && (zero || duration[unit])) {
|
||
|
return acc.concat(locale.formatDistance(token, value));
|
||
|
}
|
||
|
return acc;
|
||
|
}, [])
|
||
|
.join(delimiter);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
// Fallback for modularized imports:
|
||
|
export default formatDuration;
|