# Numbers and dates

> Korean units, K/M, "in millions", currency, decimals, date patterns and time zones.

Source: https://82chart.com/en/docs/numbers-dates/

Axis ticks are short; tooltips and tables are exact. On English pages the axis reads **12.3K · 340M** and the tooltip **123,456,789**; on Korean pages the axis uses 만·억.

## numberFormat

| Value | 12,345 → | 340,000,000 → | Used for |
| --- | --- | --- | --- |
| `'korean'` | 1.2만 | 3.4억 | Default on Korean pages |
| `'compact'` | 12.3K | 340M | Default in other languages |
| `'comma'` | 12,345 | 340,000,000 | Reports that need exact numbers |
| `'percent'` | 12,345% | - | Values that already are percents (pass 50, not 0.5) |
| a function | `(v) => string` |  | Used for the axis and the tooltip |

To change only the axis ticks, give the same value to `yAxis: { format }` (or `xAxis`). The helpers are exported too.

```js
import { korean, compact, comma } from '@82chart/core';
korean(123456789);  // '1.2억'
compact(123456789); // '123.5M'
comma(1234.5);      // '1,234.5'
```

## "In millions" reports

For report-style axes in millions with commas, divide with `scale` and add a `unit`. With a `scale`, the axis, tooltip and table all show the divided number with the unit, while the headline `value` stays the full amount. State the unit in a `footnote`.

```js
createChart('#chart', {
  type: 'bar',
  title: 'Revenue by division',
  scale: 1000000,
  unit: 'M',
  footnote: 'In millions of won',
  data: {
    labels: ['Domestic', 'Overseas', 'Online', 'Wholesale'],
    series: [{ name: 'Revenue', data: [1820000000, 940000000, 2310000000, 610000000] }],
  },
});
```

| Option | What it does |
| --- | --- |
| `unit` | After the value: `'%'`, `' users'`, `'M'` |
| `prefix` | Before the value: `'$'`, `'₩ '`. With `scale`, the tooltip shows the full amount ($1,820,000,000) |
| `scale` | Divide axis ticks by this (1000000 → millions) |
| `decimals` | Decimals in tooltips and labels (default: up to 2, trailing zeros trimmed) |

## Dates

Time axis labels follow the spacing: months as `Jan · Feb` (with the year when it changes), days as `Oct 21`, hours as `09:00`. Tooltips show the full date. Pass a pattern to `dateFormat` to choose yourself.

| Token | Meaning | Example |
| --- | --- | --- |
| `YYYY` / `YY` | Year | 2026 / 26 |
| `M` / `MM` | Month | 3 / 03 |
| `MMM` | Month name (languages that have them) | Mar |
| `D` / `DD` | Day | 7 / 07 |
| `ddd` | Weekday | Tue |
| `H` / `HH` | Hour | 9 / 09 |
| `mm` / `ss` | Minutes / seconds | 05 / 30 |

```js
createChart('#chart', {
  type: 'line',
  dateFormat: 'MMM D (ddd)', // Oct 21 (Tue)
  data: { series: [{ name: 'Visitors', data: [['2026-10-20', 1820], ['2026-10-21', 2140]] }] },
});
```

`dateFormat` is used for both the axis and the tooltip; `'auto'` is the default behaviour.

## Time zone (timeZone)

Dates are read and written in the runtime's zone by default. That is fine in browsers, but servers (Cloudflare Workers, most Node hosts) run on UTC, so `renderToSVG` there puts Korean midnight data on the previous day. Give `timeZone` an IANA name and the axis, tooltip, table and CSV all use that zone. Date-only strings such as `'2026-10-21'` are that day in the zone, and `'2026-10-21T09:00'` without an offset is 9 o'clock there.

```js
createChart('#chart', {
  type: 'line',
  timeZone: 'America/New_York', // the same labels wherever it runs
  data: { series: [{ name: 'Orders', data: [['2026-10-21T04:00:00Z', 120], ['2026-10-21T10:00:00Z', 180]] }] },
});
```

An unknown zone name logs one warning and falls back to the runtime zone. The exported helper `formatDate(date, pattern, locale, timeZone)` takes the zone as its fourth argument.
