Categories: Java

【Java入門】Date And Time API(日付時間操作API)

現在日時を取得する方法

現在日時を取得するにはnow()メソッドを使用します。
コンストラクタは用意されていないため、newすることはできません。
Date And Time APIライブラリでは文字列表現として「YYYY-MM-DD」形式を採用しています。

Java

LocalDate.now();//「2019-11-15」が返る。
LocalTime.now();//「02:28:01.075」が返る。
LocalDateTime.now();//「2019-11-15T02:28:33.389」が返る。

文字列形式の日付を渡してLocalDateを生成する方法

文字列形式の日付を渡してLocalDateを生成するLocalDate#parse()を使用します。

Java

LocalDate.parse("2019-11-17");//「2019-11-17」が返る。
LocalDateTime.parse("2019-11-17T00:00:00.000");//「2019-11-17T00:00」が返る。

特定の日付を表すインスタンスの生成方法

特定の日付を表すインスタンスを生成するにはLocalDateクラスのof()メソッドを使用します。
of()メソッドの引数には日付を表すint値もしくは、java.time.Month型列挙定数(月のみ)を指定します。

Java

//書式
LocalDate.of(int year, int month, int dayOfMonth)

//実装例
LocalDate.of(2019,11,1)//「2019-11-01」が返る。

//書式
LocalDate.of(int year, Month month, int dayOfMonth)

//実装例
LocalDate.of(2019,Month.NOVEMBER.getValue(),1)//「2019-11-01」が返る。

コードの可読性を高めるため、月に関してはint値ではなく、Month型列挙定数を指定することが推奨されています。
列挙型定数を取得するには#getValue()メソッドを使用するのが望ましいです。これを用いれば1月~12月に対応した「1~12」のint値が返されます。

列挙型定数 曜日を表すDayOfWeekと月を表すMonth

Java

//DayOfWeek列挙定数の表示
for (DayOfWeek dayofweek : DayOfWeek.values()) {
    System.out.print(dayofweek + "|");
}
//出力結果
//MONDAY|TUESDAY|WEDNESDAY|THURSDAY|FRIDAY|SATURDAY|SUNDAY|

//Month列挙定数の表示
for (Month month : Month.values()) {
    System.out.print(month + "|");
}
//出力結果
//JANUARY|FEBRUARY|MARCH|APRIL|MAY|JUNE|JULY|AUGUST|SEPTEMBER|OCTOBER|NOVEMBER|DECEMBER|

ChronoUnit列挙型

日付や時間の単位を表すインターフェースの実装としてChronoUnit列挙型があります。
すべて単数形ではなく、複数形の単語であることに注意しよう。

  • SECONDSは1秒の概念を表す単位
  • HOURSは1時間の概念を表す単位
  • MINUTESは1分の概念を表す単位
  • DAYSは1日の概念を表す単位
  • WEEKSは1週間の概念を表す単位
  • MONTHSは1か月の概念を表す単位
  • YEARSは1年の概念を表す単位

ChronoUnitを引数に取る主なLocalDateTimeクラスのメソッド

メソッド 説明
boolean isSupported (TemporalUnit unit) 指定されたフィールドがサポートされている場合はTrue、サポートしていない場合はFalseを返す。
LocalDateTime minus(long amountTosubtract, TemporalUnit unit) 指定された時間量を減算したLocalDateTimeのコピーを返す。
LocalDateTime plus(long amountToAdd, TemporalUnit unit) 指定された時間量を加算したLocalDateTimeのコピーを返す。
LocalDateTime truncatedTo(TemporalUnit unit) 時間を切り捨てたLocalDateTimeのコピーを返す。
long until(Temporal endExclusive, TemporalUnit unit) もう一方のLocalDateTimeまでの時間量を指定された単位で計算する。

isSupportedの使用例は以下のとおりです。

Java

//「2019年11月17日」の日付データを生成。
LocalDate day1 = LocalDate.parse("2019-11-17");

//day1が「日付を」サポートするかチェックする。
boolean result1 = day1.isSupported(ChronoUnit.DAYS);
System.out.println(result1);//true

//day1が「秒」をサポートするかチェックする。
boolean result2 = day1.isSupported(ChronoUnit.SECONDS);
System.out.println(result2);//false

minusの使用例は以下のとおりです。

Java

//「2019年11月17日0時0分0秒0ミリ秒」の日付時間データを生成。
LocalDateTime day1 = LocalDateTime.parse("2019-11-17T00:00:00.000");

//そのまま出力。
System.out.println(day1);//「2019-11-17T00:00」が返る。

//minusでマイナス1日して出力。
System.out.println(day1.minus(1, ChronoUnit.DAYS));1日分マイナスされて「2019-11-16T00:00」が返る。

plusの使用例は以下のとおりです。

Java

//「2019年11月17日0時0分0秒0ミリ秒」の日付時間データを生成。
LocalDateTime day1 = LocalDateTime.parse("2019-11-17T00:00:00.000");

