Java Tips | 日付・時間:Instant変換

Java Java
スポンサーリンク

Instant は「世界共通の“瞬間”を表すタイムスタンプ」

Instant は、
「UTC を基準にした、世界共通の“ある瞬間”」 を表すクラスです。

「1970-01-01T00:00:00Z(UTC)」からの経過秒・ナノ秒で管理されていて、
タイムゾーンやローカル時間の違いを超えて、「同じ瞬間」を一意に表現できます。

業務でいうと、
ログのタイムスタンプ、DB に保存する基準時刻、
システム間連携でやり取りする“絶対的な時間”の表現として、とても相性が良いです。

ここでは、
「Instant と他の日時クラスの“変換”」に絞って、
初心者向けにかみ砕いて説明していきます。


Instant を生成する基本:now と epoch 系

現在時刻の Instant を取る:Instant.now()

一番シンプルなのは Instant.now() です。

import java.time.Instant;

public class InstantNowExample {

    public static void main(String[] args) {
        Instant now = Instant.now();
        System.out.println(now); // 例: 2025-03-26T13:25:30.123456Z
    }
}
Java

ここでのポイントは、「常に UTC 基準」であることです。
末尾の Z は「Zulu(UTC)」を意味します。

LocalDateTimeZonedDateTime と違って、
「どのタイムゾーンか」を考えなくても、
「世界共通の時間軸上のどこか」という意味になります。

epoch milli / epoch second から Instant を作る

「1970-01-01T00:00:00Z からのミリ秒・秒」で Instant を作ることもできます。

import java.time.Instant;

public class InstantEpochExample {

    public static void main(String[] args) {
        long epochMilli = 1_700_000_000_000L;

        Instant fromMilli = Instant.ofEpochMilli(epochMilli);
        Instant fromSecond = Instant.ofEpochSecond(1_700_000_000L);

        System.out.println(fromMilli);
        System.out.println(fromSecond);
    }
}
Java

ここが重要です。

多くの既存システムや DB、java.util.Date は、
「epoch milli(long 値)」で時間を扱っています。

Instant は、その世界と java.time の世界をつなぐ“橋”になります。


Instant ↔ java.util.Date の変換

Date から Instant へ:toInstant()

古い API やライブラリは、まだ java.util.Date を使っていることが多いです。
Date から Instant への変換はとても簡単です。

import java.time.Instant;
import java.util.Date;

public class DateToInstantExample {

    public static void main(String[] args) {
        Date date = new Date();          // 現在日時(内部的には epoch milli)
        Instant instant = date.toInstant();

        System.out.println(date);
        System.out.println(instant);
    }
}
Java

ここでの重要ポイントは、
DateInstant も、実質的には“同じ epoch milli を別のクラスで包んでいる”」ということです。

Instant に変換してしまえば、
LocalDateTimeZonedDateTime との連携が一気にやりやすくなります。

Instant から Date へ:Date.from(instant)

逆に、InstantDate に戻すこともできます。

import java.time.Instant;
import java.util.Date;

public class InstantToDateExample {

    public static void main(String[] args) {
        Instant instant = Instant.now();
        Date date = Date.from(instant);

        System.out.println(instant);
        System.out.println(date);
    }
}
Java

既存ライブラリの API が Date を要求してくるとき、
内部では Instant で扱い、最後に Date.from(...) で渡す、
という設計にすると、古い世界と新しい世界をきれいに分離できます。


Instant ↔ ZonedDateTime の変換

Instant を「特定タイムゾーンの日時」に変換する

Instant は「世界共通の瞬間」なので、
「日本時間では何年何月何日何時か?」という形に変換したくなることが多いです。

そのときに使うのが ZonedDateTime です。

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class InstantToZonedExample {

    public static void main(String[] args) {
        Instant instant = Instant.now();

        ZoneId tokyo = ZoneId.of("Asia/Tokyo");
        ZonedDateTime tokyoTime = instant.atZone(tokyo);

        ZoneId utc = ZoneId.of("UTC");
        ZonedDateTime utcTime = instant.atZone(utc);

        System.out.println("Instant : " + instant);
        System.out.println("Tokyo   : " + tokyoTime);
        System.out.println("UTC     : " + utcTime);
    }
}
Java

ここで深掘りしたいポイントは二つです。

一つ目は、「同じ Instant を、タイムゾーンごとに違う“ローカルな日時”として見られる」ことです。
世界共通の瞬間を、各地の時計でどう見えるかに変換しているイメージです。

二つ目は、「DB やログには Instant(または epoch milli)で保存し、画面表示では ZonedDateTime に変換する」という設計がとても実務的だということです。
保存はシンプルに、表示はユーザーのタイムゾーンで——という分離がしやすくなります。

