# Dates

> Reading calendar dates in the many forms people write them, and showing them as their locale does.

A calendar date is a day, without a time or a time zone. People write dates in
many forms, and expect any of them to be understood; they read dates in the form
their language uses.

## Best practices

**Show dates as the reader's locale writes them.** The order of day, month and
year, the separators, and the names of months all follow the language of the
interface: Oct 3, 2026 in American English, 3 Oct 2026 in British, 03.10.2026 in
German, 2026/10/03 in Japanese. Where the day of the week helps — a deadline, a
meeting — show it with the date: Tue, Oct 13, 2026.

**Read any reasonable form.** Accept numbers with any separator; month names in
full or abbreviated; the locale's own labelled form, such as 2026年10月13日;
digits alone; and full-width characters from an input method. Whatever a field
shows, it reads back.

**Read what the person meant, or refuse; never guess.** A reading that is right
for some entries and silently wrong for others is worse than none: a pasted
column of day-first dates read month-first comes out half right. Where what was
typed is not a date as the locale writes one, say so and leave it as typed.

**Complete a partial date from today.** A date without a year is in the current
year; a day alone is in the current month. A two-digit year is the one nearest to
today, and no more than twenty years ahead. A year is two digits or four: three
are a slip of the hand, not a year.

**Resolve ambiguity by the locale, not by trial.** Numbers are read in the
locale's order. Four digits first are a year everywhere, so 2026-10-13 always
reads. Day and month are never exchanged to make a date of numbers that are not
one: 13/04 in an American field is refused, not read as 13 April.

**Ignore a weekday beside a date; read one alone.** Tuesday, October 13 is
13 October, and so is 10月13日(火). A weekday alone is the next such day, today
included.

**Understand relative words and counts.** Today, tomorrow and yesterday, and the
words for the days either side of them where the language has them — 明後日,
übermorgen — are dates. A number with a sign counts days from today: +3, -1. With
a letter it counts days, weeks, months or years: 3d, 2w, -1m, +1y.

**Read the years of an era.** In Japanese, 令和8年10月13日 and R8.10.13 are
13 October 2026. A short year with 年 and no era is the era's year or the
century's, whichever is nearer today.

**Take the date from a timestamp as written.** 2026-10-13T09:30:00Z is
13 October, whatever the reader's time zone: a pasted timestamp names a day, and
converting it would move some of them.

**Never invent a date.** 30 February is a mistake, not 2 March. Refuse it, so the
mistake is seen.

**Refuse a date outside the range; do not move it.** A date before the earliest
or after the latest allowed stays as typed, marked, with the reason — moving it
to the nearest end commits a date nobody chose.

**Say why.** Distinguish nothing typed, text that is not a date, a date that
does not exist, and a date before or after the range, so the message can name
the problem.

**Keep a date a date.** Hold it without a time or zone — as year, month and day —
so it never shifts by a day when read in another time zone.

## Reading

How an American English field reads what is typed, on Tuesday 13 October 2026:

| Typed                  | Read as         | Because                                    |
| ---------------------- | --------------- | ------------------------------------------ |
| `10/20/2026`           | 20 October 2026 | the locale's order                         |
| `2026-10-20`           | 20 October 2026 | four digits first are a year               |
| `10/20`                | 20 October 2026 | completed with this year                   |
| `20`                   | 20 October 2026 | completed with this month                  |
| `1020`                 | 20 October 2026 | digits alone, in the locale's order        |
| `oct 20`, `20 October` | 20 October 2026 | a month named                              |
| `Tue, Oct 20`          | 20 October 2026 | a weekday beside a date is ignored         |
| `１０月２０日`         | 20 October 2026 | labelled fields, full-width                |
| `令和8年10月20日`      | 20 October 2026 | a year of an era                           |
| `2026-10-20T09:30:00Z` | 20 October 2026 | the time is dropped                        |
| `tomorrow`             | 14 October 2026 | relative to today                          |
| `+3`, `3d`             | 16 October 2026 | a count of days from today                 |
| `2w`                   | 27 October 2026 | a count of weeks                           |
| `fri`                  | 16 October 2026 | the next Friday                            |
| `1/2/47`               | 2 January 1947  | 2047 would be more than twenty years ahead |
| `20/10`, `2010`        | —               | twenty is not a month; nothing is swapped  |
| `1/1/202`              | —               | a year is two digits or four               |
| `2/30`                 | —               | there is no such day                       |

