アップロードなし, 100%ローカル, アカウントなし

記事

ISO 8601期間表記:P1DT2Hが意味するもの

YouTube APIのレスポンスでは、ある動画の長さがPT4M13Sと表示されます。カレンダーの招待にはP15DT5H0M20Sという値が含まれています。あるディレクトリサーバーはアカウントに20260424174227.0Zというタイムスタンプを付けますが、これは関連していそうに見えて実はまったく別物です。これらの簡潔な文字列には知っておく価値のあるルールがあり、読み方を誤ると分と月が入れ替わってしまいます。ここではISO 8601の期間表記を一通り見ていきます:各文字が何を意味するか、このフォーマットがどこに現れるか、そして最大の注意点、つまりこの書き方の期間が常に一定の時間の長さとは限らないという点です。

P、T、そして各文字の意味

ISO 8601の期間はP(period)で始まります。続いて日付の構成要素が来て、それぞれ数値のあとに単位を表す文字が付きます:Yは年、Mは月、Wは週、Dは日です。Tは日付部分と時間部分を区切ります:Hは時、Mは分、Sは秒です。すべての構成要素は省略可能で、必要なものだけを書きます。PT15Mは15分、P1DT2Hは1日と2時間、P3Wは3週間です。Tは単なる飾りではありません:Mはその前では月、後では分を意味するため、P1Mは1か月、PT1Mは1分になります。最後に置かれた構成要素には、PT0.5S(0.5秒)のように小数の端数を付けられます。また各単位は自動的に繰り上がりません:PT90Mは1時間半を表す完全に有効な書き方です。

ISO 8601の期間P3Y6M4DT12H30M5Sの構造:Pが期間の始まりを示し、Y M Dが日付の単位、Tが時間部分への切り替え、H M Sが時間の単位

実際にこのフォーマットに出会う場面

この構文は気付かないうちにあちこちに存在します。YouTube Data APIはすべての動画の長さをISO 8601の期間(PT4M13S)として返します。HTMLはtime要素のdatetime属性で期間表記を受け付けます。カレンダーの招待でも使われます:iCalendar標準(RFC 5545)はイベントの長さをPT1H0M0Sのように書きますが、文法から年と月を除いています。XML Schemaのxs:durationは完全な形式をカバーし、負の期間を表す先頭のマイナス記号まで許容します。標準ライブラリはこれを直接パースできます:java.timeはPとTの文字列をPeriod.parseとDuration.parseで読み取り、多くの他の言語にも同様の使い分けがあります。機械可読なスケジュール、フィード、APIを作るなら、このフォーマットは「どのくらいの長さか」を表す共通言語です。

なぜP1Mは秒数として固定されないのか

PT15Mは常に900秒です。P1Mはそうではありません:1か月は開始位置によって28日、29日、30日、31日のいずれかになるため、P1Mは日付に紐付けて初めて具体的な値になります。P1Dでさえ24時間とは限りません。欧州連合では2026年3月29日の日曜日にサマータイムへ切り替わるため、その日は23時間しかなく、同じ土曜の夜にP1D(暦上の1日)を足す場合とPT24H(正確に24時間)を足す場合とで、到達する時刻が異なります。だからこそjava.timeには暦の単位を扱うPeriodと正確な秒数を扱うDurationという2つの型があり、日付ライブラリは期間を変換する前に基準日を求めるのです。Y、M、W、Dの構成要素は暦上の計算として、H、M、Sだけを固定の時間量として扱ってください。

期間ではない:20260424174227.0Z

20260424174227.0Zのような文字列は同じ仲間に見えるかもしれませんが、これは期間ではなくタイムスタンプであり、そもそもISO 8601でもありません。これはASN.1(LDAPディレクトリやX.509証明書で使われる記法)に由来するGeneralizedTimeという形式です。固定幅のフィールドとして読み解くと:年2026、月04、日24、続いて17:42:27、任意の小数部(.0)、そしてUTCを表すZです。これはActive DirectoryのwhenCreated属性やwhenChanged属性、LDAPのエクスポート、そして証明書の中で目にします。証明書についてはRFC 5280が2050年以降の有効期限にGeneralizedTimeを義務付けています。ISO 8601の簡潔な形式と見分ける決め手はTの欠如です:ISOであれば同じ瞬間を20260424T174227Zと書くはずです。

GeneralizedTime文字列20260424174227.0Zをフィールドごとに解読すると2026年4月24日17:42:27 UTCになる

仕様書を読まずに読み解く

単発の文字列を調べるだけなら、当サイトのISO期間変換ツールがP/T形式の期間を構成要素と合計秒数に分解し、入力した数値から文字列を組み立て直します。手元にあるのが期間の文字列ではなく2つの時刻(たとえば22:00から06:30までのシフト)である場合は、時間の長さ計算ツールが夜をまたぐ場合も含めて経過時間を計算します。どちらも完全にブラウザ内で完結し、入力した内容がお使いの端末の外に出ることはありません。ツールを使わずにざっと読むだけなら、2つのコツでほとんどのケースに対応できます:Tを探してMが月なのか分なのかを見極めること、そしてTより左側はすべて固定の秒数ではなく暦上の計算だと覚えておくことです。

この記事で紹介するツール

よくある質問

PT1MとP1Mは同じですか?

いいえ。文字MはTの区切りをまたぐと意味が変わります:P1Mは1か月、PT1Mは1分です。これはこのフォーマットで最もよくある誤読であり、これが原因でAPIのバグがリリースされたこともあります。迷ったらまずTを探してください:その前にあるものはすべて年・月・週・日で数え、その後にあるものはすべて時・分・秒で数えます。正しく書かれた期間には、Tの前に時間の単位が来ることも、Tの後に日付の単位が来ることもありません。

90分をISO 8601の期間として書くには?

PT90MとPT1H30Mはどちらも有効で、同じ長さの時間を表します。ISO 8601は各構成要素を通常の範囲に収めることを強制しないため、59を超える分や23を超える時も問題ありません。パーサーはどちらの書き方も受け付けますが、どちらを出力するかはシステムが正規化するかどうかによります。人が読むための期間を生成するならPT1H30Mの方が親切で、コードで期間を比較するなら文字列同士ではなく合計秒数で比較してください。まさに2つの異なる文字列が同じ意味を持ち得るからです。

期間(duration)と区間(interval)の違いは?

期間はどれだけの長さかを表すだけで、暦上の位置を持ちません:P3Dは3日間であり、どこから始まっても構いません。ISO 8601の区間はスラッシュを使って期間を実際の日付に固定します:2026-07-04T00:00:00Z/P3Dは2026年7月4日から始まる3日間を意味し、2026-07-04/2026-07-07という開始/終了のペアも同じ範囲を表します。R接頭辞を使った繰り返し区間もあります:R5/2026-07-04T00:00:00Z/P1Dはその開始日から5回の毎日の繰り返しを意味します。区間は暦上の単位が持つあいまいさを解消します。日付に紐付いたP1Mは常に一意の長さを持つからです。

出典