ZonedDateTime から Instant へ:toInstant()

逆に、「日本時間の ZonedDateTime を、世界共通の Instant にしたい」こともよくあります。

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.Instant;

public class ZonedToInstantExample {

    public static void main(String[] args) {
        ZonedDateTime tokyoTime = ZonedDateTime.of(
                2025, 3, 26,
                9, 0, 0, 0,
                ZoneId.of("Asia/Tokyo")
        );

        Instant instant = tokyoTime.toInstant();

        System.out.println("Tokyo   : " + tokyoTime);
        System.out.println("Instant : " + instant);
    }
}
Java

ここでのポイントは、
「タイムゾーン付きの日時を、世界共通の時間軸に“投影”している」イメージを持つことです。


Instant ↔ LocalDateTime の変換(ZoneId が必須)

Instant を LocalDateTime に変換する

LocalDateTime はタイムゾーンを持たないので、
Instant から変換するときは「どのタイムゾーンとして解釈するか」を必ず指定します。

import java.time.*;

public class InstantToLocalDateTimeExample {

    public static void main(String[] args) {
        Instant instant = Instant.now();

        ZoneId tokyo = ZoneId.of("Asia/Tokyo");
        LocalDateTime tokyoDateTime = LocalDateTime.ofInstant(instant, tokyo);

        ZoneId utc = ZoneId.of("UTC");
        LocalDateTime utcDateTime = LocalDateTime.ofInstant(instant, utc);

        System.out.println("Instant      : " + instant);
        System.out.println("Tokyo LDT    : " + tokyoDateTime);
        System.out.println("UTC   LDT    : " + utcDateTime);
    }
}
Java

ここでの重要ポイントは、
「Instant → LocalDateTime 変換には、必ず ZoneId が必要」
ということです。

同じ Instant でも、
日本時間で見るか、UTC で見るかで、
LocalDateTime の値は変わります。

LocalDateTime を Instant に変換する

逆方向も同じで、
「この LocalDateTime は、どのタイムゾーンのものか?」を決めないと Instant にできません。

import java.time.*;

public class LocalDateTimeToInstantExample {

    public static void main(String[] args) {
        LocalDateTime local = LocalDateTime.of(2025, 3, 26, 9, 0);

        ZoneId tokyo = ZoneId.of("Asia/Tokyo");
        Instant instant = local.atZone(tokyo).toInstant();

        System.out.println("LocalDateTime : " + local);
        System.out.println("Instant       : " + instant);
    }
}
Java

ここでのポイントは、
「LocalDateTime 単体では“世界のどの瞬間か”が決まらない」
「ZoneId を与えて初めて Instant にできる」
という関係をしっかり理解しておくことです。


Instant と epoch milli / second の変換

Instant → epoch milli / second

DB や他言語との連携では、
「long の epoch milli / second」でやり取りすることがよくあります。

import java.time.Instant;

public class InstantToEpochExample {

    public static void main(String[] args) {
        Instant instant = Instant.now();

        long epochMilli = instant.toEpochMilli();
        long epochSecond = instant.getEpochSecond();

        System.out.println("Instant    : " + instant);
        System.out.println("epochMilli : " + epochMilli);
        System.out.println("epochSecond: " + epochSecond);
    }
}
Java

epoch milli / second → Instant

逆に、long 値から Instant を復元するのも簡単です。

import java.time.Instant;

public class EpochToInstantExample {

    public static void main(String[] args) {
        long epochMilli = 1_700_000_000_000L;

        Instant instant = Instant.ofEpochMilli(epochMilli);
        System.out.println(instant);
    }
}
Java

ここでの重要ポイントは、
「Instant は epoch と相互変換しやすい“タイムスタンプの標準形”」
という感覚を持つことです。


まとめ:Instant変換で押さえておきたい感覚

Instant は、
「世界共通の時間軸上の“点”」を表すクラス です。

Instant.now() や epoch milli / second から生成できる。
Date とは toInstant / Date.from で相互変換できる。
ZonedDateTimeLocalDateTime とは、「どのタイムゾーンか」を意識しながら変換する。
DB や他システムとのやり取りでは、「保存は Instant(または epoch)、表示は Zoned/Local」という分離がとても実務的。

あなたのコードのどこかに、
「long のまま時間を扱っていて、どのタイムゾーン基準か分からない」
「Date と LocalDateTime が混在していて、変換がぐちゃぐちゃ」
そんな箇所があれば、一度「Instant を軸に整理できないか?」という目で眺めてみてください。

それが、「時間の表現をきちんと分離して設計できるエンジニア」への、
かなり大きな一歩になります。

タイトルとURLをコピーしました