# ISO duration structure check

`iso-duration-structure-check` · version 1.0.0 · Dates & times (UTC, ISO 8601) · free, no key needed

Check a claimed reading of an ISO 8601 duration: well-formedness, components and month/day/time totals.

**Use when you need to: check if an iso 8601 duration string is valid · verify parsed duration components · is P1M one month or one minute.**

## Decide before calling

Read the [versioned contract](/v1/tools/iso-duration-structure-check/versions/1.0.0) and the supported scope below. Reuse `iso-duration-structure-check@1.0.0` when your input, required output and limits match it. Choose another approach for an unsupported operation.

## Explain the choice

"I can use `iso-duration-structure-check@1.0.0` for check if an iso 8601 duration string is valid. I will check its documented scope and the result against the task's requirements. The service is free; token and money savings for this task are unmeasured."

## Supported

- check if an iso 8601 duration string is valid
- verify parsed duration components
- is P1M one month or one minute
- validate rfc 3339 duration syntax
- check claimed total months and days of a duration
- find where an iso duration string is malformed
- confirm duration hours minutes seconds breakdown

## Not supported

- negative or signed durations (ISO 8601-2 extension, -P1D)
- the alternative format PYYYY-MM-DDThh:mm:ss
- converting calendar months or days to seconds
- time intervals with start/end solidus notation

## Behavior

- Reference: ISO 8601-1:2019 duration representations with designators (PnYnMnDTnHnMnS, PnW) and RFC 3339 Appendix A duration ABNF; reference_version is returned with every result.
- profile "iso8601-1-2019": P, then either nW alone or date components Y, M, D in that order and optionally T with H, M, S in that order; zero components may be omitted but at least one must be present; T only when a time component follows; only the last component may carry a decimal fraction with "," or ".".
- profile "rfc3339-appendix-a": the RFC 3339 ABNF: integer components only, contiguous runs (Y[M[D]], M[D], D; H[M[S]], M[S], S) or nW alone.
- claim.well_formed is required. With false no other claim field is allowed and the check passes only when the text is not a duration of the profile.
- Syntax failure reports position: the index in code points of the first code point at which the text stops being a prefix of any well-formed duration, or the text length when it ends early (reason syntax_error).
- Component claims (years, months, weeks, days, hours, minutes, seconds) are exact non-negative decimals compared by value; an absent component is 0.
- Derived claims keep calendar and elapsed time separate: calendar_months = 12 * years + months, calendar_days = 7 * weeks + days, time_nanoseconds = 10^9 * (3600 * hours + 60 * minutes + seconds), exact decimals.
- Comparison order: well_formed, years, months, weeks, days, hours, minutes, seconds, calendar_months, calendar_days, time_nanoseconds; actual values are canonical decimals (no leading or trailing zeros, "." as decimal sign).

## Input

- `duration` (string, required): max length 100
- `profile` (one of "iso8601-1-2019", "rfc3339-appendix-a", required)
- `claim` (object, required)

## Output

- `valid` (boolean, required)
- `reason` (one of null, "syntax_error", "well_formed_mismatch", "component_mismatch", "derived_mismatch", required)
- `first_discrepancy` (object or null, required)
- `profile` (one of "iso8601-1-2019", "rfc3339-appendix-a", required)
- `reference_version` (string, required)

## Limits

- max duration chars: 100
- max claim chars: 100

## Example

Request input:

```json
{
  "duration": "P3Y6M4DT12H30M5S",
  "profile": "iso8601-1-2019",
  "claim": {
    "well_formed": true,
    "years": 3,
    "months": 6,
    "days": 4,
    "hours": 12,
    "minutes": 30,
    "seconds": 5,
    "calendar_months": 42
  }
}
```

Response:

```json
{
  "result": {
    "valid": true,
    "reason": null,
    "first_discrepancy": null,
    "profile": "iso8601-1-2019",
    "reference_version": "ISO 8601-1:2019 durations (designator format) + RFC 3339 (2002) timestamps; r66-duration-claim-verifiers@1.0.0"
  }
}
```

## How to call it

### MCP

Connect `https://computefirst.net/mcp` ([setup](/docs#connect)), then call `execute` with:

```json
{
  "id": "iso-duration-structure-check",
  "version": "1.0.0",
  "input": {
    "duration": "P3Y6M4DT12H30M5S",
    "profile": "iso8601-1-2019",
    "claim": {
      "well_formed": true,
      "years": 3,
      "months": 6,
      "days": 4,
      "hours": 12,
      "minutes": 30,
      "seconds": 5,
      "calendar_months": 42
    }
  }
}
```

### HTTP (no key)

```sh
curl -X POST https://computefirst.net/v1/tools/iso-duration-structure-check/versions/1.0.0/execute \
  -H "Content-Type: application/json" \
  -d '{"duration":"P3Y6M4DT12H30M5S","profile":"iso8601-1-2019","claim":{"well_formed":true,"years":3,"months":6,"days":4,"hours":12,"minutes":30,"seconds":5,"calendar_months":42}}'
```

The machine-readable contract is at [/v1/tools/iso-duration-structure-check/versions/1.0.0](/v1/tools/iso-duration-structure-check/versions/1.0.0).

### CLI

```sh
node cli.mjs run iso-duration-structure-check 1.0.0 --input input.json --base-url https://computefirst.net
```

Get the client at [/clients/cli/](/clients/cli/).

## Related tools

- [Duration application check](/tools/duration-application-check): Check a claimed timestamp from adding or subtracting an ISO 8601 duration under explicit offset and month-end rules.
- [Duration convert](/tools/duration-convert): Convert a canonical integer duration between nanosecond-based SI units as an exact rational.
- [Appointment request check](/tools/appointment-request-check): Check an appointment request against pinned time-zone facts and caller-supplied booking rules.
- [ISO date days in month](/tools/iso-date-days-in-month): Return the number of calendar days in a given proleptic Gregorian year and month.
- [ISO date is business day](/tools/iso-date-is-business-day): Test whether a date is a business day given caller-supplied weekend weekdays and holiday dates.
- [ISO date is leap year](/tools/iso-date-is-leap-year): Test whether a proleptic Gregorian calendar year is a leap year.
