S-JIS[2014-07-20/2017-09-27] 変更履歴

Java期間・時間クラス

Java日付時刻APIの期間・時間クラスについて。


概要

期間(日付と日付の間隔(日数))や時間(時刻と時刻の間隔(秒数))を保持するクラスは、java.time.temporal.TemporalAmountインターフェースのサブクラスになっている。

(余談だが、時刻と時間は混同されることがよくある。「時刻」は時点(瞬間)を表し、時刻同士の間(間隔)を表すのが「時間」。
「いま何時?」という質問は時刻を聞いている。「どれくらいかかった?」という質問は時間を聞いている。時刻を聞くための「今の時間は?」という言い方は厳密には間違っている)

import java.time.*;
期間・時間クラス
要素 クラス名 親インターフェース 説明 保持する値の例 備考
期間 Period TemporalAmount 日付と日付の間隔。
内部では年・月・日(int)で値を保持している。
ちなみに、「1年」と「12ヶ月」は等しくない
P1Y2M3D
P1M
P0D
toString()で表示すると、先頭が「P」から始まる文字列になっている。
「1Y」は1年、「2M」は2ヶ月、「3D」は3日を表す。負の数になる場合もある。
0の場合はその要素は省略される。全要素が0の場合は「0D」になる。
時間 Duration TemporalAmount 時刻と時刻の間隔。
内部では秒(long)とナノ秒(int)で値を保持している。
PT1H2M3S
PT1H2M3.000000004S
PT48H
PT0S
toString()で表示すると、先頭が「PT」から始まる文字列になっている。
「1H」は1時間、「2M」は2分、「3S」は3秒を表す。負の数になる場合もある。
秒以下(ナノ秒まで)がある場合は秒(S)の小数で表される。
1日を超える場合は時間(H)の値が大きくなる。
0の場合はその要素は省略される。全要素が0の場合は「0S」になる。

時間・期間の例

import java.time.*;
import java.time.temporal.*;
期間(Period)の例
内容 備考
0 Period p = Period.ZERO;  
生成
(of)
Period p = Period.of(1, 2, 3); 内部では年・月・日が別々に保持される。
Period p = Period.ofYears(1);
Period p = Period.ofMonths(1);
Period p = Period.ofWeeks(1);
Period p = Period.ofDays(1);
1週間は7日扱い。
間隔
(between)
Period p = Period.between(localDate1, localDate2); 2つのLocalDateの間隔。(LocalDate以外は指定できない)
long days = ChronoUnit.DAYS.between(date1, date2); (Periodではないが)日数を取得する方法。[2017-06-10]
コピー
(from)
Period p = Period.from(otherPeriod); 他のPeriodをコピーする。
(引数の型はTemporalAmountなのだが、Durationを渡すと例外が発生する。サポートされている単位が異なる為)
文字列解析
(parse)
Period p = Period.parse("P1D");  
他単位への変換
(to)
long month = p.toTotalMonths(); 月数を返す。
1年は12ヶ月に換算される。日の値はどんなに大きくても無視される。
正規化
(normalize)
Period p = Period.of(1, 13, 70); //→ P1Y13M70D
Period n = p.normalized(); //→ P2Y1M70D
12ヶ月で1年になるよう正規化する。日の値は変わらない。
(左記の例では、正規化前と正規化後のオブジェクトをequalsで比較すると不一致になる)
各要素の取得
(get)
int year = p.getYears();
int month = p.getMonths();
int day = p.getDays();
 
long year = p.get(ChronoUnit.YEARS);
long month = p.get(ChronoUnit.MONTHS);
long day = p.get(ChronoUnit.DAYS);
 
一部要素の変更
(with)
Period p2 = p.withYears(1);
Period p2 = p.withMonths(12);
Period p2 = p.withDays(1);
 
演算
(plus・minus)
Period p2 = p.plusYears(1);
Period p2 = p.plusMonths(12);
Period p2 = p.plusDays(1);
 
Period p2 = p.minusYears(1);
Period p2 = p.minusMonths(12);
Period p2 = p.minusDays(1);
Period p3 = p1.plus(p2); 他のPeriodを加減算した新しいオブジェクトを返す。
Period p3 = p1.minus(p2);
演算
(multiply)
Period p2 = p.multipliedBy(2);  
符号反転(negate) Period p2 = p.negated();  
時刻クラスへの加算 LocalDate date = LocalDate.of(2014, 7, 19);
Temporal t = p.addTo(date);
日付・時刻クラスに加算する。
が、戻り型がTemporal(日付時刻クラスの親インターフェース)なので、日付時刻クラスのplus/minusメソッドを使う方が良さそう。
比較
(compare)
  PeriodにはcompareToは無い。
