# [library-name]

[![npm version](https://img.shields.io/npm/v/[library-name])](https://www.npmjs.com/package/[library-name])
[![CI](https://github.com/[org]/[library-name]/actions/workflows/ci.yml/badge.svg)](https://github.com/[org]/[library-name]/actions/workflows/ci.yml)
[![Coverage](https://img.shields.io/codecov/c/github/[org]/[library-name])](https://codecov.io/gh/[org]/[library-name])
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)

> Library or package README template: badges, one-line description,
> features, installation for several package managers, quick start,
> examples, API overview, configuration, compatibility, versioning,
> contributing, security and licence. Replace every `[bracketed]` value and
> every line marked *Example*.

<!--
Guidance: How to use this template
- The first screen decides whether a developer tries the library: the
  one-line description, install command and a working quick-start snippet
  must all be visible without scrolling far.
- Every code example must run as written against the current release.
  Test them in CI if you can (doctest, README-as-test tools).
- Link to full documentation for depth; the README is the entry point, not
  the manual.
- Remove badges you do not maintain; a red or broken badge hurts trust.
-->

**[library-name] is a [short category, for example "zero-dependency
TypeScript library"] for [what it does, for example "parsing and
formatting ISO 8601 durations"].**

| Field | Value |
|---|---|
| Latest version | [1.4.2] |
| Licence | [MIT] |
| Runtime support | [Node.js 20+, modern browsers, Deno, Bun] |
| Documentation | [https://example.com/docs] |
| Maintainers | [@maintainer-1], [@maintainer-2] |

## Features

<!-- Guidance: Four to eight bullets, each a concrete capability or guarantee. Say what makes this library different from the obvious alternative. -->

- *Example:* Parses every duration form in ISO 8601, including weeks and fractional seconds.
- *Example:* Zero runtime dependencies, 2.1 kB minified and gzipped, tree-shakeable.
- *Example:* Fully typed API with no `any` in public signatures.
- [Feature]: [one-line benefit]
- [Feature]: [one-line benefit]
- [Guarantee, for example "No network access, no global state"]

## Installation

<!-- Guidance: Give the command for every package manager your users actually use. Mention peer dependencies and minimum runtime versions here, not later. -->

Install with your package manager of choice:

```bash
npm install [library-name]
pnpm add [library-name]
yarn add [library-name]
bun add [library-name]
```

[If relevant: for Deno, import from `npm:[library-name]`. For a CDN,
use a pinned version URL such as `https://cdn.jsdelivr.net/npm/[library-name]@1.4.2/+esm`.]

Peer dependencies: [none / `react >= 18`].

## Quick start

<!-- Guidance: The smallest complete program that shows the main value. It should be copy-paste runnable, including imports, and print or return something visible. -->

The example below parses a duration, adds it to a date and formats the
result:

```ts
import { parseDuration, formatDuration, addDuration } from "[library-name]";

const d = parseDuration("P1DT2H30M");
console.log(d.totalSeconds);               // 95400
console.log(addDuration(new Date("2026-01-01T00:00:00Z"), d).toISOString());
// 2026-01-02T02:30:00.000Z
console.log(formatDuration(d, { style: "long" }));
// "1 day, 2 hours, 30 minutes"
```

## Usage examples

<!-- Guidance: Three to five task-oriented examples for the most common jobs. Title each by the task ("Validate user input"), not the function name. -->

### Validate user input

Use the non-throwing variant when parsing input you do not control:

```ts
import { safeParseDuration } from "[library-name]";

const result = safeParseDuration(form.get("timeout"));
if (!result.ok) {
  showError(result.error.message); // "Expected a designator after '5'"
}
```

### Compare and sort durations

Durations compare by total length, so `PT90M` equals `PT1H30M`:

```ts
import { compareDurations } from "[library-name]";

items.sort((a, b) => compareDurations(a.duration, b.duration));
```

### [Task name]

[One sentence describing the task, followed by a short code example.]

## API overview

<!-- Guidance: A table of the public surface with one line per export. Link each name to the full reference. Mark experimental APIs clearly. -->

| Export | Signature | Description |
|---|---|---|
| `parseDuration` | `(input: string) => Duration` | Parses an ISO 8601 duration; throws `DurationSyntaxError` on invalid input |
| `safeParseDuration` | `(input: string) => Result<Duration>` | Same as `parseDuration` but returns a result object |
| `formatDuration` | `(d: Duration, opts?: FormatOptions) => string` | Formats as ISO, short or long human text |
| `addDuration` | `(date: Date, d: Duration) => Date` | Returns a new date; does not mutate the input |
| `compareDurations` | `(a: Duration, b: Duration) => -1 \| 0 \| 1` | Orders by total length |
| [`exportName`] | [`signature`] | [Description; mark "(experimental)" if not covered by SemVer] |

Full reference: [https://example.com/docs/api].

## Configuration

<!-- Guidance: Every option with type, default and effect. If configuration is global, explain how to scope it; if per call, show both forms. -->

Options are passed per call. Defaults are chosen to be safe for user input.

| Option | Type | Default | Effect |
|---|---|---|---|
| `style` | `"iso" \| "short" \| "long"` | `"iso"` | Output format of `formatDuration` |
| `locale` | `string` | `"en"` | Locale for long and short formats |
| `maxLength` | `number` | `64` | Rejects longer input to bound parsing cost |
| `allowNegative` | `boolean` | `false` | Accepts a leading minus sign |
| [`option`] | [type] | [default] | [effect] |

## Compatibility

<!-- Guidance: State what is tested in CI, not what probably works. Say what happens when a runtime reaches end of life. -->

| Environment | Supported versions | Tested in CI |
|---|---|---|
| Node.js | 20, 22, 24 | Yes |
| Browsers | Last two versions of Chrome, Edge, Firefox, Safari | Yes, via Playwright |
| Deno | 2.x | Yes |
| Bun | 1.x | Smoke test only |
| TypeScript | 5.4 and later | Yes |
| Module formats | ESM, CommonJS | Yes |

Support for a runtime version is dropped only in a major release, after
that runtime reaches end of life.

## Versioning

<!-- Guidance: Explain your SemVer contract precisely: what counts as public API, how deprecations work, and how long old majors get fixes. -->

This project follows [Semantic Versioning 2.0.0](https://semver.org):

- **Major** releases may change or remove public API. Each comes with a migration guide in [docs/migrations/].
- **Minor** releases add features in a backward-compatible way.
- **Patch** releases fix bugs without changing documented behaviour.

Public API means the exports listed above and their documented types.
Anything marked experimental or exported from `[library-name]/internal`
may change in any release. Deprecated APIs log a warning for at least one
minor release before removal. The previous major version receives security
fixes for [12] months after a new major is released. See
[CHANGELOG.md](CHANGELOG.md) for release history.

## Troubleshooting and FAQ

<!-- Guidance: Answer the questions that arrive most often as issues. Each answer should be short and link to detail. Review closed issues every release for new entries. -->

**Why does `parseDuration("P1M")` not equal 30 days?**
Months and years have no fixed length. They are kept as calendar units
and resolved only when added to a specific date with `addDuration`.

**I get `ERR_REQUIRE_ESM` in an older project.**
Use the CommonJS entry point with `require("[library-name]")` on Node.js
20 or later, or upgrade the project to ES modules. Older Node.js versions
are not supported.

**Does it work in a Content Security Policy without `unsafe-eval`?**
Yes. The library never uses `eval` or `new Function`.

**[Frequent question]**
[Short answer and a link to the relevant documentation page.]

## Alternatives

<!-- Guidance: An honest comparison builds trust and saves users time. Say when another library is the better choice. -->

| Library | Choose it when | Choose [library-name] when |
|---|---|---|
| *Example:* [date-library-a] | You need full time-zone and calendar arithmetic | You only need durations and want a tiny bundle |
| *Example:* Temporal API | Your runtimes support it natively | You must support runtimes without Temporal |
| [Alternative] | [Its strength] | [Your strength] |

## Contributing

<!-- Guidance: Point to CONTRIBUTING.md and give the three commands a contributor needs. Say which kinds of contribution are most welcome. -->

Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) and the
[Code of Conduct](CODE_OF_CONDUCT.md) first. To work on the library:

```bash
git clone https://github.com/[org]/[library-name].git
cd [library-name] && pnpm install
pnpm test
```

Good first contributions: [documentation fixes, new locale files, issues
labelled `good first issue`].

## Security

<!-- Guidance: Never ask people to report vulnerabilities in public issues. Link SECURITY.md and give a private channel. -->

Please do not report security vulnerabilities in public issues. Use
[GitHub private vulnerability reporting / security@example.com] as
described in [SECURITY.md](SECURITY.md). We aim to acknowledge reports
within [3] working days.

## Licence

[MIT](LICENSE) © YYYY [Copyright holder]. Third-party notices, if any, are
listed in [THIRD_PARTY_NOTICES.md].

## Standard and licence note

Based on common industry practice for open-source library READMEs and on
Semantic Versioning 2.0.0 (semver.org, CC BY 3.0) for the versioning
policy. Original text written for this collection; the example library is
fictional. Template licence: MIT.
