# format-duration

> Convert a number in milliseconds to a standard duration string.

Latest version **4.0.0** (published 2026-06-13) · ISC license · 0 weekly downloads

## Install

```sh
npm install format-duration
pnpm add format-duration
yarn add format-duration
bun add format-duration
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 4.0.0 |
| Published | 2026-06-13 |
| First published | 2016-08-27 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=22.12.0 |
| Dependencies | 0 |
| Unpacked size | 7.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 60 |
| Author | Nate Goldman |
| Maintainers | bret, ungoldman |
| Keywords | display, duration, format, hh:mm:ss, hours, milliseconds, mm:ss, seconds, time |

## Links

- npm: https://www.npmjs.com/package/format-duration
- Repository: https://github.com/ungoldman/format-duration
- Issues: https://github.com/ungoldman/format-duration/issues
- npm.io page: https://npm.io/package/format-duration

## Alternatives

- [@js-joda/timezone](https://npm.io/package/@js-joda/timezone.md) — 383.4K weekly downloads
- [chartjs-adapter-moment](https://npm.io/package/chartjs-adapter-moment.md) — 210.8K weekly downloads
- [strftime](https://npm.io/package/strftime.md) — 171.2K weekly downloads
- [vue-flatpickr-component](https://npm.io/package/vue-flatpickr-component.md) — 115.8K weekly downloads
- [timepicker](https://npm.io/package/timepicker.md) — 51.0K weekly downloads

## Recent versions

- 4.0.0 (latest) — 2026-06-13
- 1.3.3-beta.0 (beta) — 2021-07-15
- 3.0.2 — 2023-01-17
- 3.0.1 — 2022-12-18
- 3.0.0 — 2022-12-13
- 2.0.0 — 2022-03-17
- 1.4.0 — 2021-08-04
- 1.3.2 — 2021-07-15
- 1.3.2-beta.1 — 2021-07-15
- 1.3.2-beta.0 — 2021-07-14
- 1.3.1 — 2018-10-11
- 1.3.0 — 2018-10-11
- 1.2.0 — 2018-07-24
- 1.1.0 — 2018-02-23
- 1.0.1 — 2018-02-23
- … 1 more at https://npm.io/package/format-duration/versions

## README

<div align="center">

<img src="./stopwatch.png" alt="stopwatch" width="200">

# format-duration

Convert a number in milliseconds to a standard duration string.

[![npm][npm-image]][npm-url]
[![build][build-image]][build-url]
[![downloads][downloads-image]][npm-url]

[npm-image]: https://img.shields.io/npm/v/format-duration.svg
[npm-url]: https://www.npmjs.com/package/format-duration
[build-image]: https://github.com/ungoldman/format-duration/actions/workflows/tests.yml/badge.svg
[build-url]: https://github.com/ungoldman/format-duration/actions/workflows/tests.yml
[downloads-image]: https://img.shields.io/npm/dm/format-duration.svg

</div>

## Install

```
npm install format-duration
```

As of v4 this is an ESM-only package. CommonJS code can `require()` it on Node 22.12+ (see [#201](https://github.com/ungoldman/gh-release/issues/201) for why).

## Usage

```js
import format from 'format-duration'
// or named: import { formatDuration } from 'format-duration'
// from CommonJS: const { formatDuration } = require('format-duration')

// anything under a second is rounded down to zero
format(999) // '0:00'

// 1000 milliseconds is a second
format(1000) // '0:01'

// 1999 rounds down to 0:01
format(1000 * 2 - 1) // '0:01'

// 60 seconds is a minute
format(1000 * 60) // '1:00'

// 59 seconds looks like this
format(1000 * 60 - 1) // '0:59'

// 60 minutes is an hour
format(1000 * 60 * 60) // '1:00:00'

// 59 minutes and 59 seconds looks like this
format(1000 * 60 * 60 - 1) // '59:59'

// 24 hours is a day
format(1000 * 60 * 60 * 24) // '1:00:00:00'

// 23 hours, 59 minutes, and 59 seconds looks like this
format(1000 * 60 * 60 * 24 - 1) // '23:59:59'

// 365 days looks like this (not bothering with years)
format(1000 * 60 * 60 * 24 * 365) // '365:00:00:00'

// anything under a second is rounded down to zero
format(-999) // '0:00'

// 1000 milliseconds is a second
format(-1000) // '-0:01'

// 365 days looks like this (not bothering with years)
format(-1000 * 60 * 60 * 24 * 365) // '-365:00:00:00'

// with `leading` option, the most-significant field is zero-padded too
format(1000 * 60, { leading: true }) // '01:00'
format(1000 * 60 - 1, { leading: true }) // '00:59'
format(1000 * 60 * 60, { leading: true }) // '01:00:00'

// the days field is left at natural width: unlike hours/minutes/seconds it is
// unbounded (it never wraps into a larger unit), so it has no fixed width to pad to
format(1000 * 60 * 60 * 24, { leading: true }) // '1:00:00:00'

// with `ms` option, formatting looks like this
format(999, { ms: true }) // '0:00.999'
format(1000 * 60, { ms: true }) // '1:00.000'
format(1000 * 60 * 60 * 24 - 1, { ms: true }) // '23:59:59.999'
```

## Contributing

Contributions welcome! Please read the [contributing guidelines](CONTRIBUTING.md) first.

## License

[ISC](LICENSE.md)

Stopwatch image is from [emojidex](https://emojidex.com/emoji/stopwatch).

---
_Source: https://npm.io/package/format-duration · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
