formatDuration.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { defaultLocale } from "./_lib/defaultLocale.js";
  2. import { getDefaultOptions } from "./_lib/defaultOptions.js";
  3. /**
  4. * The {@link formatDuration} function options.
  5. */
  6. const defaultFormat = [
  7. "years",
  8. "months",
  9. "weeks",
  10. "days",
  11. "hours",
  12. "minutes",
  13. "seconds",
  14. ];
  15. /**
  16. * @name formatDuration
  17. * @category Common Helpers
  18. * @summary Formats a duration in human-readable format
  19. *
  20. * @description
  21. * Return human-readable duration string i.e. "9 months 2 days"
  22. *
  23. * @param duration - The duration to format
  24. * @param options - An object with options.
  25. *
  26. * @returns The formatted date string
  27. *
  28. * @example
  29. * // Format full duration
  30. * formatDuration({
  31. * years: 2,
  32. * months: 9,
  33. * weeks: 1,
  34. * days: 7,
  35. * hours: 5,
  36. * minutes: 9,
  37. * seconds: 30
  38. * })
  39. * //=> '2 years 9 months 1 week 7 days 5 hours 9 minutes 30 seconds'
  40. *
  41. * @example
  42. * // Format partial duration
  43. * formatDuration({ months: 9, days: 2 })
  44. * //=> '9 months 2 days'
  45. *
  46. * @example
  47. * // Customize the format
  48. * formatDuration(
  49. * {
  50. * years: 2,
  51. * months: 9,
  52. * weeks: 1,
  53. * days: 7,
  54. * hours: 5,
  55. * minutes: 9,
  56. * seconds: 30
  57. * },
  58. * { format: ['months', 'weeks'] }
  59. * ) === '9 months 1 week'
  60. *
  61. * @example
  62. * // Customize the zeros presence
  63. * formatDuration({ years: 0, months: 9 })
  64. * //=> '9 months'
  65. * formatDuration({ years: 0, months: 9 }, { zero: true })
  66. * //=> '0 years 9 months'
  67. *
  68. * @example
  69. * // Customize the delimiter
  70. * formatDuration({ years: 2, months: 9, weeks: 3 }, { delimiter: ', ' })
  71. * //=> '2 years, 9 months, 3 weeks'
  72. */
  73. export function formatDuration(duration, options) {
  74. const defaultOptions = getDefaultOptions();
  75. const locale = options?.locale ?? defaultOptions.locale ?? defaultLocale;
  76. const format = options?.format ?? defaultFormat;
  77. const zero = options?.zero ?? false;
  78. const delimiter = options?.delimiter ?? " ";
  79. if (!locale.formatDistance) {
  80. return "";
  81. }
  82. const result = format
  83. .reduce((acc, unit) => {
  84. const token = `x${unit.replace(/(^.)/, (m) => m.toUpperCase())}`;
  85. const value = duration[unit];
  86. if (value !== undefined && (zero || duration[unit])) {
  87. return acc.concat(locale.formatDistance(token, value));
  88. }
  89. return acc;
  90. }, [])
  91. .join(delimiter);
  92. return result;
  93. }
  94. // Fallback for modularized imports:
  95. export default formatDuration;