7.3. 日付操作(JSR-310 Date and Time API)¶
7.3.1. Overview¶
java.util.Date
,java.util.Calendar
に比べて、様々な日時計算が提供されている JSR-310 Date and Time API の使用を推奨する。7.3.2. How to use¶
java.time.LocalDate
、java.time.LocalTime
、java.time.LocalDateTime
を中心に説明を進めるが、主要な日時操作については各クラスで提供されるメソッドの接頭辞が同一であるため、適時クラス名を置き換えて解釈されたい。クラス名 | 説明 | 主なファクトリメソッド |
---|---|---|
タイムゾーン・時差の情報を持たない日付・時刻の操作を行うクラス | now : 現在日時で生成of : 任意日時で生成parse : 日時文字列から生成from : 日時情報を持つ他オブジェクトから生成 |
|
タイムゾーン・時差を考慮した日付・時刻の操作を行うクラス | 同上 | |
和暦の操作を行うクラス | 同上 |
クラス名 | 説明 | 主なファクトリメソッド |
---|---|---|
日時ベース、時間ベースの期間を扱うクラス | between : 日時情報を持つ2つのオブジェクトの差から生成from : 時間量を持つ他オブジェクトから生成of : 任意期間で生成 |
クラス名 | 説明 | 主なファクトリメソッド |
---|---|---|
タイムゾーンを使用して現在の時刻、日付、時刻へのアクセスを提供するクラス | fixed : 常に同じ瞬間を返すClockを生成tick : 指定した瞬間からの変動時刻を返すClockを生成instant : タイムスタンプを取得 |
クラス名 | 説明 | 主なファクトリメソッド |
---|---|---|
日時のフォーマットに関する操作を行うクラス
|
ofPattern : 指定されたパターンでフォーマッタを生成 |
Note
本ガイドラインで触れなかった内容を含め、詳細はJavadocを参照されたい。
Note
Date and Time APIのクラスは、immutableである(日時計算等の結果は新規オブジェクトが返却されており、計算元オブジェクトに変化はない)。
Note
Java SE 17のロケールデータはCLDRがデフォルトとなる。(JEP 252参照。)
Java SE 8以前のロケールデータ(COMPAT)に切り替えたい場合はデフォルトで使用されるロケール・データの変更を参照されたい。
7.3.2.1. 日時取得¶
7.3.2.1.1. 現在日時で取得¶
java.time.LocalTime
、java.time.LocalDate
、java.time.LocalDateTime
を使い分けること。- 時刻のみ取得したい場合は
java.time.LocalTime
を使用する。
LocalTime localTime = LocalTime.now(); LocalTime localTime = LocalTime.now(clock);
- 日付のみ取得したい場合は
java.time.LocalDate
を使用する。
LocalDate localDate = LocalDate.now(); LocalDate localDate = LocalDate.now(clock);
- 日付・時刻を取得したい場合は
java.time.LocalDateTime
を使用する。
LocalDateTime localDateTime = LocalDateTime.now(); LocalDateTime localDateTime = LocalDateTime.now(clock);
7.3.2.1.2. 指定日時でオブジェクトを取得¶
- 時刻を指定して
java.time.LocalTime
を取得する。
// 23:30:59 LocalTime localTime = LocalTime.of(23, 30, 59);
- 日付を指定して
java.time.LocalDate
を取得する。
// 2015/12/25 LocalDate localDate = LocalDate.of(2015, 12, 25);
- 日付・時刻)を指定して
java.time.LocalDateTime
を取得する。
// 2015/12/25 23:30:59 LocalDateTime localDateTime = LocalDateTime.of(2015, 12, 25, 23, 30, 59);
java.time.temporal.TemporalAdjusters
を使うことで様々な日時を取得することができる。// LeapYear(2012/2)
LocalDate localDate1 = LocalDate.of(2012, 2, 1);
// Last day of month(2012/2/29)
LocalDate localDate2 = localDate1.with(TemporalAdjusters.lastDayOfMonth());
// Next monday(2012/2/6)
LocalDate localDate3 = localDate1.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
7.3.2.1.3. タイムゾーンを指定する場合の日時取得¶
java.time.OffsetTime
、java.time.OffsetDateTime
、java.time.ZonedDateTime
を使い分けること。- 時刻 + UTCとの時差を取得したい場合は、
java.time.OffsetTime
を使用する。
// Ex, 12:30:11.567+09:00 OffsetTime offsetTime = OffsetTime.now();
- 日付・時刻 + UTCとの時差を取得したい場合は
java.time.OffsetDateTime
を使用する。
// Ex, 2015-12-25T12:30:11.567+09:00 OffsetDateTime offsetDateTime = OffsetDateTime.now();
- 日付・時刻 + UTCとの時差・地域を取得したい場合は
java.time.ZonedDateTime
を使用する。
// Ex, 2015-12-25T12:30:11.567+09:00[Asia/Tokyo] ZonedDateTime zonedDateTime = ZonedDateTime.now();
java.time.ZoneId
を引数に設定することで、タイムゾーンを考慮した現在日時が取得できる。java.time.ZoneId
の例を示す。ZoneId zoneIdTokyo = ZoneId.of("Asia/Tokyo");
OffsetTime offsetTime = OffsetTime.now(zoneIdTokyo);
java.time.ZoneId
は地域名/地名形式で定義する方法や、UTCからの時差で定義する方法がある。ZoneId.of("Asia/Tokyo");
ZoneId.of("UTC+01:00");
java.time.OffsetDateTime
,java.time.ZonedDateTime
の2クラスは用途が似ているが、具体的には以下のような違いがある。クラス名 | 説明 |
---|---|
java.time.OffsetDateTime |
定量値(時差のみ)を持つため、各地域の時間の概念に変化がある場合も、システムに変化が起こらない。 |
java.time.ZonedDateTime |
時差に加えて地域の概念があるため、各地域の時間の概念に変化があった場合、システムに変化が起こる。(政策としてサマータイム導入される場合など) |
7.3.2.1.4. クロックを指定する場合の日時取得¶
7.3.2.2. 期間¶
7.3.2.2.1. 期間の取得¶
java.time.Period
、時間ベースの期間を扱う場合は、java.time.Duration
を使用する。java.time.Duration
で表される1日は厳密に24時間であるため、サマータイムの変化が解釈されずに想定通りの結果にならない可能性がある。java.time.Period
はサマータイムなどの概念を考慮した1日を表すため、サマータイムを扱うシステムであっても誤差は生じない。LocalDate date1 = LocalDate.of(2010, 01, 15);
LocalDate date2 = LocalDate.of(2011, 03, 18);
LocalTime time1 = LocalTime.of(11, 50, 50);
LocalTime time2 = LocalTime.of(12, 52, 53);
// One year, two months and three days.
Period pd = Period.between(date1, date2);
// One hour, two minutes and three seconds.
Duration dn = Duration.between(time1, time2);
Note
of
メソッドを利用して、期間を指定して生成する方法もある。詳細はPeriod, DurationのJavadocを参照されたい。
7.3.2.3. 型変換¶
7.3.2.3.1. Date and Time APIの各クラスの相互運用性¶
java.time.LocalTime
、java.time.LocalDate
、java.time.LocalDateTime
はそれぞれ容易に変換が可能である。java.time.LocalTime
からjava.time.LocalDateTime
への変換。
// Ex. 12:10:30 LocalTime localTime = LocalTime.now(); // 2015-12-25 12:10:30 LocalDateTime localDateTime = localTime.atDate(LocalDate.of(2015, 12, 25));
java.time.LocalDate
からjava.time.LocalDateTime
への変換。
// Ex. 2012-12-25 LocalDate localDate = LocalDate.now(); // 2015-12-25 12:10:30 LocalDateTime localDateTime = localDate.atTime(LocalTime.of(12, 10, 30));
java.time.LocalDateTime
からjava.time.LocalTime
,java.time.LocalDate
への変換。
// Ex. 2015-12-25 12:10:30 LocalDateTime localDateTime = LocalDateTime.now(); // 12:10:30 LocalTime localTime = localDateTime.toLocalTime(); // 2012-12-25 LocalDate localDate = localDateTime.toLocalDate();
java.time.OffsetTime
、java.time.OffsetDateTime
、java.time.ZonedDateTime
もそれぞれ容易に変換が可能である。java.time.OffsetTime
から、java.time.OffsetDateTime
への変換。
// Ex, 12:30:11.567+09:00 OffsetTime offsetTime = OffsetTime.now(); // 2015-12-25T12:30:11.567+09:00 OffsetDateTime offsetDateTime = offsetTime.atDate(LocalDate.of(2015, 12, 25));
java.time.OffsetDateTime
からjava.time.ZonedDateTime
への変換。
// Ex, 2015-12-25T12:30:11.567+09:00 OffsetDateTime offsetDateTime = OffsetDateTime.now(); // 2015-12-25T12:30:11.567+09:00[Asia/Tokyo] ZonedDateTime zonedDateTime = offsetDateTime.atZoneSameInstant(ZoneId.of("Asia/Tokyo"));
java.time.ZonedDateTime
からjava.time.OffsetDateTime
,java.time.OffsetTime
への変換。
// Ex, 2015-12-25T12:30:11.567+09:00[Asia/Tokyo] ZonedDateTime zonedDateTime = ZonedDateTime.now(); // 2015-12-25T12:30:11.567+09:00 OffsetDateTime offsetDateTime = zonedDateTime.toOffsetDateTime(); // 12:30:11.567+09:00 OffsetTime offsetTime = zonedDateTime.toOffsetDateTime().toOffsetTime();
java.time.LocalTime
をjava.time.OffsetTime
に変換することも可能である。// Ex, 12:30:11.567
LocalTime localTime = LocalTime.now();
// 12:30:11.567+09:00
OffsetTime offsetTime = localTime.atOffset(ZoneOffset.ofHours(9));
LocalTime
からLocalDateTime
の変換であれば日付の情報が不足している の要領)を加えることで別のクラスへ変換が可能である。7.3.2.3.2. java.util.Dateとの相互運用性¶
java.time.LocalDate
等のクラスは、java.time.Instant
に変換したうえでjava.util.Date
に変換することが可能である。java.time.LocalDateTime
から、java.util.Date
への変換。
LocalDateTime localDateTime = LocalDateTime.now(); Instant instant = localDateTime.toInstant(ZoneOffset.ofHours(9)); Date date = Date.from(instant);Note
java.time.LocalTime
、java.time.LocalDate
はInstantを持っていないため、一度java.time.LocalDateTime
に変換する必要がある。変換方法はDate and Time APIの各クラスの相互運用性を参照されたい。
java.util.Date
からjava.time.LocalDateTime
への変換。
Date date = new Date(); Instant instant = date.toInstant(); LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
7.3.2.3.3. java.sql パッケージとの相互運用性¶
java.sql
パッケージのクラスは、java.time.Instant
に変換せずにjava.time.LocalDate
等のクラスと相互変換が可能である。java.sql.Date
からjava.time.LocalDate
への変換。
java.sql.Date date = new java.sql.Date(System.currentTimeMillis()); LocalDate localDate = date.toLocalDate();
java.time.LocalDate
からjava.sql.Date
への変換。
LocalDate localDate = LocalDate.now(); java.sql.Date date = java.sql.Date.valueOf(localDate);
java.sql.Time
からjava.time.LocalTime
への変換。
java.sql.Time time = new java.sql.Time(System.currentTimeMillis()); LocalTime localTime = time.toLocalTime();
java.time.LocalTime
からjava.sql.Time
への変換。
LocalTime localTime = LocalTime.now(); java.sql.Time time = java.sql.Time.valueOf(localTime);
java.sql.Timestamp
からjava.time.LocalDateTime
への変換。
java.sql.Timestamp timestamp = new java.sql.Timestamp(System.currentTimeMillis()); LocalDateTime localDateTime = timestamp.toLocalDateTime();
java.time.LocalDateTime
からjava.sql.Timestamp
への変換。
LocalDateTime localDateTime = LocalDateTime.now(); java.sql.Timestamp timestamp = java.sql.Timestamp.valueOf(localDateTime);
7.3.2.3.4. 文字列へのフォーマット¶
toString
メソッドを使用する方法と、java.time.fomat.DateTimeFormatter
を使用する方法がある。java.time.fomat.DateTimeFormatter
を使用し様々な日時文字列へ変換することが出来る。java.time.fomat.DateTimeFormatter
は、事前定義されたISOパターンのフォーマッタを利用する方法と、任意のパターンのフォーマットを定義して利用する方法がある。DateTimeFormatter formatter1 = DateTimeFormatter.BASIC_ISO_DATE;
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("G uuuu/MM/dd E")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);
Locale
とResolverStyle
(厳密性)を定義できる。Locale
のデフォルト値はシステムによって変化するため、初期化時に設定することが望ましい。ResolverStyle
(厳密性)はofPattern
メソッドを使う場合、デフォルトでResolverStyle.SMART
が設定されるが、本ガイドラインでは予期せぬ挙動が起こらないよう、厳密に日付を解釈するResolverStyle.STRICT
の設定を推奨している。(ISOパターンのフォーマッタを利用する場合はResolverStyle.STRICT
が設定されている)yyyy
は暦に対する年を表すため、暦によって解釈が異なる(西暦なら2015と解釈されるが、和暦なら0027と解釈される)。yyyy
形式に変えてuuuu
形式を利用することを推奨する。DateTimeFormatter formatter1 = DateTimeFormatter.BASIC_ISO_DATE;
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("G uuuu/MM/dd E")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);
LocalDate localDate1 = LocalDate.of(2015, 12, 25);
// "2015-12-25"
System.out.println(localDate1.toString());
// "20151225"
System.out.println(formatter1.format(localDate1));
// "西暦 2015/12/25 金"
System.out.println(formatter2.format(localDate1));
7.3.2.3.5. 文字列からのパース¶
java.time.fomat.DateTimeFormatter
を用いることで、様々な日付文字列をDate and Time APIのクラスへ変換することが出来る。DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("uuuu/MM/dd")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("HH:mm:ss")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);
LocalDate localDate = LocalDate.parse("2015/12/25", formatter1);
LocalTime localTime = LocalTime.parse("14:09:20", formatter2);
7.3.2.4. 日付操作¶
7.3.2.4.1. 日時の計算¶
plus
メソッドとminus
メソッドが提供されている。- 時間の計算を行う場合の例。
LocalTime localTime = LocalTime.of(20, 30, 50); LocalTime plusHoursTime = localTime.plusHours(2); LocalTime plusMinutesTime = localTime.plusMinutes(10); LocalTime minusSecondsTime = localTime.minusSeconds(15);
- 日付の計算を行う場合の例。
LocalDate localDate = LocalDate.of(2015, 12, 25); LocalDate plusYearsDate = localDate.plusYears(10); LocalDate minusMonthsTime = localDate.minusMonths(1); LocalDate plusDaysTime = localDate.plusDays(3);
7.3.2.4.2. 日時の比較¶
- 時間の比較を行う場合の例。
LocalTime morning = LocalTime.of(7, 30, 00); LocalTime daytime = LocalTime.of(12, 00, 00); LocalTime evening = LocalTime.of(17, 30, 00); daytime.isBefore(morning); // false morning.isAfter(evening); // true evening.equals(LocalTime.of(17, 30, 00)); // true daytime.isBefore(daytime); // false morning.isAfter(morning); // false
- 日付の比較を行う場合の例。
LocalDate may = LocalDate.of(2015, 6, 1); LocalDate june = LocalDate.of(2015, 7, 1); LocalDate july = LocalDate.of(2015, 8, 1); may.isBefore(june); // true june.isAfter(july); // false july.equals(may); // false may.isBefore(may); // false june.isAfter(june); // false
7.3.2.4.3. 日時の判定¶
- 妥当な日時文字列かを判定したい場合、
java.time.format.DateTimeParseException
の発生有無で判定できる。
String strDateTime = "aabbcc"; DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HHmmss") .withLocale(Locale.JAPANESE) .withResolverStyle(ResolverStyle.STRICT);; DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuMMdd") .withLocale(Locale.JAPANESE) .withResolverStyle(ResolverStyle.STRICT);; try { // DateTimeParseException LocalTime localTime = LocalTime.parse(strDateTime, timeFormatter); } catch (DateTimeParseException e) { System.out.println("Invalid time string !!"); } try { // DateTimeParseException LocalDate localDate = LocalDate.parse(strDateTime, dateFormatter); } catch (DateTimeParseException e) { System.out.println("Invalid date string !!"); }
- うるう年かを判定したい場合、
java.time.LocalDate
のisLeapYear
メソッドで判定できる。
LocalDate date1 = LocalDate.of(2012, 1, 1); LocalDate date2 = LocalDate.of(2015, 1, 1); date1.isLeapYear(); // true date2.isLeapYear(); // false
7.3.2.4.4. 年月日等の個別取得¶
get
メソッドを利用する。LocalDate localDate = LocalDate.of(2015, 2, 3);
LocalTime localTime = LocalTime.of(2, 30, 22, 123456789);
int year = localDate.getYear(); // (1)
int month = localDate.getMonthValue(); // (2)
int dayOfMonth = localDate.getDayOfMonth(); // (3)
int dayOfYear = localDate.getDayOfYear(); // (4)
DayOfWeek week = localDate.getDayOfWeek(); // (5)
int weekValue = week.getValue(); // (5)
int hour = localTime.getHour(); // (6)
int minute = localTime.getMinute(); // (7)
int second = localTime.getSecond(); // (8)
int nano = localTime.getNano(); // (9)
項番 | 説明 |
---|---|
(1)
|
年を取得する。本例では、
2015 が返却される。 |
(2)
|
月を取得する。本例では、
2 が返却される。Note
|
(3)
|
月初からの日数を取得する。本例では、
3 が返却される。 |
(4)
|
元日からの日数を取得する。本例では、
34 が返却される。 |
(5)
|
曜日を取得する。本例では、
TUESDAY (getValue では2 )が返却される。返却される値と曜日の対応は、[1:MONDAY、2:TUESDAY、3:WEDNESDAY、4:THURSDAY、5:FRIDAY、6:SATURDAY、7:SUNDAY]となる。
|
(6)
|
時を取得する。本例では、
2 が返却される。 |
(7)
|
分を取得する。本例では、
30 が返却される。 |
(8)
|
秒を取得する。本例では、
22 が返却される。 |
(9)
|
ナノ秒を取得する。本例では、
123456789 が返却される。 |
7.3.2.5. 和暦(JapaneseDate)¶
java.time.chrono.JapaneseDate
という、和暦を扱うクラスが提供されている。7.3.2.5.1. 和暦の取得¶
java.time.LocalDate
と同様に、now
メソッド、of
メソッドで取得できる。java.time.chrono.JapaneseEra
クラスを使うことで、和暦を指定した取得も行うことが出来る。JapaneseDate japaneseDate1 = JapaneseDate.now();
JapaneseDate japaneseDate2 = JapaneseDate.of(2015, 12, 25);
JapaneseDate japaneseDate3 = JapaneseDate.of(JapaneseEra.HEISEI, 27, 12, 25);
Note
java.time.chrono.JapaneseDate
は、グレゴリオ暦が導入された明治6年(西暦1873年)より前は利用できない。
// DateTimeException JapaneseDate japaneseDate = JapaneseDate.of(1500, 1, 1);
実行結果
java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported
7.3.2.5.2. 文字列へのフォーマット¶
java.time.fomat.DateTimeFormatter
を用いることで、和暦日付へ変換することが出来る。利用の際には、DateTimeFormatter#withChronology
メソッドで暦をjava.time.chrono.JapaneseChronology
に設定する。DateTimeFormatter formatter = DateTimeFormatter.ofPattern("Gppy年ppM月ppd日")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(JapaneseChronology.INSTANCE);
JapaneseDate japaneseDate = JapaneseDate.of(1992, 1, 1);
// "平成 4年 1月 1日"
System.out.println(formatter.format(japaneseDate));
7.3.2.5.3. 文字列からのパース¶
java.time.fomat.DateTimeFormatter
を用いることで、和暦文字列からjava.time.chrono.JapaneseDate
へ変換することが出来る。DateTimeFormatter formatter = DateTimeFormatter.ofPattern("Gy年MM月dd日")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(JapaneseChronology.INSTANCE);
JapaneseDate japaneseDate1 = JapaneseDate.from(formatter.parse("平成27年12月25日"));
JapaneseDate japaneseDate2 = JapaneseDate.from(formatter.parse("明治6年01月01日"));
7.3.2.5.4. 西暦・和暦の変換¶
java.time.LocalDate
からの変換を容易に行える。LocalDate localDate = LocalDate.of(2015, 12, 25);
JapaneseDate jpDate = JapaneseDate.from(localDate);
7.3.2.6. JSP Tag Library¶
7.3.2.6.1. 設定方法¶
タブライブラリを利用するには、以下のtaglib定義が必要である。
<%@ taglib uri="http://sargue.net/jsptags/time" prefix="javatime" %>
7.3.2.6.2. javatime:formateタグ¶
javatime:formatタグとは、LocalDate、LocalTime、LocalDateTimeオブジェクトをフォーマットするタグである。
<% pageContext.setAttribute("now", java.time.LocalDateTime.now()); %>
<span>Using pattern="uuuuMMdd" to format the current system date</span><br/>
<javatime:format value="${now}" pattern="yyyyMMdd" />
<br/>
<span>Using style="SM" to format the current system date</span><br/>
<javatime:format value="${now}" style="SM" />
出力結果
- jpロケールの場合
- enロケールの場合
javatime:formatタグの属性一覧は、以下の通りである。
No. | Attributes | Description |
---|---|---|
value
|
Temporalインスタンスを設定する。
|
|
var
|
時刻情報を持つ変数名
|
|
scope
|
時刻情報を持つ変数名のスコープ
|
|
locale
|
ロケール情報
|
|
style
|
フォーマットするためのスタイル情報(2桁。日付部分と時刻部分それぞれのスタイルを設定する。
入力可能な値は S=Short, M=Medium, L=Long, F=Full, -=None)
Note style属性を指定して日付と時刻部分を表示する場合、ブラウザのlocaleによって表示内容が異なる。 |
|
pattern
|
フォーマットするためのパターン(uuuuMMddなど)。
入力可能なパターンは、DateTimeFormatterのjavadocを参照されたい。
|
|
dateTimeZone
|
タイムゾーン
|
ほかのタグについては、Java 8 java.time JSP tagsを参照されたい。