ローカル日時クラスまとめ<前編>[Java]
はじめに
こんにちは。
プログラミング初心者wakinozaと申します。
Java勉強中に調べたことを記事にまとめています。
十分気をつけて執筆していますが、なにぶん初心者が書いた記事なので、理解が浅い点などあるかと思います。
間違い等あれば、指摘いただけると助かります。
記事を参考にされる方は、初心者の記事であることを念頭において、お読みいただけると幸いです。
対象読者
- Javaを勉強中の方
- 「Date and Time API」について知りたい方
記事のテーマ
- 「Date and Time API」のローカル日時を扱うクラスを開発でよく使います。しかし、APIの種類が多くて覚えきれないため、使うたびに公式リファレンスで検索していましたが、だんだんそれが面倒に。そこで、よく使いそうなローカル日時クラスのメソッドやAPIを、自分用にまとめてみました
- 前編では、「Date and Time API」の概要と、インスタンスの生成、インスタンスから情報や文字列を取得する方法をまとめています。インスタンスの操作に関わるメソッドは、後編で紹介していきます
目次
1. 「Date and Time API」の特徴
2. java.timeパッケージの代表的なクラス
3. ローカル日時クラス
4. インスタンスの生成
5. 日時情報の取得
6. インスタンスから任意の形式の文字列を取得
本文
1. 「Date and Time API」の特徴
Java 7以前では、日時を扱う場合には「java.util.Dateクラス」と「java.util.Calendarクラス」を組み合わせて記述していました。
しかし、DateクラスとCalendarクラスの運用には問題がありました。
Dateクラスは、ミュータブルであり、タイムゾーンの情報がなく、直感的でないメソッド名が多いなどの問題点がありました。Calenderクラスも同様にミュータブルです。また、月が0から始まるなど直感的でないAPIがあり、日時の計算が煩雑になるという問題点もありました。
そこで、これらの問題を解決するためにJava 8で導入されたのが「Date and Time API」です。
DateクラスとCalendarクラスと比べた場合の「Date and Time API」の特徴は以下の通りです。
- イミュータブルであるため、意図せず値が変更される可能性がない
- 日付・時間・日時をそれぞれ別のクラスで扱うため、不要な情報を保持する必要がない
- 日時を指定してインスタンスを生成できる
- インスタンスの情報を個別に取得できる
- 年月日の計算が簡素に記述できる
これからJavaアプリケーションを開発する場合は、特別な理由がない限りは「Date and Time API」を使用することが推奨されています。
2. java.timeパッケージの代表的なクラス
「Date and Time API」の主要クラスは、java.timeパッケージに所属しています。
この節では、java.timeパッケージの代表的なクラスをいくつか紹介していきます。
java.timeパッケージには主に3種類のクラスが存在します。
- 瞬間を表すクラス:Instantクラスなど
- 日時を表すクラス:LocalDateTimeクラス、OffsetDateTimeクラス、ZonedDateTimeクラスなど
- 期間を表すクラス:Durationクラス、Periodクラスなど
1. 瞬間を表すクラス
Instantクラスは、「瞬間」を表すクラスです。具体的には、基準となる標準Javaエポック (1970-01-01T00:00:00Z) からの経過時間をナノ秒数で格納します。旧来のDateクラスではミリ秒単位までしか表現できませんでしたが、Instantクラスはナノ秒単位まで正確に表現できます。
//現在の瞬間をInstantインスタンスとして取得
Instant now = Instant.now();
System.out.println("Instant: " + now);
//結果:Instant: 2025-09-02T07:19:02.123456789Z
2. 日時を表すクラス
現在地の日時を表すクラスには、ローカル日時を格納するLocalDateTimeクラス、ローカル日時と時差情報を格納するOffsetDateTimeクラス、ローカル日時・時差情報・タイムゾーンを格納するZonedDateTimeクラスがあります。
時差情報とは、グリニッジ標準時間との時差(例:+9:00)です。タイムゾーンとは、どの地域の標準時を利用するかを識別するための文字列(例: Asia/Tokyo)です。
ローカル日時 | 時差情報 | タイムゾーン | |
---|---|---|---|
LocalDateTime | ○ | × | × |
OffsetDateTime | ○ | ○ | × |
ZonedDateTime | ○ | ○ | ○ |
LocalDateTime now2 = LocalDateTime.now();
System.out.println("LocalDateTime: " + now2);
//結果:LocalDateTime: 2025-09-02T16:34:19.552270564
OffsetDateTime now3 = OffsetDateTime.now();
System.out.println("OffsetDateTime: " + now3);
//結果:OffsetDateTime: 2025-09-02T16:34:19.555165753+09:00
ZonedDateTime now4 = ZonedDateTime.now();
System.out.println("ZonedDateTime: " + now4);
//結果:ZonedDateTime: 2025-09-02T16:35:19.777064656+09:00[Asia/Tokyo]
3. 期間を表すクラス
Durationクラスは、時間ベースの「時・分・秒」単位の間隔を表します。
Periodクラスは、日付ベースの「年・月・日」単位の間隔を表します。
3. ローカル日時クラス
以降は、使用頻度の高いローカル日時を表すクラスについて説明していきます。
ローカル日時を表すクラスの特徴は、時差情報やタイムゾーンの情報を保持しないことです。
ローカル日時を表すクラスは、あえて時差やタイムゾーンを保持しないことで、人間が日常的に感じる「曖昧でローカルな時間感覚」をコンピュータ上で表現しています。
例えば、誰かと「来週の火曜日の午後3時に打ち合わせをしましょう」と約束する場合、通常は人間は具体的な時差やタイムゾーンまで意識していないでしょう。人間の感覚では「火曜日の午後3時」という情報だけで、十分なのです。
もし、すべての日時情報が時差やタイムゾーンなどの詳細な情報を保持していた場合、不必要なデータを保持するために余計なメモリが必要になり、情報の管理も煩雑になります。
人間の時間感覚に近い、情報を絞ったクラスを用意することで、日時情報をシンプルに、また直感的に扱うことができるようになったのです。
ローカル日時を表すクラスには、「日時」を表すLocalDateTimeクラスの他に、「日付」を表すLocalDateクラスや「時間」を表すLocalTimeクラス、「年」だけを扱うYearクラスや「年月」だけを扱うYearMonthクラスなど、特定の情報のみ扱うクラスが用意されています。
そのうちよく利用するのが、LocalDateTimeクラス、LocalDateクラス、LocalTimeクラスです。
年 | 月 | 日 | 時 | 分 | 秒 | ナノ秒 | |
---|---|---|---|---|---|---|---|
LocalDateTime | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
LocalDate | ○ | ○ | ○ | × | × | × | × |
LocalTime | × | × | × | ○ | ○ | ○ | ○ |
4. インスタンスの生成
まずは、LocalDateTimeクラスのインスタンスを生成してみましょう。
「Date and Time API」の多くのクラスでは、コンストラクタがprivateで定義されているため、newによるインスタンス生成はできません。そのため、staticメソッドを利用して、インスタンスを生成します。
インスタンスを生成する方法は、以下の3つがあります。
- 現在の時刻からインスタンスを生成する
- 年・月・日・時・秒・ナノ秒を指定する
- 日付文字列(ISO8601形式)を指定する
1. 現在の時刻からインスタンスを生成する
現在の時刻からインスタンスを生成する場合は、now()メソッドを利用します。
メソッド | 説明 |
---|---|
public static LocalDateTime now() | デフォルトのタイムゾーンのシステム・クロックから現在の日付/時間を取得し、インスタンスを生成する |
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
//結果:2025-09-03T15:48:46.860317653
2. 年・月・日・時・秒・ナノ秒を指定する
日時の情報を指定してインスタンスを生成する場合は、of()メソッドを利用します。
of()メソッドには多数のオーバーロードが用意されています。
秒やナノ秒などの情報が不要な場合は、秒やナノ秒を指定せずにインスタンスを生成することも可能です。その場合、秒やナノ秒はゼロとして設定されます。
メソッド | 説明 |
---|---|
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute) | 指定された年、月・日・時間・分から、日付/時間を取得し、インスタンスを生成する。秒とナノ秒はゼロに設定される |
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second) | 指定された年、月・日・時間・分・秒から、日付/時間を取得し、インスタンスを生成する。ナノ秒はゼロに設定される |
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) | 指定された年、月・日・時間・分・秒・ナノ秒から、日付/時間を取得し、インスタンスを生成する |
LocalDateTime dateTime1 = LocalDateTime.of(2025, 1, 1, 1, 23);
LocalDateTime dateTime2 = LocalDateTime.of(2025, 1, 1, 1, 23, 45);
LocalDateTime dateTime3 = LocalDateTime.of(2025, 1, 1, 1, 23, 45, 678_000_000);
System.out.println(dateTime1); //結果:2025-01-01T01:23
System.out.println(dateTime2); //結果:2025-01-01T01:23:45
System.out.println(dateTime3); //結果:2025-01-01T01:23:45.678
また、月の指定は、int型の整数を指定する以外に、列挙型クラスMonthの定数を利用する方法もあります。
月 | 列挙型定数 |
---|---|
1月 | Month.JANUARY |
2月 | Month.FEBRUARY |
3月 | Month.MARCH |
4月 | Month.APRIL |
5月 | Month.MAY |
6月 | Month.JUNE |
7月 | Month.JULY |
8月 | Month.AUGUST |
9月 | Month.SEPTEMBER |
10月 | Month.OCTOBER |
11月 | Month.NOVEMBER |
12月 | Month.DECEMBER |
メソッド | 説明 |
---|---|
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) | 指定された年、月・日・時間・分・秒・ナノ秒から、日付/時間を取得し、インスタンスを生成する |
LocalDateTime dateTime4 = LocalDateTime.of(2025, Month.JANUARY, 1, 1, 23);
System.out.println(dateTime4); //結果:2025-01-01T01:23
また、LocalDateクラスのインスタンスと、LocalTimeクラスのインスタンスから、LocalDateTimeクラスのインスタンスを生成できます。
メソッド | 説明 |
---|---|
public static LocalDateTime of(LocalDate date, LocalTime time) | 指定されたLocalDateとLocalTimeから日付/時間を取得し、インスタンスを生成する |
3.日付文字列(ISO8601形式)を指定する
parse()メソッドを使用することで、ISO8601形式の文字列からインスタンスを生成します。
メソッド | 説明 |
---|---|
public static LocalDateTime parse(CharSequence text) | ISO8601形式の文字列を解析し、インスタンスを生成する |
LocalDateTimeクラスの文字列の形式 |
---|
"2025-01-01T01:00:00.123" |
"2025-01-01T01:00:00" (ミリ秒を省略) |
LocalDateTime dateTime5 = LocalDateTime.parse("2025-01-01T01:00:00.123");
LocalDateTime dateTime6 = LocalDateTime.parse("2025-01-01T01:00:00" );
System.out.println(dateTime5); //結果:2025-01-01T01:00:00.123
System.out.println(dateTime6); //結果:2025-01-01T01:00:00
parse()メソッドで、ISO8601形式以外の文字列を解析する場合は、第2引数にDateTimeFormatterを指定します。DateTimeFormatterについては後ほど説明します。
5. 日時情報の取得
インスタンスの各フィールド(年月日などの情報)を個別に取得するには、get○○メソッドを利用します。
メソッド | 戻り値(指定がない場合はint型の整数) |
---|---|
public int getYear() | 年 |
public Month getMonth() | 月(列挙型のMonthクラス) |
public int getMonthValue() | 月 (int型の1~12) |
public int getDayOfMonth() | 日 |
public DayOfWeek getDayOfWeek() | 曜日(列挙型のDayOfWeekクラス) |
public int getHour() | 時 |
public int getMinute() | 分 |
public int getSecond() | 秒 |
public int getNano() | ナノ秒 |
LocalDateTime dateTime = LocalDateTime.of(2025, Month.JANUARY, 2, 3, 45, 6, 789_000_000);
System.out.println("年. :" + dateTime.getYear()); //年 :2025
System.out.println("月(Enum):" + dateTime.getMonth()); //月(Enum):JANUARY
System.out.println("月(int) :" + dateTime.getMonthValue()); //月(int) :1
System.out.println("日 :" + dateTime.getDayOfMonth()); //日 :2
System.out.println("曜日 :" + dateTime.getDayOfWeek()); //曜日 :THURSDAY
System.out.println("時 :" + dateTime.getHour() ); //時 :3
System.out.println("分 :" + dateTime.getMinute()); //分 :45
System.out.println("秒 :" + dateTime.getSecond()); //秒 :6
System.out.println("ナノ秒 :" + dateTime.getNano()); //ナノ秒 :789000000
6. インスタンスから任意の形式の文字列を取得
「Date and Time API」の主要クラスには、toString()メソッドが実装されています。そのため、toString()メソッドやSystem.out.print()などを呼び出すことで、文字列を取得できます。
LocalDateTime now = LocalDateTime.now();
String dateString = now.toString();
System.out.println(dateString);
//結果:2025-09-05T14:48:41.123456789
しかし、この時取得できる文字列は、ISO8601形式に限られます。この形式は、コンピュータにとっては理解しやすいですが、人間にとっては理解しにくいという欠点があります。
日時のインスタンス情報を、人間にもわかりやすい形式で取得したいときに利用するのが、DateTimeFormatterクラスです。
1. DateTimeFormatter
DateTimeFormatterは、書式を定義することで、日時と文字列の相互変換を可能にする双方向のフォーマッタです。
このフォーマッタを利用することで、日時情報を任意の形式の文字列で取得することができます。
書式を定義する際には、DateTimeFormatterのstaticメソッドであるofPattern()メソッドを利用します。
メソッド | 説明 |
---|---|
public static DateTimeFormatter ofPattern(String pattern) | 引数で指定された書式を使用してフォーマッタを作成します |
2. パターン文字
書式を定義するには、「パターン文字」を使用します。「パターン文字」とは、特定の日時要素(年、月、日、時、分など)を表すための文字です。パターン文字が日時要素を、文字の繰り返し数で表示形式を表します。
パターン文字 | 説明 | 表示形式 |
---|---|---|
y | 年 | y: 2025, yy: 25, yyy: 2025, yyyy: 2025 |
M | 月 | M: 9, MM: 09, MMM: 9月, MMMM: 九月 |
d | 日 | d: 5, dd: 05 |
E | 曜日 | E: Wed, EE: Wed, EEE: Wed, EEEE: 水曜日 |
a | 午前/午後 | a:午前 |
H | 時(24時間) | H: 14, HH: 14 |
h | 時(12時間) | h: 2, hh: 02 |
m | 分 | m: 8, mm: 08 |
s | 秒 | s: 6, ss: 06 |
- パターン文字の繰り返しが1回の場合は、桁数に関わらずそのまま表示されます(例 y:2025, M:12)
- 繰り返しが2回の場合は、1桁の数字の先頭に「0」が付与されます。(例 MM:05, dd:05)
- パターン文字以外の文字("年","月", "/",空白など)は、そのまま文字列として出力されます。
3. formatメソッド
DateTimeFormatterで定義した書式を用いて文字列を取得するには、format()メソッドを使用します。
メソッド | 説明 |
---|---|
public String format(TemporalAccessor temporal) | 引数で指定されたフォーマッタを使用して日付/時間オブジェクトを文字列に変換します |
ofPattern()メソッドとformat()メソッドを使って、いくつかの書式パターンで文字列を取得してみましょう。
LocalDateTime dateTime = LocalDateTime.of(2025, 9, 10, 1, 20, 30);
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String formatted1 = dateTime.format(formatter1);
System.out.println(formatted1);
// 結果: 2025/09/10
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH時mm分ss秒");
String formatted2 = dateTime.format(formatter2);
System.out.println( formatted2);
// 結果: 2025年09月10日 01時20分30秒
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("M月d日(EEEE) a h時m分");
String formatted3 = dateTime.format(formatter3);
System.out.println(formatted3);
// 結果: 9月10日(水曜日) 午前 1時20分
4. 任意の文字列から、インスタンスを生成する
DateTimeFormatterを利用すると、任意の文字列からインスタンスを生成することができます。
上で説明したように、日時情報を指定してインスタンスを生成する場合は、日時情報を1つずつ指定する方法と、ISO8601形式の文字列で指定する方法がありました。
しかし時に、ISO8601形式ではない文字列からインスタンスを生成したい場合があります。
そのような場合、DateTimeFormatterを利用することで、日時情報を正しくコンピュータに読み込ませることができます。
String dateTimeString = "2025年09月05日 15時00分";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH時mm分");
LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
まとめ
-
Java 8で導入された「Date and Time API」は、旧来のDateやCalendarクラスが持つ問題点(可変性、直感的でないAPIなど)を解決し、より安全で扱いやすい日時操作を提供します
-
ローカル日時を扱うLocalDateTime, LocalDate, LocalTimeクラスは、タイムゾーンを持たないことで、人間の感覚に近い日時をシンプルに表現できます
-
インスタンスの生成には、現在日時を取得するnow()、日時を指定するof()、文字列を解析するparse()といったstaticメソッドを使用します
-
DateTimeFormatterクラスを利用することで、yyyy/MM/ddのような任意の書式で日時を文字列に変換したり、逆に特定の書式の文字列からインスタンスを生成したりすることが可能です
記事は以上です。
最後までお読みいただき、ありがとうございました。
参考情報一覧
この記事は以下の情報を参考にして執筆しました。
- [スッキリわかるJava入門 第4版]
- [パーフェクトJava 改訂3版]
- [プロになるJava]
- 20.2 Date and Time API(LocalDateTimeクラス、LocalDateクラス、LocalTimeクラス、Periodクラス、Durationクラス、ZonedDateTimeクラスなど)~Java Basic編 (最終更新 2023-11-05) (参照 2025-09-03)
- 公式ドキュメント (参照 2025-09-03)
Discussion