秒変換で何をしたいのかイメージする
「DBに“1970年からの秒”で保存されている」「外部APIがエポック秒で送ってくる」「処理時間を秒でログに出したい」。
こういうときに必要になるのが、日付・時間と「秒」の相互変換です。
ミリ秒と同じく、秒も「エポック(1970-01-01T00:00:00Z)」からの経過時間として扱うことが多いです。
Java の日付・時間API(Instant や Duration)と、この“エポック秒”をどう行き来するかを押さえておくと、業務コードがかなりスッキリします。
エポック秒とは何か
1970-01-01T00:00:00Z からの経過秒
エポック秒は、「1970-01-01T00:00:00Z(UTC)」からの経過時間を秒単位で表したものです。
0 はちょうど 1970-01-01T00:00:00Z、1 は 1 秒後、60 は 1 分後、60×60×24 は 1 日後、というイメージです。
ミリ秒と違うのは「単位が秒」であることだけで、基準(UTCのエポック)は同じです。
「秒で持つか、ミリ秒で持つか」は、精度とデータ量のトレードオフとして設計で決めます。
Instant と秒の相互変換
Instant からエポック秒へ変換する
Instant は「UTC 上の瞬間」を表すクラスです。
これをエポック秒に変換するには、getEpochSecond() を使います。
import java.time.Instant;
public class InstantToSeconds {
public static void main(String[] args) {
Instant now = Instant.now();
long epochSeconds = now.getEpochSecond();
System.out.println("Instant : " + now);
System.out.println("エポック秒 : " + epochSeconds);
}
}
Javaここで深掘りしたいのは、「内部では Instant を使い、保存や通信のときだけ秒にする」という発想です。Instant はナノ秒精度を持っていますが、getEpochSecond() すると秒単位に丸められます(小数点以下は切り捨て)。
エポック秒から Instant へ変換する
逆に、エポック秒から Instant を作るときは Instant.ofEpochSecond を使います。
import java.time.Instant;
public class SecondsToInstant {
public static void main(String[] args) {
long epochSeconds = 1_742_950_000L; // 例
Instant instant = Instant.ofEpochSecond(epochSeconds);
System.out.println("エポック秒 : " + epochSeconds);
System.out.println("Instant : " + instant);
}
}
Java「DBは long(秒)、アプリ内部は Instant」という構成にしておくと、
タイムゾーン変換やフォーマットなどをすべて Instant ベースで統一できて、バグが減ります。
秒とローカル日時(JSTなど)の変換
エポック秒 → 日本時間の LocalDateTime
DB にエポック秒が入っていて、それを日本時間の日時として画面に表示したいケースです。
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class SecondsToJstDateTime {
public static void main(String[] args) {
long epochSeconds = 1_742_950_000L; // 例
Instant instant = Instant.ofEpochSecond(epochSeconds);
ZoneId jst = ZoneId.of("Asia/Tokyo");
ZonedDateTime jstZdt = instant.atZone(jst);
LocalDateTime jstLocal = jstZdt.toLocalDateTime();
System.out.println("エポック秒 : " + epochSeconds);
System.out.println("Instant(UTC) : " + instant);
System.out.println("JST ZonedDateTime: " + jstZdt);
System.out.println("JST LocalDateTime: " + jstLocal);
}
}
Java流れは、エポック秒 → Instant → JST の ZonedDateTime → LocalDateTime です。
ここで重要なのは、「秒はあくまで UTC 基準の“瞬間”であり、JST かどうかは後から決める」という感覚です。
日本時間の LocalDateTime → エポック秒
今度は逆に、「画面で入力された日本時間の日時をエポック秒で保存したい」ケースです。
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class JstDateTimeToSeconds {
public static void main(String[] args) {
LocalDateTime jstLocal = LocalDateTime.of(2025, 3, 26, 10, 5, 30);
ZoneId jst = ZoneId.of("Asia/Tokyo");
ZonedDateTime jstZdt = jstLocal.atZone(jst);
long epochSeconds = jstZdt.toInstant().getEpochSecond();
System.out.println("JST LocalDateTime: " + jstLocal);
System.out.println("JST ZonedDateTime: " + jstZdt);
System.out.println("エポック秒 : " + epochSeconds);
}
}
Javaここで深掘りしたいのは、「LocalDateTime 単体では“どこの国の時間か”が分からない」という点です。
必ず ZoneId をかぶせて ZonedDateTime にし、そのうえで toInstant() → getEpochSecond() という流れにします。
処理時間計測と「秒」への変換
nanoTime で測って秒に変換する
処理時間を測るときは、System.nanoTime() を使うのが定番です。
これを秒に変換するのもよくあるパターンです。
public class ElapsedSecondsExample {
public static void main(String[] args) {
long start = System.nanoTime();
doHeavyWork();
long end = System.nanoTime();
long elapsedNanos = end - start;
double elapsedSeconds = elapsedNanos / 1_000_000_000.0;
System.out.println("処理時間(秒): " + elapsedSeconds);
}
private static void doHeavyWork() {
try {
Thread.sleep(1500); // 1.5秒だけ待つ
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
Javaここで大事なのは、「時刻そのもの」と「経過時間」は別物だ、という感覚です。
時刻は Instant やエポック秒、経過時間は nanoTime や Duration で扱う、と役割を分けると設計がきれいになります。
Duration と秒の変換
Duration → 秒
Duration は「時間の長さ」を表すクラスで、秒との相性がとても良いです。getSeconds() や toSeconds() 相当の扱いで、秒単位に変換できます。
import java.time.Duration;
public class DurationToSeconds {
public static void main(String[] args) {
Duration d = Duration.ofMinutes(2).plusSeconds(30); // 2分30秒
long seconds = d.getSeconds(); // 全体を秒にした値
System.out.println("Duration: " + d);
System.out.println("秒 : " + seconds); // 150
}
}
Java秒 → Duration
逆に、秒から Duration を作るときは Duration.ofSeconds を使います。
import java.time.Duration;
public class SecondsToDuration {
public static void main(String[] args) {
long seconds = 150L;
Duration d = Duration.ofSeconds(seconds);
System.out.println("秒 : " + seconds);
System.out.println("Duration: " + d); // PT2M30S
}
}
Java「処理時間を秒でログに出すけれど、内部では Duration で扱う」といった設計にすると、
「分に直したい」「ミリ秒に直したい」といった変換も簡単になり、コードの意図も読みやすくなります。
セキュリティ・ログ設計と秒
粒度を“秒”にするか“ミリ秒”にするか
セキュリティインシデント調査では、ログの時刻が「どれくらい細かいか」が重要になります。
秒まであれば、だいたいの順序は追えますが、同じ秒の中で大量のイベントが起きるシステムでは、ミリ秒が欲しくなることもあります。
設計としては、例えば次のような考え方があります。
内部的には Instant(ナノ秒精度)で持つ。
ログ出力は秒までにする(あるいはミリ秒までにする、とルール化)。
画面表示は秒まで、あるいは分までに丸める。
「内部の精度」と「外に見せる精度」を分けておくと、
必要なときには高精度な情報を使いつつ、普段は過剰な情報を出さない、というバランスが取りやすくなります。
秒変換ユーティリティとしてまとめる
「Instant ⇔ 秒」「JST ⇔ 秒」を一か所に閉じ込める
秒変換も、あちこちで同じようなコードを書きがちなので、ユーティリティにまとめておくと実務でかなり楽になります。
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class SecondsUtils {
private static final ZoneId JST = ZoneId.of("Asia/Tokyo");
public static long instantToEpochSeconds(Instant instant) {
return instant.getEpochSecond();
}
public static Instant epochSecondsToInstant(long epochSeconds) {
return Instant.ofEpochSecond(epochSeconds);
}
public static long jstLocalToEpochSeconds(LocalDateTime localJst) {
ZonedDateTime zdt = localJst.atZone(JST);
return zdt.toInstant().getEpochSecond();
}
public static LocalDateTime epochSecondsToJstLocal(long epochSeconds) {
Instant instant = Instant.ofEpochSecond(epochSeconds);
return instant.atZone(JST).toLocalDateTime();
}
}
Java呼び出し側は、例えば次のように書けます。
LocalDateTime jst = LocalDateTime.of(2025, 3, 26, 10, 5, 30);
long epochSeconds = SecondsUtils.jstLocalToEpochSeconds(jst);
LocalDateTime back = SecondsUtils.epochSecondsToJstLocal(epochSeconds);
Java「秒を触るときは必ず SecondsUtils を通す」と決めてしまえば、
エポックの基準やタイムゾーンの扱いを間違えるリスクが一気に減ります。
まとめ:秒変換で身につけてほしい感覚
秒変換は、「エポック秒」と「日時オブジェクト(Instant や LocalDateTime)」を行き来することです。
エポック秒は「1970-01-01T00:00:00Z からの経過時間」であり、UTC 基準である。
“瞬間”として扱うなら Instant を使い、getEpochSecond と ofEpochSecond で秒と相互変換する。
ローカル時間(JST など)とは、ZoneId と ZonedDateTime を経由して変換する。
処理時間の計測には、nanoTime と Duration を使い、必要に応じて秒に変換してログやメトリクスに出す。
もしあなたのコードのどこかに、「それっぽい long の秒を直接割り算して日付を計算している」ような箇所があれば、
そこを一度 Instant や ZonedDateTime ベースの秒変換に置き換えられないか眺めてみてください。
その小さな置き換えが、時間にもセキュリティにも強いエンジニアへの、かなり実務的で確かな一歩になります。
