# pretty-ms > Convert milliseconds to a human readable string: `1337000000` → `15d 11h 23m 20s` *See [`parse-duration-ms`](https://github.com/sindresorhus/parse-duration-ms) for the inverse.* ## Install ```sh npm install pretty-ms ``` ## Usage ```js import prettyMilliseconds from 'pretty-ms'; prettyMilliseconds(1337000000); //=> '15d 11h 23m 20s' prettyMilliseconds(1337000000n); //=> '15d 11h 23m 20s' prettyMilliseconds(1337); //=> '1.3s' prettyMilliseconds(133); //=> '133ms' // `compact` option prettyMilliseconds(1337, {compact: true}); //=> '1s' // `verbose` option prettyMilliseconds(1335669000, {verbose: true}); //=> '15 days 11 hours 1 minute 9 seconds' // `colonNotation` option prettyMilliseconds(95500, {colonNotation: true}); //=> '1:35.5' // `formatSubMilliseconds` option prettyMilliseconds(100.400080, {formatSubMilliseconds: true}) //=> '100ms 400µs 80ns' // `subSecondsAsDecimals` option prettyMilliseconds(900, {subSecondsAsDecimals: true}); //=> '0.9s' // Can be useful for time durations prettyMilliseconds(new Date(2014, 0, 1, 10, 40) - new Date(2014, 0, 1, 10, 5)) //=> '35m' ``` ## API ### prettyMilliseconds(milliseconds, options?) #### milliseconds Type: `number | bigint` Milliseconds to humanize. An integer (`number` or `bigint`) is exact at any size. A fractional number is first rounded to 15 significant digits, the precision of a number, which removes float noise: - `0.57 * 100_000` (`56999.99999999999`) is `57s`. - `999.9999999999999` (16 digits) is `1s`, but `999.99999999999` (14 digits) is `999ms`. From `1e14` milliseconds (about 3,170 years) up, no digits are left for the fraction, so the duration is rounded to whole milliseconds, and from `1e15` (about 31,700 years) up, to the nearest 10 milliseconds. #### options Type: `object` ##### secondsDecimalDigits Type: `number`\ Default: `1` Number of digits to appear after the seconds decimal point. Digits are floored, not rounded, so the seconds never round up into the next step: `1999ms` is `1.9s`, and at `0` digits it is `1s`, never `2s`. The flooring applies to the duration after it is read (see `milliseconds` for how a fractional number is read). ##### millisecondsDecimalDigits Type: `number`\ Default: `0` Number of digits to appear after the milliseconds decimal point. The milliseconds are rounded, not floored, but they never round up to `1000ms`, and a nonzero duration under a second never rounds down to `0ms`: `999.6ms` is `999ms`, and `0.2ms` is `1ms`. This does not apply with `formatSubMilliseconds`, which floors instead. Useful in combination with [`process.hrtime()`](https://nodejs.org/api/process.html#process_process_hrtime_time). ##### keepDecimalsOnWholeSeconds Type: `boolean`\ Default: `false` Keep milliseconds on whole seconds: `13s` → `13.0s`. Useful when you are showing a number of seconds spent on an operation and don't want the width of the output to change when hitting a whole number. ##### compact Type: `boolean`\ Default: `false` Only show the first unit: `1h 10m` → `1h`. Also ensures that `millisecondsDecimalDigits` and `secondsDecimalDigits` are both set to `0`. ##### unitCount Type: `number`\ Default: `Infinity` Number of units to show. Setting `compact` to `true` overrides this option. It is ignored with `colonNotation`. ##### verbose Type: `boolean`\ Default: `false` Use full-length units: `5h 1m 45s` → `5 hours 1 minute 45 seconds` ##### separateMilliseconds Type: `boolean`\ Default: `false` Show milliseconds separately. This means they won't be included in the decimal part of the seconds. ##### formatSubMilliseconds Type: `boolean`\ Default: `false` Show microseconds and nanoseconds. The values are floored to whole nanoseconds, so a duration under 1 nanosecond is `0ms`. ##### colonNotation Type: `boolean`\ Default: `false` Display time using colon notation: `5h 1m 45s` → `5:01:45`. Always shows time in at least minutes: `1s` → `0:01`, or in at least hours with `hideSeconds`: `1m` → `0:01`. Useful when you want to display time without the time units, similar to a digital watch. Setting `colonNotation` to `true` overrides the following options to `false`: - `compact` - `formatSubMilliseconds` - `separateMilliseconds` - `verbose` Days after a year are padded to 3 digits to keep the width: `1:005:00:00:00`. It also ignores `unitCount`, as dropping a field would change what the remaining fields mean: `1:01:01` would become `1:01`, which reads as 1 minute. ##### hideYear Type: `boolean`\ Default: `false` Hides the year and shows the hidden year additionally as days (365 per year): `1y 3d 5h 1m 45s` → `368d 5h 1m 45s`. ##### hideYearAndDays Type: `boolean`\ Default: `false` Hides the year and days and shows the hidden values additionally as hours: `1y 3d 5h 1m 45s` → `8837h 1m 45s`. ##### hideSeconds Type: `boolean`\ Default: `false` Hides the seconds: `1y 3d 5h 1m 45s` → `1y 3d 5h 1m`. A duration under a minute has no coarser unit, so it keeps its seconds rather than showing nothing. With `colonNotation`, the hours are always shown, so the fields read as `h:mm`: `60000` → `0:01`, and `45000` → `0:00:45`. ##### subSecondsAsDecimals Type: `boolean`\ Default: `false` Show sub-second values as decimal seconds: `900ms` → `0.9s`. Useful for progress indicators where you want consistent unit format to prevent flickering. Also floored, so `999ms` is `0.9s`. A duration too small for the seconds field to show, like `50ms` at the default `secondsDecimalDigits` of `1`, stays in milliseconds rather than showing as zero. With `compact`, the seconds have no decimals, so a duration under a second stays in milliseconds. ## FAQ ### Why doesn't this package support months? This package formats time durations, not calendar dates. Months (28-31 days) have variable lengths, making duration calculations ambiguous. Years are shown as a fixed 365 days, so they do not account for leap years. Use the [`hideYear`](#hideyear) option to show days as the largest unit, since days are always exactly 24 hours. For calendar-based formatting, use [Temporal API](https://tc39.es/proposal-temporal/docs/) or a date library like [date-fns](https://github.com/date-fns/date-fns). ### Why doesn't the formatted difference of two values match the formatted values? ```js prettyMilliseconds(3670); //=> '3.6s' prettyMilliseconds(5230); //=> '5.2s' prettyMilliseconds(5230 - 3670); //=> '1.5s' // Not '1.6s' ``` This is inherent to displaying rounded numbers, the same reason [rounded percentages don't always add up to 100%](https://help.surveymonkey.com/en/surveymonkey/analyze/percents-not-totaling/). Values are rounded independently, and rounding does not distribute over subtraction. `prettyMilliseconds(5230 - 3670)` correctly represents the true difference; it just won't always match subtracting the two rounded strings by eye. ## Related - [pretty-ms-cli](https://github.com/sindresorhus/pretty-ms-cli) - CLI for this module - [parse-ms](https://github.com/sindresorhus/parse-ms) - Parse milliseconds into an object - [to-milliseconds](https://github.com/sindresorhus/to-milliseconds) - Convert an object of time properties to milliseconds - [parse-duration-ms](https://github.com/sindresorhus/parse-duration-ms) - Parse duration strings to milliseconds - [pretty-bytes](https://github.com/sindresorhus/pretty-bytes) - Convert bytes to a human readable string