ISO-8601 Date-Time Builder

Construct a valid ISO-8601 date-time string from parts

Free ISO-8601 date-time builder. Enter year, month, day, hour, minute, second and UTC offset to assemble a well-formed ISO-8601 timestamp, with validation for each field. Runs entirely in your browser. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What does a valid ISO-8601 date-time look like?

It follows the pattern YYYY-MM-DDThh:mm:ss followed by a timezone designator, for example 2026-06-06T14:30:00+01:00 or 2026-06-06T13:30:00Z. The T separates the date from the time.

ISO-8601 is the international standard for representing dates and times as text. A correctly built ISO-8601 string sorts chronologically as plain text, is unambiguous across locales, and is accepted by virtually every programming language and database. This tool lets you assemble one field-by-field and validates each part so you never emit an impossible date.

How it works

The builder zero-pads each component to the right width and joins them in the canonical order:

YYYY-MM-DDThh:mm:ss±hh:mm

Before producing output it validates the calendar date. The number of days in a month depends on the month and, for February, on whether the year is a leap year. A year is a leap year if it is divisible by 4, except century years which must also be divisible by 400:

const leap = (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0;
const daysInMonth = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

The time fields are checked against their ranges (hour 0–23, minute and second 0–59), and the timezone is rendered either as Z for UTC or as a signed ±hh:mm offset. As a final check, the assembled string is passed to Date.parse to confirm the runtime accepts it.

Worked examples

Example 1 — local business hour: Year 2026, month 6, day 6, 14:30:00 at offset +01:00 produces:

2026-06-06T14:30:00+01:00

Example 2 — same instant in UTC: Switching the offset to Z and the hour to 13 represents the identical moment:

2026-06-06T13:30:00Z

Example 3 — midnight UTC at year start: Year 2027, month 1, day 1, 00:00:00 at Z:

2027-01-01T00:00:00Z

Example 4 — leap-year validation: Entering February 29, 2028 is valid (2028 is a leap year: 2028 ÷ 4 = 507, not a century year). Entering February 29, 2027 is rejected — 2027 is not a leap year.

Why you should always include the timezone designator

A datetime string without any timezone — like 2026-06-06T14:30:00 — is technically a local datetime in ISO-8601. Its meaning is entirely context-dependent. If the string is read in a different timezone than it was written, the moment it refers to changes silently.

The fix is simple: always append Z for UTC, or the explicit offset +hh:mm / -hh:mm for a local time. The builder in this tool always emits a designator, so you cannot accidentally produce an ambiguous string.

Choosing between Z and an offset

Use Z whenUse ±hh:mm when
Storing timestamps in databases or logsPreserving the local civil time that was in effect
Comparing times across regionsDisplaying to users in their own timezone
Writing API payloads that will be consumed globallyRecording times in contexts where the local offset matters (flight schedules, legal deadlines)

For most server-side storage and API design, UTC (Z) is the safest default. Convert to a local offset only at display time.

Common mistakes this tool prevents

  • Impossible dates like 2027-02-29 (not a leap year) or 2026-04-31 (April has 30 days) — the builder rejects these with a clear error message.
  • Out-of-range times like hour 25 or minute 61.
  • Missing T separator — a space between date and time is tolerated by some parsers but is not valid ISO-8601 extended format. The builder always uses T.
  • No timezone — every output from this tool includes a designator so the timestamp is unambiguous.