## Stepping

A step is a day; a large step a week; a page a month. A step in the month or year
keeps the day, or takes the last day of a month too short for it.

Stepping stops at the ends of the range. A step of days that would pass an end
lands on it. A step of a month or a year lands on the end when the end is in the
month or year stepped to; when no day of that month or year is allowed, the date
stays where it is rather than changing a part that was not stepped. A date
already outside the range steps towards it one step at a time, and never further
away.

See also [Editing values](https://ui.publictheta.com/foundations/use-field.md) and [Date field](https://ui.publictheta.com/components/date-field.md).

## Behaviour

Each statement is verified by a test in Chromium, Chromium (touch), Firefox, WebKit, WebKit (touch), unless it names the environments it applies to or is marked open.

### Reading

- What is shown reads back as the same date, in every locale and style.
- Numbers are read in the locale's order, with any separators.
- Four digits first are the year, whatever the locale.
- A date without a year is in this year; a day alone is in this month.
- A two-digit year is the one nearest today, at most twenty years ahead.
- A year of three digits, or of five, is not a year.
- Digits alone are a whole date, or a month and day in the locale's order.
- The day and the month are never swapped to make a date of what was typed.
- Months may be named, in the locale's language or English, in full or abbreviated.
- A weekday alongside the date is ignored.
- A word that names both a weekday and a month is the weekday where the month is given otherwise.
- In Japanese, each of the seven weekdays beside a date is ignored, in parentheses or not.
- In Korean, each of the seven weekdays beside a date is ignored, in parentheses or not.
- Fields labelled as East Asian languages write them are read by their labels.
- Full-width characters, as an input method types them, read the same.
- A year of a Japanese era is read, by the era's name or its initial.
- A year an era did not reach is not a date.
- In Japanese, a short year with 年 and no era is the era's or the century's, whichever is nearer today.
- The locale's words for today and the two days either side of it are dates.
- A number with a sign is that many days from today.
- With `d`, `w`, `m` or `y` after it, a number is days, weeks, months or years from today.
- Months or years from today end on the last day of a month too short for the day.
- A weekday alone is the next such day, today included.
- `next` or `last` with a weekday, such as `next friday`, is that day of the week after or before. *(open)*
- A weekday of a named week, such as 来週の金曜, is read. *(open)*
- The end of the month, such as 月末, is read. *(open)*
- A time written after a date is dropped; the date is the one written, in no other zone.
- A date that does not exist is not rolled over into one that does.
- A date outside the range is refused, naming the end it is beyond, not moved to it.
- Nothing typed is empty; anything else that is not a date is invalid.
- A locale's names are gathered once, however many fields read with them.
- Dates in calendars other than the Gregorian are read and shown. *(open)*

### Showing

- A date is shown as the locale writes dates.
- Its parts join to what is shown.
- The weekday is shown with the date when asked for, the date written as its style writes it.
- With its weekday, what is shown reads back as the same date, in every locale and style.
- A date is shown in the years of an era, such as 令和8年. *(open)*

### Showing, whatever is given

- The short style writes the year in full, so that a date reads back in its own century.
- A value that is not a date is shown as nothing, rather than failing or as another date.
- A locale that is not one is put right, not failed on.

### Stepping

- A step is a day; a large step a week; a page a month.
- A step in the month or the year changes that part alone.
- A step in the weekday is a day.
- A month too short for the day ends on its last day.
- A step of days that would pass the end of the range stops at the end.
- A step of a month or a year that would pass the end of the range stops at the end when the end is in the month or year stepped to; otherwise the date stays.
- A date outside the range steps towards it one step at a time, and never further from it.
- Stepping stops at the years 1 and 9999.
- Stepping an empty field starts from today, or from the end of the range nearest today.

## Reference implementation

React: `npx shadcn@latest add https://ui.publictheta.com/r/date-type.json`
