Java | Java 標準ライブラリ:LocalDateTime

Java Java
スポンサーリンク

LocalDateTime をざっくり一言でいうと

LocalDateTime は、

「日付(年・月・日)+時刻(時・分・秒)」を、タイムゾーンなしで表すクラス

です。

LocalDate が「日付だけ」
LocalTime が「時刻だけ」

だとしたら、LocalDateTime はその合体版。

「2025 年 1 月 10 日 9 時 30 分」という“カレンダー上の日時”を扱いたいときに使います。
ただし、「それが世界のどの場所の 9:30 か」は含まない、というのが重要なポイントです。

会議日時、締切日時、予約時刻など
「日付と時刻がセットで必要」な場面の基本形が LocalDateTime です。


LocalDateTime の基本:生成と分解

「今この瞬間」と「指定した日時」を作る

まずは一番よく使う作り方から。

import java.time.LocalDateTime;

public class LocalDateTimeBasic {
    public static void main(String[] args) {
        // 今この瞬間(PC のタイムゾーン基準)
        LocalDateTime now = LocalDateTime.now();
        System.out.println("now = " + now); // 例: 2025-01-10T09:30:15.123456789

        // 指定した日時(2025/01/10 09:30:00)
        LocalDateTime meeting =
                LocalDateTime.of(2025, 1, 10, 9, 30);
        System.out.println("meeting = " + meeting); // 2025-01-10T09:30
    }
}
Java

of(年, 月, 日, 時, 分) で、直感通りに指定できます。
Date のような「月は 0 始まり」みたいな罠はありません。

秒やナノ秒まで指定したければ、引数を増やせます。

LocalDateTime precise =
        LocalDateTime.of(2025, 1, 10, 9, 30, 15, 123_000_000);
// 2025-01-10T09:30:15.123(ナノ秒まで)
Java

年・月・日・時・分・秒をばらす

import java.time.LocalDateTime;

LocalDateTime dt = LocalDateTime.of(2025, 1, 10, 9, 30, 15);

int year   = dt.getYear();        // 2025
int month  = dt.getMonthValue();  // 1
int day    = dt.getDayOfMonth();  // 10
int hour   = dt.getHour();        // 9
int minute = dt.getMinute();      // 30
int second = dt.getSecond();      // 15
Java

「年月日」と「時分秒」が 1 つにまとまっている感覚を掴んでください。
ただし、タイムゾーン(日本かニューヨークか)は含んでいないのがミソです。


LocalDate / LocalTime との関係(頭の中の整理)

LocalDate + LocalTime → LocalDateTime

LocalDateTime は、LocalDateLocalTime から簡単に作れます。

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

LocalDate date = LocalDate.of(2025, 1, 10);
LocalTime time = LocalTime.of(9, 30);

LocalDateTime dt1 = LocalDateTime.of(date, time);
LocalDateTime dt2 = date.atTime(time);
LocalDateTime dt3 = time.atDate(date);
Java

どれも結果は同じ「2025-01-10T09:30」です。

「日付は別で扱いたいけど、DB には日時として保存したい」
みたいな場面で、LocalDateLocalTime を一時的に LocalDateTime にまとめる、という使い方もよくします。

LocalDateTime から LocalDate / LocalTime を取り出す

逆方向も簡単です。

LocalDateTime dt = LocalDateTime.of(2025, 1, 10, 9, 30);

LocalDate dateOnly = dt.toLocalDate(); // 2025-01-10
LocalTime timeOnly = dt.toLocalTime(); // 09:30
Java

「ロジック的には日付だけ欲しい」「時刻だけ比べたい」
というときは、分解して考えるとシンプルになります。


LocalDateTime の「不変性」とその意味

不変(immutable)なので勝手に書き換わらない

LocalDateTimeLocalDate / LocalTime と同じく、不変です。

LocalDateTime dt1 = LocalDateTime.of(2025, 1, 10, 9, 30);
LocalDateTime dt2 = dt1.plusDays(1);

System.out.println(dt1); // 2025-01-10T09:30
System.out.println(dt2); // 2025-01-11T09:30
Java

plusDays(1) を呼んでも、dt1 は一切変わりません。
新しい LocalDateTime が返ってくるだけです。

この設計のおかげで、

メソッドに渡した日時が、中で勝手に書き換えられない
スレッドが複数あっても、「データ競合」で日時が壊れない

という安全性が得られます。


日時の加算・減算・比較(よく使うところを重点的に)

plusXxx / minusXxx で足し引きする

代表的なものはこうです。

LocalDateTime dt = LocalDateTime.of(2025, 1, 10, 9, 30);

LocalDateTime plusDays    = dt.plusDays(3);     // 3 日後 → 2025-01-13T09:30
LocalDateTime minusDays   = dt.minusDays(5);    // 5 日前 → 2025-01-05T09:30
LocalDateTime plusHours   = dt.plusHours(2);    // 2 時間後 → 11:30
LocalDateTime plusMinutes = dt.plusMinutes(90); // 90 分後 → 11:00
LocalDateTime plusMonths  = dt.plusMonths(1);   // 1 か月後
LocalDateTime plusYears   = dt.plusYears(1);    // 1 年後
Java

月末やうるう年をまたいだときも、カレンダールールに従ってうまく処理してくれます。

日時計算の基本は「plusXxx / minusXxx を使う」で覚えておけば大丈夫です。

日時の前後関係を調べる

LocalDateTime 同士の比較は isBefore, isAfter, equals で書けます。

LocalDateTime dt1 = LocalDateTime.of(2025, 1, 10, 9, 30);
LocalDateTime dt2 = LocalDateTime.of(2025, 1, 10, 10, 0);