//そのまま出力。
System.out.println(day1);//「2019-11-17T00:00」が返る。

//plusでプラス1か月して出力。
System.out.println(day1.plus(1, ChronoUnit.MONTHS));//1か月分プラスされて「2019-12-17T00:00」が返る。

trunatedToの使用例は以下のとおりです。

Java

LocalDateTime day1 = LocalDateTime.parse("2019-11-17T15:20:15.000");
System.out.println(day1);//「2019-11-17T15:20:15」が返る。
System.out.println(day1.truncatedTo(ChronoUnit.DAYS));//「2019-11-17T00:00」が返る。

ChronoUnit.DAYSを指定したので日付未満が切り捨てられて「T00:00」になりました。

untilの使用例は以下のとおりです。

Java

LocalDateTime day1 = LocalDateTime.parse("2019-11-17T00:00:00.000");
LocalDateTime day2 = LocalDateTime.parse("2019-11-18T00:00:00.000");
System.out.println(day1.until(day2, ChronoUnit.DAYS));//「1」が返る。
System.out.println(day1.until(day2, ChronoUnit.MINUTES));//「1440」が返る。
System.out.println(day1.until(day2, ChronoUnit.MONTHS));//「0」が返る。

日付の比較(isBefore/isAfter/isEqual)

以下の3つのメソッドがあります。

  • boolean isBefore(ChronoLocalDateTime<?> other)
  • boolean isAfter(ChronoLocalDateTime<?> other)
  • boolean isEqual(ChronoLocalDateTime<?> other)
    使用例は以下のとおりです。

Java

LocalDate day1 = LocalDate.parse("2019-11-17");
LocalDate day2 = LocalDate.parse("2019-12-17");
System.out.println(day1.isBefore(day2));//true
System.out.println(day1.isAfter(day2));//false
System.out.println(day1.isEqual(day2));//false

日時を表すオブジェクトから別のオブジェクトを取得する

Java

System.out.println(LocalDate.from(LocalDateTime.now()));//「2020-05-31」
System.out.println(LocalTime.from(LocalDateTime.now()));//「17:47:03.267」

以下は情報を保持していないため実行時エラーになる例。

Java

System.out.println(LocalDateTime.from(LocaDate.now()));//時間の情報を持っていないため実行時エラーになる。
System.out.println(LocalDateTime.from(LocalTime.now()));//日付の情報を持っていないため実行時エラーになる。

TemporalUnitインターフェースが持つ計算用メソッド(addTo/between)

  • addTo
  • between

addToの使用例は以下のとおりです。

Java

LocalDateTime day1 = LocalDateTime.parse("2019-11-17T00:00:00.000");

//day1の5日後を取得。
System.out.println(ChronoUnit.DAYS.addTo(day1,5));//「2019-11-22T00:00」が返る。

betweenの使用例は以下のとおりです。

Java

LocalDateTime day1 = LocalDateTime.parse("2019-11-17T00:00:00.000");
LocalDateTime day2 = LocalDateTime.parse("2019-11-18T00:00:00.000");

System.out.println(ChronoUnit.DAYS.between(day1,day2));//「1」が返る。
System.out.println(ChronoUnit.DAYS.between(day2,day1));//「-1」が返る。

現在のタイムゾーンを取得する。

Java

System.out.println(ZoneId.systemDefault());//「Asia/Tokyo」が返される。

時間の間隔を表すクラス

Data and Time APIでは時間の間隔を表すクラスとして以下の2つがあります。

  • java.time.Durationは、時間ベースで間隔を表すクラス。
  • java.time.periodは、日付ベースで間隔を表すクラス。

基本的にはどちらのクラスもbetweenメソッドで「間隔」を取得してからメソッドを使う形になります。

Durationクラスの主なメソッド

メソッド 説明
int getNano() 間隔の秒内のナノ秒を取得する。
int getSeconds() 間隔の秒数を取得する。

getNanoの使用例は以下のとおりです。

Java

LocalDateTime day1 = LocalDateTime.parse("2019-11-17T12:34:56.789");
LocalDateTime day2 = LocalDateTime.parse("2019-11-17T12:34:56.800");
Duration d = Duration.between(day1, day2);
System.out.println(d.getNano());//「11000000」が返る。

しかし、秒が異なっていてもミリ秒が同じ値の場合、「0」で表示されてしまうので注意が必要。以下がその例。

Java

LocalDateTime day1 = LocalDateTime.parse("2019-11-17T12:34:56.789");
LocalDateTime day2 = LocalDateTime.parse("2019-11-17T12:34:58.789");
Duration d = Duration.between(day1, day2);
System.out.println(d.getNano());//「0」が返る。

day1は56秒でday2は58秒なので秒数は異なりますが、ミリ秒がどちらも789ミリ秒で同じなので同じなので結果は「0」になります。

