Developer Tool

ISO 8601 Duration Converter

Parse duration strings like PT1H30M into seconds and readable parts, or build new ones from fields, with calendar-aware end-date math.

API developers, integration engineers, and anyone configuring time-based limits meet ISO 8601 durations in Google API parameters, JSON Schema definitions, Slack scheduled message fields, PostgreSQL-style intervals, and schema.org media metadata. When to use it: Turning PT45M from a response into minutes for a timeout, building P30D for a retention policy, checking whether P1M or P30D matches a billing rule, or finding the end date a subscription window produces. What it solves: Validates component order and the T separator, breaks every unit out, computes exact totals for fixed units while flagging the estimates behind Y and M, builds correctly ordered strings from field inputs, and applies durations to a start date with real month and leap-year arithmetic. Why it matters: A misread M silently switches months and minutes, and duration math involving month lengths is where scheduling bugs hide.

Years0
Months0
Weeks0
Days0
Hours0
Minutes0
Seconds0
Canonical—

Readable: —

Exact seconds—
Exact minutes—
Days (avg basis)—

End date: —


Build a duration from parts

P1D

Readable: 1 day

How ISO 8601 Duration Parsing Works

The parser matches the input against the canonical pattern: an optional sign, the letter P, up to four date units in the fixed order Y, M, W, D, then an optional T followed by H, M, S in that order. A lookahead rejects strings with no components at all, so bare "P" or a trailing "T" fails with a specific message instead of silently parsing as zero.

Once matched, each unit is converted to a number with decimal support, using either a period or a comma as the separator because ISO 8601 allows both. The canonical form is then rebuilt from the parsed values in strict order, which normalizes casing (lowercase p and t are accepted on input) and removes redundant zeros.

Total calculations split into two paths. When the duration contains only weeks, days, hours, minutes, and seconds, totals are exact because every one of those units has a fixed length. The moment years or months appear, the tool switches to labeled estimates using 365.2425 days per year and 30.436875 days per month, the same average basis used across scheduling libraries, and the notes panel states the assumption out loud.

End-date math applies years and months first with calendar clamping, so adding one month to January 31 lands on February 28 or 29 rather than rolling into March. Days and clock units are added afterward in fixed milliseconds. This order matches how subscription and billing systems advance periods.

Before / After Examples

Example 1: API Timeout String to Seconds

Before (Duration from an API response)

"idleTimeout": "PT45M"

<!-- Config wants an integer -->

After (Parsed totals)

minutes: 45
seconds: 2700
human:   45 minutes
exact:   yes (no Y/M units)

Example 2: Mixed Date and Time Components

Before (Raw config value)

P1DT2H30M

<!-- M before T vs after T? -->

After (Components + exact seconds)

days: 1  hours: 2  minutes: 30
seconds: 95400
human:   1 day, 2 hours, 30 minutes
canonical: P1DT2H30M

Example 3: Calendar Month vs Fixed Days

Before (Start date and two candidates)

start: 2026-01-31
A: P1M
B: P30D

<!-- Which matches billing? -->

After (Calendar-aware results)

A → 2026-02-28  (clamped month end)
B → 2026-03-02  (fixed 30 days)
note: P1M is exact only on a calendar

Use Cases

Developer Production Workflow
Convert a PT45M response field into seconds for a client timeout Check retention configs that mix P30D and P1M windows Review API documentation examples against the spec pattern
Build valid duration strings for a JSON Schema definition Compute expected end dates for billing cycle tests Explain the T separator to a teammate with live output
Validate negative durations accepted only under ISO 8601-2 Audit scheduler defaults for accidental month/minute mixups Convert legacy second counts into portable duration strings
Round-trip durations between a Go service and a JS client Verify P1M vs P30D behavior before a plan migration Document exact vs estimated totals in an integration guide

Common Mistakes & Troubleshooting

Reading M as minutes when it sits before the T

In P10M the M is ten months; in PT10M it is ten minutes. Configuration authors make this swap constantly, and the result is a ten-month timeout or a ten-minute billing period. Split the string at T before interpreting any M.

❌ Read P30M as "30 minutes"
✅ P30M = 30 months · PT30M = 30 minutes

Treating P1M as a fixed 30-day span

Calendar months vary between 28 and 31 days, so a P1M subscription from the 31st clamps to the 28th in February. If the product requires exactly thirty days, write P30D and test the rollover explicitly.

❌ from Jan 31 add P1M, expect Feb 31
✅ Expect Feb 28 (clamped) or use P30D

Reporting seconds totals that include years

Multiplying P1Y by 31,536,000 seconds assumes a 365-day year and drifts by a full day against leap years. Any total spanning Y or M is an estimate, so label it or compute it from an actual start date instead.

