{"id":"duration-application-check","version":"1.0.0","description":"Check a claimed timestamp from adding or subtracting an ISO 8601 duration under explicit offset and month-end rules.","supported_operations":["check timestamp plus iso duration result","verify date after adding P1M to january 31","validate claimed end time of a duration","did the agent subtract the duration correctly","check month end clamping when adding months","audit rfc 3339 timestamp plus period"],"unsupported_operations":["IANA time zones or daylight-saving transitions (fixed offsets only)","leap seconds (second 60) and sub-nanosecond fractions","fractional years, months, weeks or days","business-day or holiday calendars"],"semantics":["Reference: ISO 8601-1:2019 durations with designators (years, months, weeks and days are nominal calendar units; hours, minutes and seconds are exact) and RFC 3339 section 5.6 date-time; reference_version is returned with every result.","start and claim timestamps: RFC 3339 date-time YYYY-MM-DDTHH:MM:SS[.1-9 digits](Z|+HH:MM|-HH:MM), T and Z may be lower case, years 0000-9999 proleptic Gregorian; second 60 and more than 9 fractional digits are unsupported_input.","duration: ISO 8601-1:2019 designator format; calendar components must be whole and the time part a whole number of nanoseconds (else unsupported_input).","offset_policy (required): keep_start_offset does the calendar steps on the local date in the start offset and writes the result in that offset (-00:00 stays -00:00); utc does them on the UTC date and writes Z.","Order of application: total months 12Y + M first (rollover policy on the local date), then 7W + D calendar days on the local date (time of day kept), giving calendar_result; then the exact time 10^9 (3600H + 60M + S) nanoseconds on the instant, giving result. direction subtract negates every component and keeps the same order.","rollover (required): clamp moves a nonexistent day to the last day of the month (Jan 31 + P1M = Feb 28/29); overflow carries the excess days into the next month (Jan 31 + P1M = Mar 2/3); reject makes the claim invalid with reason day_overflow_rejected and invalid_local_date.","Comparison order: claim.calendar_result (when given) then claim.result; each first by instant (difference_nanoseconds = claimed - actual), then by offset. A local date outside 0000-9999 gives reason result_out_of_range. actual is the canonical RFC 3339 text (uppercase T and Z, minimal fraction, Z for a zero offset)."],"limits":{"max_duration_chars":100,"max_timestamp_chars":64},"pricing":{"status":"unpriced","charge_usd":null},"input_schema":{"type":"object","additionalProperties":false,"required":["start","duration","direction","offset_policy","rollover","claim"],"properties":{"start":{"type":"string","minLength":20,"maxLength":64},"duration":{"type":"string","maxLength":100},"direction":{"type":"string","enum":["add","subtract"]},"offset_policy":{"type":"string","enum":["keep_start_offset","utc"]},"rollover":{"type":"string","enum":["clamp","overflow","reject"]},"claim":{"type":"object","additionalProperties":false,"required":["result"],"properties":{"calendar_result":{"type":"string","minLength":20,"maxLength":64},"result":{"type":"string","minLength":20,"maxLength":64}}}}},"output_schema":{"type":"object","additionalProperties":false,"required":["valid","reason","first_discrepancy","reference_version"],"properties":{"valid":{"type":"boolean"},"reason":{"type":["string","null"],"enum":[null,"day_overflow_rejected","result_out_of_range","calendar_instant_mismatch","calendar_offset_mismatch","instant_mismatch","offset_mismatch"]},"first_discrepancy":{"type":["object","null"],"additionalProperties":false,"required":["field","claimed","actual","difference_nanoseconds","invalid_local_date"],"properties":{"field":{"type":"string","enum":["calendar_result","result"]},"claimed":{"type":"string"},"actual":{"type":["string","null"]},"difference_nanoseconds":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$"},"invalid_local_date":{"type":["string","null"]}}},"reference_version":{"type":"string"}}},"examples":[{"input":{"start":"2024-01-31T10:00:00Z","duration":"P1M","direction":"add","offset_policy":"keep_start_offset","rollover":"clamp","claim":{"result":"2024-02-29T10:00:00Z"}},"output":{"valid":true,"reason":null,"first_discrepancy":null,"reference_version":"ISO 8601-1:2019 durations (designator format) + RFC 3339 (2002) timestamps; r66-duration-claim-verifiers@1.0.0"}},{"input":{"start":"2024-01-31T10:00:00Z","duration":"P1M","direction":"add","offset_policy":"keep_start_offset","rollover":"overflow","claim":{"result":"2024-02-29T10:00:00Z"}},"output":{"valid":false,"reason":"instant_mismatch","first_discrepancy":{"field":"result","claimed":"2024-02-29T10:00:00Z","actual":"2024-03-02T10:00:00Z","difference_nanoseconds":"-172800000000000","invalid_local_date":null},"reference_version":"ISO 8601-1:2019 durations (designator format) + RFC 3339 (2002) timestamps; r66-duration-claim-verifiers@1.0.0"}},{"input":{"start":"2024-03-09T12:00:00-05:00","duration":"P1DT12H","direction":"add","offset_policy":"keep_start_offset","rollover":"reject","claim":{"calendar_result":"2024-03-10T12:00:00-05:00","result":"2024-03-11T00:00:00-05:00"}},"output":{"valid":true,"reason":null,"first_discrepancy":null,"reference_version":"ISO 8601-1:2019 durations (designator format) + RFC 3339 (2002) timestamps; r66-duration-claim-verifiers@1.0.0"}}],"execute_url":"/v1/tools/duration-application-check/versions/1.0.0/execute"}