【Java】日時処理(LocalDateTime)
はじめに
Java の日時処理としてDateやCalendarが使用されていましたが、Java8 以降ではLocalDateTimeが新たに追加されました。
Dateなどは性能面などの問題があるため、Java8 以降を使用する場合はLocalDateTimeを使用することが推奨されています。
この記事では、このLocalDateTimeの基本的な使用方法について説明していきます。
関連クラスについて
LocalDateTimeはjava.timeパッケージに定義されています。
このパッケージには、日付のみを扱うLocalDateや時間のみを扱うLocalTimeなどのクラスも定義されています。
説明を忘れていましたが、LocalDateTimeは日付+ 時間を扱うクラスになります。
そのため、時間が必要ない場合はLocalDateを使うなど、使い分けをします。
その他にもjava.timeには日時処理に関するクラスが定義されていますが、ここでは割愛します。
インスタンスの生成
LocalDateTimeは、インスタンスを生成するために以下のstaticなメソッドが用意されています。
now
nowは現在日時が設定されたインスタンスを生成します。
LocalDateTime datetime = LocalDateTime.now();of
ofは年、月、日、時、分、秒、ナノ秒を数値とし直接指定することでインスタンスを生成します。
秒、ナノ秒は省略できるようオーバーロードされています。省略した場合は 0 が設定されます。
LocalDateTime datetime1 = LocalDateTime.of(2021, 1, 1, 10, 20, 30, 123456); //2021/1/1 10:20:30.123456
LocalDateTime datetime2 = LocalDateTime.of(2021, 1, 1, 10, 20, 30; //2021/1/1 10:20:30.000
LocalDateTime datetime3 = LocalDateTime.of(2021, 1, 1, 10, 20); //2021/1/1 10:20:00.000月は数値でなくMonthという列挙型で指定することもできます。
LocalDateTime datetime3 = LocalDateTime.of(2021, Month.JANUARY, 1, 10, 20); //2021/1/1 10:20:00.000またLocalDateとLocalTimeを合わせるようにインスタンスを生成することができます。
逆にtoLocalDate、toLocalTimeによってLocalDateとLocalTimeに分離することもできます。
LocalDate date = LocalDate.of(2021, 1, 1);
LocalTime time = LocalTime.of(10, 20, 30);
LocalDateTime datetime = LocalDateTime.of(date, time); //2021/1/1 10:20:30.000
LocalDate date1 = datetime.toLocalDate();
LocalTime time1 = datetime.toLocalTime();parse
parseは対象の文字列に対し、フォーマットを指定することでインスタンスを生成することができます。
フォーマットについては後述します。
String strDateTime = "2021/01/01/ 10:20:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss");
LocalDateTime datetime = LocalDateTime.parse(strDateTime, formatter);日時の計算
加減算
日時の加減算は以下項目ごとにメソッドが用意されています。
LocalDate、LocalTimeでも対応する項目については用意されています。
| 項目 | 加算 | 減算 |
|---|---|---|
| 年 | plusYears | minusYears |
| 月 | plusMonths | minusMonths |
| 日 | plusDays | minusDays |
| 週 | plusWeeks | minusWeeks |
| 時 | plusHours | minusHours |
| 分 | plusMinutes | minusMinutes |
| 秒 | plusSeconds | minusSeconds |
| ナノ秒 | plusNanos | minusNanos |
LocalDateTime datetime = LocalDateTime.of(2021, 1, 1, 10, 20, 30, 123456); //2021/1/1 10:20:30.123456
datetime = datetime.plusYears(1); //2022/1/1 10:20:30.123456
datetime = datetime.minusMonths(3); //2021/10/1 10:20:30.123456差分
日時の差分は列挙型であるChronoUnitのbetweenを使用します。
例えば日付の差分を取得する場合、列挙型定数のDAYSを使用します。
LocalDateTime datetime1 = LocalDatetime.of(2021, 1, 1, 10, 20);
LocalDateTime datetime2 = LocalDatetime.of(2021, 1, 10, 10, 20);
ChronoUnit.DAYS.between(datetime1, datetime2); // 9
ChronoUnit.DAYS.between(datetime2, datetime1); // -9
datetime1 = LocalDatetime.of(2021, 1, 1, 12, 20);
ChronoUnit.DAYS.between(datetime1, datetime2); // 8日22時間の差 結果として8が返る別の単位で比較したい場合は、対応する列挙型定数を選択します。
| 項目 | 加算 |
|---|---|
| 年 | YEARS |
| 月 | MONTHS |
| 日 | DAYS |
| 週 | WEEKS |
| 時 | HOURS |
| 分 | MINUTES |
| 秒 | SECONDS |
| ミリ秒 | MILLIS |
| ナノ秒 | NANOS |
日時の比較
LocalDateTimeを比較する場合、ChronoUnitによる差分で行うこともできますが、
isAfter、isBefore、isEqualを使用することでよりシンプルに表現することができます。
LocalDateTime datetime1 = LocalDatetime.of(2021, 1, 1, 10, 20);
LocalDateTime datetime2 = LocalDatetime.of(2021, 1, 10, 10, 20);
LocalDateTime datetime3 = LocalDatetime.of(2021, 1, 10, 10, 20);
datetime1.isAfter(datetime2); //false
datetime1.isBefore(datetime2); //true
datetime2.isAfter(datetime1); //true
datetime2.isBefore(datetime1); //false
datetime2.isAfter(datetime3); //false
datetime2.isBefore(datetime3); //false
datetime2.isEqual(datetime3); //trueこれらの比較はナノ秒までのすべての単位が対象になります。
LocalDateとLocalTimeにも同様の比較メソッドがあります。
日時のフォーマット
format
LocalDateTimeを指定したフォーマットの文字列に変換する場合は、formatを使用します。
その際、フォーマットの指定にはDateTimeFormatterを使用します。
LocalDateTime datetime = LocalDatetime.of(2021, 1, 1, 10, 20);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss");
String strDatetime = datetime.format(formatter); //2021/01/01 10:20:00説明済みですが、文字列から日時に変換する場合はparseを使用します。
その際にも、フォーマットの指定にDateTimeFormatterを使用します。
フォーマット文字
フォーマットは主に以下の文字を使用します。
| 文字 | 単位 | 補足 |
|---|---|---|
u | 年 | 西暦 |
y | 年 | 暦(ERA)に対する年 |
G | 年号 | |
M | 月 | |
d | 日 | |
H | 時 | 24 時間(0〜23)表記 |
h | 時 | 12 時間(0〜11)表記 |
m | 分 | |
s | 秒 | |
S | ミリ秒以下 | |
a | 午前・午後 | |
E | 曜日 |
これらの文字は文字数によって、その表現が異なります。
西暦を表すuやyは通常2021のように 4 桁ですが、uuとすることで21と下 2 桁で変換されます。
ちなみにuとuuuuは同じ2021となりますが、多くは桁の合うuuuuを使用します。
年以外の月、日、時、分、秒は、MMのように 2 文字とすると 0 詰めされます。
例えば 1 月の場合、Mは1、MMは01と変換されます。
また曜日はEの場合火と変換されますが、EEEEとすれば火曜日と変換されます。
ロケール
フォーマットを行う際にロケールを指定することができます。
このロケールによってGやEなどは指定したロケールの表現に変わります。
LocalDateTime datetime = LocalDatetime.of(2021, 1, 1, 10, 20);
DateTimeFormatter formatterJp = DateTimeFormatter.ofPattern("E");
DateTimeFormatter formatterEn = DateTimeFormatter.ofPattern("E", Locale.ENGLISH);
String jp = datetime.format(formatterJp); //金
String en = datetime.format(formatterEn); //Fri日本日付
Gは年号を表しますが、実はLocalDateTimeでは西暦と変換されます。
これを日本の年号である平成や令和に変換したい場合には、JapaneseDateを使用します。
LocalDateTime datetime = LocalDatetime.of(2021, 1, 1, 10, 20);
JapaneseDate dateJp = JapanseDate.from(datetime);
DateTimeFormatter formatterJp = DateTimeFormatter.ofPattern("G");
String jp = dateJp.format(formatter); //令和