boolean b1 = dt1.isBefore(dt2); // true
boolean b2 = dt1.isAfter(dt2);  // false
boolean b3 = dt1.equals(dt2);   // false
Java

もう少し実務寄りの例にすると、

「締切日時より前か?」
「予約日時が現在時刻より後か?」

などを自然な条件で書けます。

LocalDateTime now      = LocalDateTime.now();
LocalDateTime deadline = LocalDateTime.of(2025, 1, 31, 23, 59);

boolean inTime = now.isBefore(deadline) || now.equals(deadline);
Java

日本語に直すと「現在が締切以前かどうか」です。


文字列との相互変換(日時の表示と入力)

LocalDateTime → 文字列(format)

画面表示やログ出力などで、日時を文字列にしたい場面は多いです。
DateTimeFormatter を使います。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeFormat {
    public static void main(String[] args) {
        LocalDateTime dt = LocalDateTime.of(2025, 1, 10, 9, 30, 15);

        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        String s = dt.format(fmt);

        System.out.println(s); // 2025/01/10 09:30:15
    }
}
Java

DateTimeFormatter はスレッドセーフなので、
SimpleDateFormat のように「static で共有したら壊れた」みたいな事故が起きません。

文字列 → LocalDateTime(parse)

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeParse {
    public static void main(String[] args) {
        String text = "2025-01-10T09:30:15";

        // ISO 形式(yyyy-MM-ddTHH:mm:ss)はそのまま parse 可能
        LocalDateTime dt1 = LocalDateTime.parse(text);

        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
        LocalDateTime dt2 = LocalDateTime.parse("2025/01/10 09:30", fmt);

        System.out.println(dt1); // 2025-01-10T09:30:15
        System.out.println(dt2); // 2025-01-10T09:30
    }
}
Java

フォーム入力や設定ファイル・CSV などから「日時文字列」を取り込むときの定番パターンです。


LocalDateTime とタイムゾーン/Instant/Date の関係(ここが重要)

ここは少し深掘りします。
LocalDateTime をちゃんと使いこなしたいなら、「何を持っていないか」を理解するのが大事だからです。

LocalDateTime は「タイムゾーンを持っていない」

LocalDateTime は、「2025-01-10 09:30」という“カレンダー上の日時”であって、
「東京の 9:30」なのか「ニューヨークの 9:30」なのかまでは表しません。

同じ「2025-01-10T09:30」でも、

東京で解釈したら「世界標準時では 0:30」
ロンドンで解釈したら「世界標準時では 9:30」

というように、「世界共通の瞬間」としては別物です。

「世界共通の一瞬」を表すのは InstantDate の役割です。

LocalDateTime ↔ Instant / Date に変換するときは「ZoneId」が必須

LocalDateTime を「世界共通の瞬間(Instant)」に変換するときは、必ずタイムゾーンを指定します。

import java.time.*;

LocalDateTime dt = LocalDateTime.of(2025, 1, 10, 9, 30);
ZoneId tokyo = ZoneId.of("Asia/Tokyo");

Instant instant = dt.atZone(tokyo).toInstant();
System.out.println(instant); // 例: 2025-01-10T00:30:00Z(UTC)
Java

逆に、Instant から LocalDateTime に戻すときも同じです。

Instant instant = Instant.now();
ZoneId tokyo = ZoneId.of("Asia/Tokyo");

LocalDateTime dt = LocalDateTime.ofInstant(instant, tokyo);
System.out.println(dt); // 東京時間での現在日時
Java

Date との変換も、「Instant を経由して、ZoneId を意識する」のが鉄板パターンです。

import java.time.*;
import java.util.Date;

// Date → LocalDateTime(東京時間で解釈)
Date legacy = new Date();
Instant instant = legacy.toInstant();
ZoneId tokyo = ZoneId.of("Asia/Tokyo");
LocalDateTime dt = LocalDateTime.ofInstant(instant, tokyo);

// LocalDateTime → Date(東京時間として)
Instant instant2 = dt.atZone(tokyo).toInstant();
Date date = Date.from(instant2);
Java

ここでのキモは、

LocalDateTime 自体はタイムゾーンを持たない
「どこの国の日時として解釈するか」を指定した瞬間に、世界共通の Instant にマッピングされる

という感覚です。


LocalDateTime をどんなときに使うべきか(実務的な勘どころ)

向いている場面

例えば、こんな場面では LocalDateTime がしっくり来ます。

予約日時
会議の開始日時
締切日時(「2025-01-31 23:59」など)
クライアントローカルで完結する予定(カレンダーアプリなど)

「ユーザーの住んでいる場所のカレンダー上の日時として意味がある」
という場面です。

あまり向いていない場面

逆に、次のような場面では LocalDateTime だけだと情報不足です。

ログのタイムスタンプ(世界中どこで見ても一意な瞬間が必要)
「サーバー間で日時をやり取りするプロトコル」
タイムゾーンをまたいで厳密に比較するスケジューリング

こういうときは、

保存・通信は Instant(もしくは UTC の OffsetDateTime / ZonedDateTime
表示やローカル操作のときだけ、ユーザーのタイムゾーンで LocalDateTime に変換

という設計のほうが安全です。


まとめ:LocalDateTime を自分の中でどう位置づけるか

LocalDateTime を初心者向けに一言でまとめると、

「日付+時刻をセットで持つ“カレンダー上の日時”を、タイムゾーン抜きで表すクラス」

です。

押さえておきたいポイントは次の通りです。

  • 年・月・日・時・分・秒を 1 つで扱えるが、タイムゾーンは持たない
  • 不変(immutable)で、安全に使いまわせる
  • plusXxx / minusXxx で日時計算、isBefore / isAfter で比較が直感的
  • DateTimeFormatter でフォーマット/パースができ、Date / Instant とは ZoneId を挟んで変換する

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