【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); //令和