概要
パッケージ java.time.temporalは、Date and Time APIのパッケージjava.timeのサブパッケージで、時間的オブジェクト(temporal object)を操作する基本的なインターフェースや列挙型が定義されています。
この記事は、これらのインターフェースの使い方をおさらいしたときの記録になります。
環境
- Windows 10 Professional
- Oracle JDK 1.8.0_162
- Oracle JDK 10.0.1
参考
- [パッケージ java.time.temporal - JDK 1.8] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/package-summary.html)
- [パッケージ java.time - JDK 1.8] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/package-summary.html)
- [Oracle JDK 9ドキュメント] (https://docs.oracle.com/javase/jp/9/index.html)
- [Oracle JDK 10ドキュメント] (https://docs.oracle.com/javase/jp/10/index.html)
[インタフェース Temporal] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/Temporal.html)
時間的オブジェクト(日付、時間、オフセット、またはそれらのなんらかの組合せなど)への読取り/書込みアクセスを定義するフレームワークレベルのインタフェースです。
時間的オブジェクト(temporal object)の実装クラスには、LocalDate, LocalDateTime, LocalTime, Year, YearMonthなどがあります。
注意
このインタフェースはフレームワークレベルのインタフェースであり、アプリケーション・コードで広範囲にわたって使用しないようにしてください。かわりに、LocalDateなどの具象型のインスタンスを作成して使い回してください。これには様々な理由がありますが、その1つはこのインタフェースの実装がISO以外の暦体系になっている可能性があることです。この問題の詳細は、ChronoLocalDateを参照してください。
minus
default Temporal minus(TemporalAmount amount)
default Temporal minus(long amountToSubtract, TemporalUnit unit)
簡単な用例
時間的オブジェクトにTemporalAmountで表現する時間量で減算します。
Period period = Period.ofDays(10);
LocalDate.of(2018, 1, 30).minus(period);
時間的オブジェクトにTemporalUnitで表現する単位で減算します。
LocalDate.of(2018, 1, 30).minus(10, ChronoUnit.DAYS);
この用例でいえばよりシンプルにminusDaysを使うこともできます。
LocalDate.of(2018, 1, 30).minusDays(10);
plus
default Temporal plus(TemporalAmount amount)
Temporal plus(long amountToAdd, TemporalUnit unit)
簡単な用例
時間的オブジェクトにTemporalAmountで表現する時間量で加算します。
Period period = Period.ofDays(10);
LocalDate.of(2018, 1, 30).plus(period);
時間的オブジェクトにTemporalUnitで表現する単位で加算します。
LocalDate.of(2018, 1, 30).plus(10, ChronoUnit.DAYS);
この用例でいえばよりシンプルにplusDaysを使うこともできます。
LocalDate.of(2018, 1, 30).plusDays(10);
until
2つの時間的オブジェクトの間の時間量を指定した単位で計算します。
long until(Temporal endExclusive, TemporalUnit unit)
簡単な用例
LocalDate endExclusive = LocalDate.of(2019, 1, 1);
LocalDate.of(2018, 1, 1).until(endExclusive, ChronoUnit.DAYS);
// → 365
LocalDate.of(2018, 1, 1).until(endExclusive, ChronoUnit.MONTHS);
// → 12
LocalDate.of(2018, 1, 1).until(endExclusive, ChronoUnit.YEARS);
// → 1
with
default Temporal with(TemporalAdjuster adjuster)
Temporal with(TemporalField field, long newValue)
簡単な用例
時間的オブジェクトのTemporalFieldで指定したフィールドを変更します。
LocalDate.of(2018, 1, 1).with(ChronoField.MONTH_OF_YEAR, 3);
この用例でいえばよりシンプルにwithMonthを使うこともできます。
LocalDate.of(2018, 1, 1).withMonth(3);
[インタフェース TemporalAccessor] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/TemporalAccessor.html)
時間的オブジェクト(日付、時間、オフセット、またはそれらのなんらかの組合せなど)への読取り専用アクセスを定義するフレームワークレベルのインタフェースです。
サブインターフェースにTemporalがあり、実装クラスには, LocalDate, LocalDateTime, LocalTime, Month, MonthDay, Year, YearMonthなどがあります。
注意
このインタフェースはフレームワークレベルのインタフェースであり、アプリケーション・コードで広範囲にわたって使用しないようにしてください。かわりに、LocalDateなどの具象型のインスタンスを作成して使い回してください。これには様々な理由がありますが、その1つはこのインタフェースの実装がISO以外の暦体系になっている可能性があることです。この問題の詳細は、ChronoLocalDateを参照してください。
get
時間的オブジェクトの指定されたフィールドの値を返します。
default int get(TemporalField field)
簡単な用例
LocalDateTime.now().get(ChronoField.DAY_OF_MONTH);
この用例でいえばよりシンプルなgetDayOfMonthがあります。
LocalDateTime.now().getDayOfMonth();
query
時間的オブジェクトに関数型インターフェースTemporalQueryの実装を使って問い合わせをします。
default <R> R query(TemporalQuery<R> query)
簡単な用例
月の最初の日曜日の週をその月の第1週として、月の第2月曜日と第3木曜日を問い合わせるクエリです。
たとえば、2018年2月の第1週は2月4日(日)から始まる週とします。(2月1日(月)は、2018年1月の第4週に含まれます。)
TemporalQuery<Boolean> isRegularHoliday = accessor -> {
LocalDate target = LocalDate.from(accessor);
LocalDate first = target.with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY));
switch (DayOfWeek.of(target.get(ChronoField.DAY_OF_WEEK))) {
case MONDAY:
if (target.equals(first.plusDays(8))) {
return true;
}
break;
case THURSDAY:
if (target.equals(first.plusDays(18))) {
return true;
}
break;
default:
break;
}
return false;
};
LocalDate.of(2018, 2, 5).query(isRegularHoliday);
// → false
LocalDate.of(2018, 2, 8).query(isRegularHoliday);
// → false
LocalDate.of(2018, 2,12).query(isRegularHoliday);
// → true
LocalDate.of(2018, 2,15).query(isRegularHoliday);
// → false
LocalDate.of(2018, 2,19).query(isRegularHoliday);
// → false
LocalDate.of(2018, 2,22).query(isRegularHoliday);
// → true
LocalDate.of(2018, 2,26).query(isRegularHoliday);
// → false
range
時間的オブジェクトの指定したフィールドの有効な範囲を返します。(たとえば月の日数、年の日数など)
default ValueRange range(TemporalField field)
簡単な用例
2020年2月の月の範囲を求めます。
ValueRange range = LocalDate.of(2020, 2, 1).range(ChronoField.DAY_OF_MONTH);
range.toString();
// 1- 29
[インターフェース TemporalField] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/TemporalField.html)
月、時刻などの日付/時間のフィールドを表すインターフェースで、実装クラスにEnum ChronoFieldがあります。
adjustInto
指定した日付/時間フィールドに値を設定した新しい時間的オブジェクトを返します。
<R extends Temporal> R adjustInto(R temporal, long newValue)
簡単な用例
ChronoField.MONTH_OF_YEAR.adjustInto(LocalDate.now(), 12);
一般的な使い方として、可読性が高くなるwithを使うようにします。
LocalDate.now().with(ChronoField.MONTH_OF_YEAR, 12);
この用例でいえばよりシンプルなwithMonthがあります。
LocalDate.now().withMonth(12);
[列挙型 ChronoField] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/ChronoField.html)
フィールドの標準セットです。
定義されている主な定数(抜粋)
- YEAR : 年
- MONTH_OF_YEAR : 月
- DAY_OF_MONTH : 月の日
- HOUR_OF_DAY : 時
- MINUTE_OF_HOUR : 分
- SECOND_OF_MINUTE : 秒
- MILLI_OF_SECOND : 1秒のうちのミリ秒
- MICRO_OF_SECOND : 1秒のうちのマイクロ秒
- NANO_OF_SECOND : 1秒のうちのナノ秒
[インタフェース TemporalUnit] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/TemporalUnit.html)
日間、時間などの日付/時間の単位を表すインターフェースで、実装クラスにEnum ChronoUnitがあります。
addTo
時間的オブジェクトに日時の単位で表す時間量を加算した新しい時間オブジェクトを返します。
<R extends Temporal> R addTo(R temporal, long amount)
簡単な用例
ChronoUnit.DAYS.addTo(LocalDate.now(), 1);
一般的な使い方として、可読性が高くなるplusを使うようにします。
LocalDate.now().plus(1, ChronoUnit.DAYS);
この用例でいえばよりシンプルなplusDaysがあります。
LocalDate.now().plusDays(1);
between
2つの時間的オブジェクトの間の時間量を日時の単位で表した結果を返します。
long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive)
簡単な用例
ChronoUnit.DAYS.between(LocalDate.now(), LocalDate.now().plusDays(3));
一般的な使い方として、可読性が高くなるuntilを使うようにします。
LocalDate.now().until(LocalDate.now().plusDays(3), ChronoUnit.DAYS);
// → 3
Periodのインスタンスを返すメソッドもあります。
Period period = LocalDate.now().until(LocalDate.now().plusDays(3));
period.getDays()
// → 3
isSupportedBy
時間的オブジェクトが日時の単位をサポートしているか確認します。
default boolean isSupportedBy(Temporal temporal)
簡単な用例
ChronoUnit.HOURS.isSupportedBy(LocalDateTime.now());
// → true
ChronoUnit.HOURS.isSupportedBy(LocalDate.now());
// → false
ChronoUnit.HOURS.isSupportedBy(LocalTime.now());
// → true
ChronoUnit.HOURS.isSupportedBy(YearMonth.now());
// → false
[列挙型 ChronoUnit] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/ChronoUnit.html)
日付期間の単位の標準セットです。
定義されている主な単位(抜粋)
- YEARS : 1年の概念を表す単位。
- MONTHS : 1か月の概念を表す単位。
- DAYS : 1日の概念を表す単位。
- HOURS : 1時間の概念を表す単位。
- MINUTES : 1分の概念を表す単位。
- SECONDS : 1秒の概念を表す単位。
- MILLIS : 1ミリ秒の概念を表す単位 (1000分の1秒)
- MICROS : 1マイクロ秒の概念を表す単位 (100万分の1秒)
- NANOS : 1ナノ秒の概念を表す単位 (10億分の1秒)
[インタフェース TemporalAmount] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/TemporalAmount.html)
時間量を表すインターフェースで、具象クラスにはPeriod(年、月および日を格納する日付ベースの実装)、Duration(秒およびナノ秒を格納する時間ベースの実装)があります。
注意
このインタフェースはフレームワークレベルのインタフェースであり、アプリケーション・コードで広範囲にわたって使用しないようにしてください。かわりに、PeriodやDurationなどの具象型のインスタンスを作成して使い回してください。
Periodで表す時間量の例
1日を表す時間量
Period.ofDays(1);
1週間を表す時間量
Period.ofWeeks(1);
1カ月と10日を表す時間量
Period.ofMonths(1).plusDays(10);
Durationで表す時間量の例
1時間を表す時間量
Duration.ofHours(1);
30分を表す時間量
Duration.ofMinutes(30);
48時間を表す時間量
Duration.ofDays(2);
between
Duration.betweenで2つの時間的オブジェクトの時間量を計算することができます。
Duration duration = Duration.between(
LocalDateTime.of(2018, 1, 1, 0, 0, 0),
LocalDateTime.of(2018, 1, 2, 1, 2, 3)
);
duration.toDays();
// → 1
duration.toHours();
// → 25
duration.toMinutes();
// → 1502
duration.getSeconds();
// → 90123
- ちなみに、Durationクラスはjava.timeパッケージです。
TemporalAmountを引数に取るメソッド
インタフェースTemporalAccessorを実装したクラスであればplus/minusメソッドにTemporalAmountを利用できます。
addTo
LocalDateやLocalDateTimeなどの時間的オブジェクトにPeriodやDurationなどで表現する時間量を加算し新しい時間的オブジェクトを返します。
Temporal addTo(Temporal temporal)
簡単な用例
Period daysOfLimit = Period.ofDays(10);
Temporal temporal = daysOfLimit.addTo(LocalDate.of(2018, 1, 1));
LocalDate.from(temporal);
一般的な使い方として、可読性が高くなるplusを使うようにします。
Period daysOfLimit = Period.ofDays(10);
LocalDate.of(2018, 1, 1).plus(daysOfLimit);
この用例でいえばよりシンプルなplusDaysがあります。
LocalDate.of(2018, 1, 1).plusDays(10);
subtractFrom
LocalDateやLocalDateTimeなどの時間的オブジェクトにPeriodやDurationなどで表現する時間量を減算し新しい時間的オブジェクトを返します。
Temporal subtractFrom(Temporal temporal)
簡単な用例
Period daysOfLimit = Period.ofDays(10);
Temporal temporal = daysOfLimit.subtractFrom(LocalDate.of(2018, 2, 1));
LocalDate.from(temporal);
一般的な使い方として、可読性が高くなるminusを使うようにします。
Period daysOfLimit = Period.ofDays(10);
LocalDate.of(2018, 2, 1).minus(daysOfLimit);
この用例でいえばよりシンプルなminusDaysがあります。
LocalDate.of(2018, 2, 1).minusDays(10);
[インタフェース TemporalAdjuster] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/TemporalAdjuster.html)
時間的オブジェクトを調整する(たとえば特定の曜日、月の第2月曜日、月末などに設定)ためのインターフェースです。
なお、一般的な時間調整(月末日を求めるなど)は、クラス
TemporalAdjustersに実装されています。
関数型インターフェースなので、ラムダ式やメソッド参照として利用できます。
TemporalAdjusterを引数に取るメソッド
インターフェースTemporalを実装したクラスであればwithメソッドにTemporalAdjusterを利用できます。
adjustInto
時間的オブジェクトをアジャスタで調整した結果を新しい時間的オブジェクトとして返します。
Temporal adjustInto(Temporal temporal)
簡単な用例
次の月の第2月曜日の日付を求めます。
TemporalAdjuster adjuster = temporal -> {
LocalDate target = LocalDate.from(temporal);
// 当月の第2月曜日
LocalDate secondMonday = target
.with(TemporalAdjusters.firstDayOfMonth())
.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY))
.plusDays(7);
if (target.isBefore(secondMonday) || target.isEqual(secondMonday)) {
return secondMonday;
}
// 来月の第2月曜日
return secondMonday
.with(TemporalAdjusters.firstDayOfNextMonth())
.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY))
.plusDays(7);
};
Temporal temporal = adjuster.adjustInto(LocalDate.of(2018, 1, 1));
LocalDateTime.from(temporal);
// → 2018-01-08
一般的な使い方として、可読性が高くなるwithを使うようにします。
LocalDatee.of(2018, 1, 29).with(adjuster);
// → 2018-02-12
[クラス TemporalAdjusters] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/TemporalAdjusters.html)
一般的でよく使用される時間調整処理(たとえば月初または月末の日を求める、翌週の水曜日を求めるなど)がstaticメソッドとして実装されているクラスです。
このクラスには、staticメソッドとして使用できるアジャスタの標準セットが含まれています。これらの機能を次に示します。
- 月の最初または最後の日を見つける
- 翌月の最初の日を見つける
- その年の最初または最後の日を見つける
- 翌年の最初の日を見つける
- 月内の最初または最後の曜日(「6月の最初の水曜日」など)を見つける
- 次または前の曜日(「次の木曜日」など)を見つける
簡単な用例
今日日付以降の次の月曜日を求めます。
当日も含めたい場合はTemporalAdjusters.nextOrSameを使用します。
LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.MONDAY));
月末の日付を求めます。
LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
年末をの日付を求めます。
LocalDate.now().with(TemporalAdjusters.lastDayOfYear());
[インタフェース TemporalQuery<R>] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/TemporalQuery.html)
時間的オブジェクトへの問い合わせのためのインターフェースです。
実装クラスにTemporalQueriesがあります。
関数型インターフェースなので、ラムダ式やメソッド参照として利用できます。
TemporalQuery<R>を引数に取るメソッド
インタフェースTemporalAccessorを実装したクラスであればqueryメソッドにラムダ式やメソッド参照を使用できます。
queryFrom
R queryFrom(TemporalAccessor temporal)
簡単な用例
次の月曜日までの日数を求めます。
TemporalQuery<Long> daysOfNextMonday = accessor -> {
LocalDate inc = LocalDate.from(accessor);
LocalDate exc = inc.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));
return ChronoUnit.DAYS.between(inc, exc);
};
LocalDate.of(2018, 1, 29).query(daysOfNextMonday);
// → 0
LocalDate.of(2018, 1, 30).query(daysOfNextMonday);
// → 6
ラムダ式
LocalDate.of(2018, 1, 29).query( accessor -> {
LocalDate inc = LocalDate.from(accessor);
LocalDate exc = inc.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
return ChronoUnit.DAYS.between(inc, exc);
});
// → 7
メソッド参照
LocalDateTime.now().query(YearMonth::from);
// → 2018-01
[クラス TemporalQueries] (https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/TemporalQueries.html)
関数型インタフェースTemporalQueryを実装したクラスです。
localDate
時間的オブジェクトからLocalDateを問い合わせます。
public static TemporalQuery<LocalDate> localDate()
簡単な用例
LocalDate date = LocalDateTime.now().query(TemporalQueries.localDate());
メソッド参照
LocalDate date = LocalDateTime.now().query(LocalDate::from);
この用例でいえばよりシンプルなtoLocalDateがあります。
LocalDate date = localDateTime.now().toLocalDate();
localTime
時間的オブジェクトからLocalTimeを問い合わせます。
public static TemporalQuery<LocalTime> localTime()
簡単な用例
LocalTime time = LocalDateTime.now().query(TemporalQueries.localTime());
メソッド参照
LocalTime time = LocalDateTime.now().query(LocalTime::from);
この用例でいえばよりシンプルなtoLocalTimeがあります。
LocalTime time = localDateTime.now().toLocalTime();
Java 9で追加されたAPI
[パッケージ java.time.temporal] (https://docs.oracle.com/javase/jp/9/docs/api/java/time/temporal/package-summary.html)
- モジュール: java.base
追加はありません。
[パッケージ java.time] (https://docs.oracle.com/javase/jp/9/docs/api/java/time/package-summary.html)
- モジュール: java.base
[クラス Clock] (https://docs.oracle.com/javase/jp/9/docs/api/java/time/Clock.html)
tickMillis
public static Clock tickMillis(ZoneId zone)
[クラス Duration] (https://docs.oracle.com/javase/jp/9/docs/api/java/time/Duration.html)
dividedBy
public long dividedBy(Duration divisor)
toSeconds
public long toSeconds()
toDaysPart
public long toDaysPart()
toHoursPart
public int toHoursPart()
toMinutesPart
public int toMinutesPart()
toSecondsPart
public int toSecondsPart()
toMillisPart
public int toMillisPart()
toNanosPart
public int toNanosPart()
truncatedTo
public Duration truncatedTo(TemporalUnit unit)
[クラス LocalDate] ()
ofInstant
public static LocalDate ofInstant(Instant instant, ZoneId zone)
datesUntil
public Stream<LocalDate> datesUntil(LocalDate endExclusive)
datesUntil
public Stream<LocalDate> datesUntil(LocalDate endExclusive, Period step)
toEpochSecond
public long toEpochSecond(LocalTime time, ZoneOffset offset)
[クラス LocalTime] (https://docs.oracle.com/javase/jp/9/docs/api/java/time/LocalTime.html)
ofInstant
public static LocalTime ofInstant(Instant instant, ZoneId zone)
toEpochSecond
public long toEpochSecond(LocalDate date, ZoneOffset offset)
[クラス OffsetTime] (https://docs.oracle.com/javase/jp/9/docs/api/java/time/OffsetTime.html)
toEpochSecond
public long toEpochSecond(LocalDate date)
Java 10で追加されたAPI
[パッケージ java.time.temporal] (https://docs.oracle.com/javase/jp/10/docs/api/java/time/temporal/package-summary.html)
- モジュール: java.base
追加はありません。
[パッケージ java.time] (https://docs.oracle.com/javase/jp/10/docs/api/java/time/package-summary.html)
- モジュール: java.base
追加はありません。
Java 14で追加されたAPI
[パッケージ java.time.temporal] (https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/time/temporal/package-summary.html)
- モジュール: java.base
追加はありません。
[パッケージ java.time] (https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/time/package-summary.html)
- モジュール: java.base
追加はありません。
その他のおさらいメモ
- [Java NIO2のおさらいメモ] (https://qiita.com/rubytomato@github/items/6880eab7d9c76524d112)
- 2017年08月15日
- [クラス java.util.Objectsのおさらいメモ] (https://qiita.com/rubytomato@github/items/ba38877ed5a00dd24f16)
- 2017年08月25日
- [Java Collections Frameworkのおさらいメモ] (https://qiita.com/rubytomato@github/items/554095ae21a2c36f131a)
- 2017年08月30日
- [パッケージ java.time.temporal のおさらいメモ] (https://qiita.com/rubytomato@github/items/e9325dd46aa11f1b8e2e)
- 2018年01月30日
- [クラス java.util.Optionalのおさらいメモ] (https://qiita.com/rubytomato@github/items/92ac7944c830e54aa03d)
- 2018年03月22日