java.svg

【Java】日時処理(LocalDateTime)

Java

はじめに

Java の日時処理としてDateCalendarが使用されていましたが、Java8 以降ではLocalDateTimeが新たに追加されました。

Dateなどは性能面などの問題があるため、Java8 以降を使用する場合はLocalDateTimeを使用することが推奨されています。

この記事では、このLocalDateTimeの基本的な使用方法について説明していきます。

関連クラスについて

LocalDateTimejava.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

またLocalDateLocalTimeを合わせるようにインスタンスを生成することができます。 逆にtoLocalDatetoLocalTimeによってLocalDateLocalTimeに分離することもできます。

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);

日時の計算

加減算

日時の加減算は以下項目ごとにメソッドが用意されています。 LocalDateLocalTimeでも対応する項目については用意されています。

項目加算減算
plusYearsminusYears
plusMonthsminusMonths
plusDaysminusDays
plusWeeksminusWeeks
plusHoursminusHours
plusMinutesminusMinutes
plusSecondsminusSeconds
ナノ秒plusNanosminusNanos
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

差分

日時の差分は列挙型であるChronoUnitbetweenを使用します。

例えば日付の差分を取得する場合、列挙型定数の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による差分で行うこともできますが、 isAfterisBeforeisEqualを使用することでよりシンプルに表現することができます。

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

これらの比較はナノ秒までのすべての単位が対象になります。

LocalDateLocalTimeにも同様の比較メソッドがあります。

日時のフォーマット

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
H24 時間(0〜23)表記
h12 時間(0〜11)表記
m
s
Sミリ秒以下
a午前・午後
E曜日

これらの文字は文字数によって、その表現が異なります。

西暦を表すuyは通常2021のように 4 桁ですが、uuとすることで21と下 2 桁で変換されます。 ちなみにuuuuuは同じ2021となりますが、多くは桁の合うuuuuを使用します。

年以外の月、日、時、分、秒は、MMのように 2 文字とすると 0 詰めされます。 例えば 1 月の場合、M1MM01と変換されます。

また曜日はEの場合と変換されますが、EEEEとすれば火曜日と変換されます。

ロケール

フォーマットを行う際にロケールを指定することができます。 このロケールによってGEなどは指定したロケールの表現に変わります。

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