# Number and date filters

> Round numbers, pick plurals and format numbers and dates with Intl.

These filters round numbers and format numbers and dates for readers. Formatting uses the JavaScript `Intl` API, so it handles locales, currencies and time zones without extra libraries.

## `abs`

Returns the absolute value of a number.

page.kiln:

```kiln
{{ (-5)|abs }}
```

Output:

```html
5
```

Note the brackets. Filters bind tighter than a minus sign, so `-5|abs` means `-(5|abs)`.

## `round`

Rounds to a number of decimal places, 0 by default. The second argument is the method: `"common"` (the default, which rounds halves away from zero), `"ceil"` or `"floor"`.

page.kiln:

```kiln
{{ 3.14159|round(2) }}
{{ 2.5|round }}
{{ 2.1|round(0, "ceil") }}
```

Output:

```html
3.14
3
3
```

## `formatNumber`

Formats a number with `Intl.NumberFormat`. Pass any of its options as named arguments, plus `locale`. Option values must be strings, numbers or booleans, and an option name `Intl` doesn't know is an error.

page.kiln:

```kiln
{{ 1234567.891|formatNumber }}
{{ 49.5|formatNumber(style: "currency", currency: "GBP") }}
{{ 0.256|formatNumber(style: "percent") }}
{{ 1234.5|formatNumber(locale: "de-DE", minimumFractionDigits: 2) }}
```

Output:

```html
1,234,567.891
£49.50
26%
1.234,50
```

## `plural`

Picks the word or phrase that fits a number, using the plural rules of the render's locale. Pass the forms as named arguments. Every `#` in the chosen form becomes the number, formatted for the locale.

page.kiln:

```kiln
{{ 1|plural(one: "# item", other: "# items") }}
{{ 1200|plural(one: "# item", other: "# items") }}
{{ 3|plural("item", "items") }}
```

Output:

```html
1 item
1,200 items
items
```

- Two forms without names are `one` and `other`, which covers English.
- `other` is required. It is used when the locale's form for the number isn't passed.
- The names are the ones `Intl.PluralRules` uses: `zero`, `one`, `two`, `few`, `many` and `other`. Which a number gets depends on the language. In English, 0 is `other`, so use `if` for wording like "No items".
- Pass `type: "ordinal"` for positions, such as 1st and 2nd, and `locale` to use another language's rules.

page.kiln:

```kiln
{{ 22|plural(one: "#st", two: "#nd", few: "#rd", other: "#th", type: "ordinal") }}
{{ 5|plural(one: "# plik", few: "# pliki", many: "# plików", other: "# pliku", locale: "pl") }}
```

Output:

```html
22nd
5 plików
```

## `formatDate`

Formats a date with `Intl.DateTimeFormat`. It accepts a `Date`, an ISO 8601 string or milliseconds since 1970. A day past the end of its month, such as `2026-02-30`, is an error. Pass any of its options as named arguments, plus `locale` and `timeZone`. Option values must be strings, numbers or booleans. The default style is `dateStyle: "medium"`, unless you pass an option that chooses what to show, such as `timeStyle`, `month` or `hour`.

page.kiln:

```kiln
{{ "2026-10-15"|formatDate }}
{{ "2026-10-15"|formatDate(dateStyle: "long", locale: "en-GB") }}
{{ "2026-10-15T14:30:00Z"|formatDate(timeStyle: "short", timeZone: "Europe/London") }}
{{ "2026-10-15"|formatDate(weekday: "long", day: "numeric", month: "long") }}
```

Output:

```html
Oct 15, 2026
15 October 2026
3:30 PM
Thursday, October 15
```

A date and time without an offset, such as `2026-10-15T10:00`, is read as UTC. So is a date on its own: `2026-10-15` is midnight UTC, which a time zone behind UTC, such as `America/New_York`, shows as the day before. Pass `timeZone: "UTC"` to show a date on its own as written.

page.kiln:

```kiln
{{ "2026-10-15"|formatDate(timeZone: "America/New_York") }}
{{ "2026-10-15"|formatDate(timeZone: "UTC") }}
```

Output:

```html
Oct 14, 2026
Oct 15, 2026
```

## Locale and time zone

These filters use the render's locale and time zone unless you pass them. These default to `"en"` and `"UTC"`, so output is the same on every server. Set them for the environment or for one render. See [Creating an environment](https://kilnlang.com/docs/api/create-kiln/#options).

## Missing values

`formatNumber`, `plural` and `formatDate` print nothing for null. An empty field never turns into 0 or today's date.

page.kiln:

```kiln
<time>{{ post.publishedAt|formatDate }}</time>
```

Output:

```html
<time></time>
```