ゼロ判定 boolean zero = p.isZero();  
負数判定 boolean negative = p.isNegative();  
サポートチェック List<TemporalUnit> supported = p.getUnits(); (getメソッド等で)使用できる単位の一覧を返す。

時間(Duration)の例
内容 備考
0 Duration d = Duration.ZERO;  
生成
(of)
Duration d = Duration.ofDays(1);
Duration d = Duration.ofHours(24);
Duration d = Duration.ofMinutes(60);
Duration d = Duration.ofSeconds(60);
Duration d = Duration.ofSeconds(60, 0);
Duration d = Duration.ofMillis(1000);
Duration d = Duration.ofNanos(1);
内部では秒・ナノ秒に変換されて保持される。
Duration d = Duration.of(1, ChronoUnit.DAYS); 単位を指定して生成。
日より大きい単位は指定できない。(1ヶ月の日数が不定だからだろう)
間隔
(between)
Duration d = Duration.between(dt1, dt2); 2つの日付時刻オブジェクトの間隔。
コピー
(from)
Duration d = Duration.from(otherDuration); 他のDurationをコピーする。
(引数の型はTemporalAmountなのだが、Periodを渡すと例外が発生する。サポートされている単位が異なる為)
文字列解析
(parse)
Duration d = Duration.parse("PT1H");  
他単位への変換
(to)
long day = d.toDays();
long hour = d.toHours();
long minute = d.toMinutes();
long second = d.toSeconds(); // Java9
long milli = d.toMillis();
long nano = d.toNanos();
各単位の値に変換する。[/2017-09-27]
long day = d.toDaysPart();
int hour = d.toHoursPart();
int minute = d.toMinutesPart();
int second = d.toSecondsPart();
int milli = d.toMillisPart();
int nano = d.toNanosPart();
Java9以降。[2017-09-27]
各要素の値(その単位の範囲内)を返す。
例えばtoHoursPart()は「toHours() % 24」、toMinutesPart()は「toMinutes() % 60」と同じ。
各要素の取得
(get)
long second = d.getSeconds();
int nano = d.getNano();
 
long second = d.get(ChronoUnit.SECONDS);
long nano = d.get(ChronoUnit.NANOS);
 
一部要素の変更
(with)
Duration d2 = d.withSeconds(60);
Duration d2 = d.withNanos(10);
 
演算
(plus・minus)
Duration d2 = d.plusDays(1);
Duration d2 = d.plusHours(1);
Duration d2 = d.plusMinutes(1);
Duration d2 = d.plusSeconds(1);
Duration d2 = d.plusMillis(1);
Duration d2 = d.plusNanos(1);
 
Duration d2 = d.minusDays(1);
Duration d2 = d.minusHours(1);
Duration d2 = d.minusMinutes(1);
Duration d2 = d.minusSeconds(1);
Duration d2 = d.minusMillis(1);
Duration d2 = d.minusNanos(1);
Duration d2 = d.plus(1, ChronoUnit.DAYS);  
Duration d2 = d.minus(1, ChronoUnit.DAYS);
Duration d3 = d1.plus(d2); 他のDurationを加減算した新しいオブジェクトを返す。
Duration d3 = d1.minus(d2);
演算
(multiply・divide)
Duration multi = d.multipliedBy(2);  
Duration divide = d.dividedBy(2);  
long divide = d.dividedBy(d2); Java9以降。[2017-09-27]
絶対値(abs) Duration a = d.abs();  
符号反転(negate) Duration n = d.negated();  
時刻クラスへの加算 LocalTime time = LocalTime.of(1, 0);
Temporal t = d.addTo(time);
日付・時刻クラスに加算する。
が、戻り型がTemporal(日付時刻クラスの親インターフェース)なので、日付時刻クラスのplus/minusメソッドを使う方が良さそう。
切り捨て(truncate) Duration d = Duration.ofHours(24 + 12);
Duration d2 = d.truncatedTo(ChronoUnit.DAYS);
// PT36H → PT24H
Java9以降。[2017-09-27]
指定単位より小さい部分を切り捨てる。
比較
(compare)
boolean equals = d1.equals(d2);
int compare = d1.compareTo(d2);
compareToの結果とequalsの結果は一致する。
ゼロ判定 boolean zero = d.isZero();  
正数判定 boolean positive = d.isPositive() Java18以降。[2022-03-23]
負数判定 boolean negative = d.isNegative();  
サポートチェック List<TemporalUnit> supported = d.getUnits(); (plusやminusメソッド等で)使用できる単位の一覧を返す。

日付時刻APIに戻る / Java目次へ戻る / 新機能へ戻る / 技術メモへ戻る
メールの送信先:ひしだま