❌ P1Y == 31536000s (always)
✅ Exact only for W/D/H/M/S; Y/M need a start date

Putting the T before any date units

PT1H30MDP1D is not a duration. Date units come first, then T, then time units, and T must appear only when time units follow. Strict parsers reject anything else, which surfaces as a validation error during integration tests.

❌ P1DT2H extra T or reversed parts
✅ P[nY][nM][nW][nD]T[nH][nM][nS]

Assuming every parser accepts a leading minus

Negative durations are an ISO 8601-2 extension. Some libraries treat the sign as a parse error, and others negate components silently. This tool accepts the sign and flags it so you can decide whether the consumer upstream supports it.

❌ Send -PT30M to a strict ISO 8601-1 parser
✅ Test the consumer first; fall back to a separate sign field

Best Practices

✓

Use clock units for timeouts

Session limits, cache TTLs, and poll intervals should be PT or PD so their length never changes with the calendar.

✓

Use calendar units for billing periods

Monthly and yearly plans should stay in P1M and P1Y so renewals land on the same day-of-month the customer signed up on.

✓

Label estimated totals

Whenever Y or M appears, present the seconds figure as an average or derive it from a concrete start date rather than implying exactness.

✓

Keep the T separator on both writer and reader

Writing PT0S for an empty duration and requiring the separator in your parser prevents months-versus-minutes confusion across services.

✓

Normalize casing before comparison

ISO allows lowercase p and t. Rebuild durations through a parser so "pt30m" and "PT30M" compare equal in golden tests.

✓

Test month-end and leap-day cases

January 31 plus P1M and February 29 plus P1Y expose clamping bugs that only fire once a year. Add them to scheduled test suites.

✓

Fractions on the smallest unit only

PT0.5H is accepted widely; P0.5M is not. Keep decimal precision on seconds to survive strict validators.

✓

Parse once at system boundaries

Convert duration strings into milliseconds at ingestion and keep numbers internally, so every downstream module shares one interpretation.

Frequently Asked Questions

What is an ISO 8601 duration? +

An ISO 8601 duration is a string that expresses a length of time using the pattern P followed by date units and, after a T separator, time units. Examples include PT30M for thirty minutes, P1DT2H30M for one day two hours thirty minutes, and P1Y2M3DT4H5M6S for one year two months three days four hours five minutes six seconds. The format is language-independent, so APIs, XML schemas, and databases can exchange time spans without locale ambiguity.

Why does the format need a T separator? +

The letter M means months when it appears in the date part and minutes when it appears in the time part. The T separator disambiguates the two halves: everything before T uses calendar units, and everything after T uses clock units. Without it, P10M would be indistinguishable from ten minutes versus ten months, which is exactly the kind of ambiguity that breaks billing cycles and session timeouts.

How do I convert a duration to seconds? +

Weeks, days, hours, minutes, and seconds convert exactly: multiply each unit by its fixed length and add the results. Years and months have no fixed length, so any seconds total that includes them is an estimate based on average year and month lengths. This tool computes exact totals for fixed units and clearly marks estimated totals whenever Y or M components are present.

What is the difference between P1M and PT30D? +

P1M is one calendar month, which is 28 to 31 days depending on where it lands, while PT30D is a fixed span of exactly thirty days (actually written P30D when days appear in the date part). A subscription renewed with P1M from January 31 falls on February 28, then March 31, whereas a thirty-day period drifts earlier each cycle. Pick calendar months for billing semantics and fixed days for timeouts.

Can durations be negative or fractional? +

ISO 8601-2 allows a leading plus or minus sign, which this tool accepts and flags as an extension, because some parsers only handle unsigned durations. Decimal fractions are valid on the smallest unit present, for example PT1.5S or PT0.25H. Fractions on larger units like P0.5Y are rejected by strict profiles, so keep them on seconds when interoperability matters.

Which systems use ISO 8601 durations? +

JSON Schema uses the duration format for xs:duration-style validation, Google APIs use them for read windows and timeouts, Slack and other SaaS APIs accept them for scheduled parameters, PostgreSQL stores similar intervals, and schema.org uses Duration on media objects. Anywhere a configuration file needs a time span without picking a date, the P/DT pattern is the standard answer.

Is the parsing done on a server? +

No. The parser, the builder, and the date arithmetic all run as local JavaScript in the page. Durations from internal billing configs or unreleased API contracts are parsed in the tab and never transmitted. The end-date calculation uses your browser UTC calendar logic, so month-end and leap-year behavior follows the same rules as the rest of your JavaScript code.