getSecondの使用例は以下のとおりです。

Java

LocalDateTime day1 = LocalDateTime.parse("2019-11-17T12:34:56.789");
LocalDateTime day2 = LocalDateTime.parse("2019-11-17T12:34:58.800");
Duration d = Duration.between(day1, day2);
System.out.println(d.getSeconds());//「2」が返る。

day1は56秒でday2は58秒で差分が2秒なので「2」が返ります。

第1引数>第2引数 であれば結果はマイナス値になります。

Java

LocalDateTime day1 = LocalDateTime.parse("2019-11-17T12:34:56.789");
LocalDateTime day2 = LocalDateTime.parse("2019-11-17T12:34:54.800");
Duration d = Duration.between(day1, day2);
System.out.println(d.getSeconds());//「-2」が返る。

Periodクラスの主なメソッド

メソッド 説明
int getDay() 期間の日数を取得する。
int getMonths() 期間の月数を取得する。
int getYears() 期間の年数を取得する。

getDays(),getMonths(),getYears()の使用例は以下のとおりです。

Java

LocalDate day1 = LocalDate.parse("2019-11-17");
LocalDate day2 = LocalDate.parse("2020-12-20");
Period p = Period.between(day1, day2);

System.out.println(p.getDays());//「3」が返る。
System.out.println(p.getMonths());//「1」が返る。
System.out.println(p.getYears());//「1」が返る。

注意

年同士の比較、月同士の比較、日付同士の比較なので、1年過ぎていたからと言って月が13か月になったりはしません。

日時のフォーマット

日時の表示形式をフォーマットするにはjava.time.formatパッケージのDateTimeFormatterクラスを使用します。
従来のSimpleDateFormatはスレッドセーフではありませんでしたが、DateTimeFormatterクラスは不変でスレッドセーフなので積極的に使っていきましょう。

フィールド 説明
BASIC_ISO_DATE 基本的なISO日付
ISO_DATE オフセット付き、またはオフセットなしのISO日付
ISO_LOCAL_DATE ISOローカル日付
ISO_OFFSET_TIME オフセット付きの時間

使用例は以下のとおり。

Java

LocalDateTime localDateTime = LocalDateTime.of(2019, 11, 18, 13, 4, 5, 123456789);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());

DateTimeFormatter formatter = DateTimeFormatter.BASIC_ISO_DATE;
System.out.println("BASIC_ISO_DATE: " + formatter.format(localDateTime));//BASIC_ISO_DATE: 20191118

formatter = DateTimeFormatter.ISO_DATE;
System.out.println("ISO_DATE: "+ formatter.format(localDateTime));//ISO_DATE: 2019-11-18

formatter = DateTimeFormatter.ISO_LOCAL_DATE;
System.out.println("ISO_LOCAL_DATE?: " + formatter.format(localDateTime));//ISO_LOCAL_DATE: 2019-11-18

formatter = DateTimeFormatter.ISO_OFFSET_DATE;
System.out.println("ISO_OFFSET_DATE?: "+ formatter.format(zonedDateTime));//ISO_OFFSET_DATE: 2019-11-18+09:00

formatter = DateTimeFormatter.ISO_OFFSET_TIME;
System.out.println("ISO_OFFSET_TIME: "+ formatter.format(zonedDateTime));//ISO_OFFSET_TIME: 13:04:05.123456789+09:00

独自のカスタムパターン

独自のカスタムパターンを指定してDateTimeFormatterインスタンスを取得するにはofPatternメソッドを使用します。

Java

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ld = LocalDateTime.parse("2019-11-18 12:20:00", dtf);
System.out.println(ld);//「2019-11-18T12:20」が返る。

エポック秒

java.time.Instantクラスは、時系列上の単一時点を表すクラスです。
具体的には1970年1月1日午前0時0分0秒からの経過秒数(エポック秒)を保持しています。
(instantには「瞬間」という意味がある。)

機能 説明
now()メソッド Instantインスタンスを取得するファクトリ・メソッド
instantクラスのstatic定数フィールドEPOCH エポック秒の起点を取得する。
toEpochSecond()メソッド 現在の経過秒を取得する。long型を返す。
toEpochMilli()メソッド 現在の経過ミリ秒を取得する。long型を返す。

(1年は31,536,000秒=60秒×60分×24時間×365日)

Java

//エポック秒「1970-01-01T00:00:00Z」が返る
System.out.println(Instant.EPOCH);

//Instantインスタンスを取得するコード
Instant.now();

//エポックから現在までのミリ秒「1577001432837」が返る
System.out.println(Instant.now().toEpochMilli());

//エポックから現在までの秒「1577001632」が返る
System.out.println(Instant.now().getEpochSecond());

以上で記事の解説はお終い!

もっとJavaやSpringを勉強したい方にはUdemyがオススメ!同僚に差をつけよう!

issiki_wp