「ISO変換」とは何をするものか
「API は ISO 形式で日時を返してくる」「ログを ISO 形式で出したい」「他言語ともやり取りしたい」
そんなときに出てくるキーワードが ISO-8601 です。
ISO-8601 は、日時を2025-03-26T10:05:302025-03-26T10:05:30+09:002025-03-26T01:05:30Z
のように、世界中で共通に解釈できる形で表現するルールです。
Java の日付・時間APIは、この ISO-8601 を“ど真ん中”に据えて設計されています。
だから「ISO変換」は、Java にとって一番得意な領域だと思って大丈夫です。
Java の ISO フォーマッタの基本
ISO_LOCAL_DATE / ISO_LOCAL_DATE_TIME / ISO_OFFSET_DATE_TIME
DateTimeFormatter には、ISO-8601 用の定義済みフォーマッタがいくつも用意されています。
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class IsoFormatterBasic {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 3, 26);
LocalDateTime dateTime = LocalDateTime.of(2025, 3, 26, 10, 5, 30);
OffsetDateTime offsetDateTime =
OffsetDateTime.of(2025, 3, 26, 10, 5, 30, 0, ZoneOffset.ofHours(9));
String d = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
String dt = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
String odt = offsetDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
System.out.println("ISO_LOCAL_DATE : " + d); // 2025-03-26
System.out.println("ISO_LOCAL_DATE_TIME : " + dt); // 2025-03-26T10:05:30
System.out.println("ISO_OFFSET_DATE_TIME : " + odt); // 2025-03-26T10:05:30+09:00
}
}
Javaここで押さえておきたいのは、
「タイムゾーンやオフセットを含めたいかどうか」で使う型とフォーマッタが変わる、ということです。
日付だけなら LocalDate+ISO_LOCAL_DATE。
タイムゾーンなしの日時なら LocalDateTime+ISO_LOCAL_DATE_TIME。
オフセット付き(+09:00 や Z)なら OffsetDateTime+ISO_OFFSET_DATE_TIME。
Instant と ISO 形式(Z付き)との変換
Instant → ISO(UTC表現)
Instant は「UTC 上の瞬間」です。
これを ISO 文字列にするときは、toString() でも ISO-8601 形式になります。
import java.time.Instant;
public class InstantIso {
public static void main(String[] args) {
Instant instant = Instant.parse("2025-03-26T01:05:30Z");
String iso = instant.toString();
System.out.println("Instant : " + instant); // 2025-03-26T01:05:30Z
System.out.println("ISO文字列 : " + iso); // 2025-03-26T01:05:30Z
}
}
JavaZ は「UTC(ゼロオフセット)」を意味します。
ログや外部連携で「UTC で統一したい」ときは、この形をそのまま使うのが一番素直です。
ISO(Z付き文字列)→ Instant
逆に、ISO 文字列から Instant に変換するときは Instant.parse を使います。
import java.time.Instant;
public class InstantParseIso {
public static void main(String[] args) {
String text = "2025-03-26T01:05:30Z";
Instant instant = Instant.parse(text);
System.out.println("元文字列: " + text);
System.out.println("Instant: " + instant);
}
}
Javaここでのポイントは、
「UTC の ISO 文字列は、Instant とほぼ 1 対 1 で対応している」
という感覚です。
JST(Asia/Tokyo)と ISO オフセット形式の変換
JST の日時 → ISO_OFFSET_DATE_TIME
日本時間(JST)を ISO 形式(+09:00 付き)で出したいケースです。
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class JstToIsoOffset {
public static void main(String[] args) {
ZoneId jst = ZoneId.of("Asia/Tokyo");
ZonedDateTime jstTime =
ZonedDateTime.of(2025, 3, 26, 10, 5, 30, 0, jst);
String iso = jstTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
System.out.println("JST ZonedDateTime: " + jstTime);
System.out.println("ISOオフセット形式: " + iso); // 2025-03-26T10:05:30+09:00
}
}
Javaここで深掘りしたいのは、
「タイムゾーン付きの日時は、ISO 形式にすると“オフセット付き文字列”になる」
ということです。
+09:00 が付いていることで、「これは日本時間だ」と他システムにも明確に伝えられます。
ISO_OFFSET_DATE_TIME → ZonedDateTime
ISO 文字列から ZonedDateTime に戻すこともできます。
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class IsoOffsetToZoned {
public static void main(String[] args) {
String text = "2025-03-26T10:05:30+09:00";
ZonedDateTime zdt =
ZonedDateTime.parse(text, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
System.out.println("元文字列 : " + text);
System.out.println("ZonedDateTime : " + zdt);
}
}
JavaISO 形式を使うメリットは、
「文字列だけ見ても、タイムゾーン情報まで含めて正しく復元できる」
という点にあります。
ISO 形式と LocalDateTime の注意点
タイムゾーンなしの ISO と “瞬間”のギャップ
ISO_LOCAL_DATE_TIME は、タイムゾーン情報を含みません。
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalIso {
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 3, 26, 10, 5, 30);
String text = dt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
LocalDateTime parsed =
LocalDateTime.parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
System.out.println("元 LocalDateTime: " + dt);
System.out.println("ISO文字列 : " + text);
System.out.println("パース結果 : " + parsed);
}
}
Javaこれは「カレンダー上の日時」を表すには十分ですが、
「世界のどの瞬間か」は決まりません。
“瞬間”として扱いたい場合は、ZonedDateTime や OffsetDateTime と組み合わせて、ISO_OFFSET_DATE_TIME などを使う方が安全です。
ISO変換ユーティリティとしてまとめる
「ISOで出す・ISOから読む」を一か所に集約する
ISO 形式との変換も、あちこちでバラバラに書くのではなく、
ユーティリティクラスにまとめておくと実務でかなり楽になります。
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class IsoUtils {
// UTC Instant ⇔ ISO文字列(Z付き)
public static String instantToIso(Instant instant) {
return instant.toString(); // ISO-8601
}
public static Instant isoToInstant(String isoText) {
return Instant.parse(isoText);
}
// JST LocalDateTime ⇔ ISOオフセット文字列(+09:00)
private static final ZoneId JST = ZoneId.of("Asia/Tokyo");
public static String jstLocalToIsoOffset(LocalDateTime localJst) {
OffsetDateTime odt = localJst.atZone(JST).toOffsetDateTime();
return odt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
}
public static LocalDateTime isoOffsetToJstLocal(String isoText) {
OffsetDateTime odt =
OffsetDateTime.parse(isoText, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
return odt.atZoneSameInstant(JST).toLocalDateTime();
}
}
Javaこうしておけば、呼び出し側は
String iso = IsoUtils.instantToIso(Instant.now());
Javaのように、「ISO で出す」という意図をコードで明示できます。
セキュリティ・外部連携から見た ISO変換
異なるシステム・言語間で“誤解されない時間”を渡す
ISO-8601 は、Java だけでなく、ほとんどの言語・プラットフォームがサポートしています。
だから、外部APIやマイクロサービス間の連携では、
「日時は ISO-8601 でやり取りする」がほぼデファクトスタンダードです。
特に、2025-03-26T01:05:30Z や 2025-03-26T10:05:30+09:00 のように、
オフセット付きの ISO 形式を使うと、
どのタイムゾーンの時間かが明確
サマータイムの有無に関わらず、正しい“瞬間”に復元できる
というメリットがあります。
セキュリティインシデント調査や監査でも、
「ログは ISO-8601(オフセット付き)で統一」「内部は Instant(UTC)」
という設計にしておくと、後からの解析が圧倒的にやりやすくなります。
まとめ:ISO変換で絶対に覚えてほしいこと
ISO変換は、「Java の日時オブジェクト」と「ISO-8601 文字列」を行き来することです。
Instant は toString() / Instant.parse でそのまま ISO(Z付き)と相互変換できる。LocalDate / LocalDateTime は ISO_LOCAL_DATE / ISO_LOCAL_DATE_TIME でタイムゾーンなしの ISO と変換できる。
タイムゾーン・オフセットを含めたいときは、OffsetDateTime や ZonedDateTime と ISO_OFFSET_DATE_TIME を使う。
外部連携・ログ・監査では、オフセット付き ISO 形式で統一すると、誤解されない“時間の証拠”になる。
もしあなたのコードのどこかに、
独自フォーマットで日時を文字列化している箇所があれば、
「そこ、本当に ISO-8601 にできないか?」と一度立ち止まって眺めてみてください。
それを ISO に寄せていくことが、
“時間にもセキュリティにも強いエンジニア”への、かなり実務的な一歩になります。
