Java8入門:日付関係知識とDate and Time API

Java Logo

Java7とJava8を勉強で、日付関係APIを学んだ。APIも重要だが、ISO 8601という日時表現の国際標準規格や、世界共通時(UTC)の内容も学んだ。

日付関係知識

UTCとGMTの違いは?、UNIX時間とは?など、日付関係は知識を整理しておく。

ISO 8601とは

ISO 8601は日付と時刻の表記に関する国際規格である。世界共通時(UTC)とグレゴリオ暦を基準として利用する。JavaのDate and Time APIは、ISO8601をベースとしている。

今、このブログを書いている時間を表現すると、以下のような表記となる。
2017-10-01T14:09:42+09:00

UTC時で表示すると、以下のようになる。
2017-10-01T05:09:42Z

ISO 8601 - Wikipedia

ISO 8601は日付と時刻の表記に関する国際規格。最新版は2004年に発行されたISO 8601:2004 で、古い版としてISO 8601:2000 、ISO 8601:1988 があった。

世界共通時(UTC)とは

今の標準時はUTCだと覚えておく。GMT グリニッジ標準時は、過去に使われていた標準時。

UTC協定世界時とGMTグリニッジ標準時の違い | LOCALTIME.JP

世界共通の標準時であり、セシウム原子時計によって刻まれる国際原子時をもとにして常に正確に保持されている。

グレゴリオ暦とは

グレゴリオ暦は日本でも使われている。暦とは、年や月などの区切りを決めるためのルールだと理解した。太陽暦は、地球が太陽の周りを1周する期間を1年としている。

グレゴリオ暦 - Wikipedia

現行太陽暦として世界各国で用いられている。(一部省略)紀年法はキリスト紀元(西暦)を用いる。

太陽暦 - Wikipedia

太陽暦(たいようれき、英: solar calendar)とは、地球が太陽の周りを回る周期(太陽年)を基にして作られた暦(暦法)である。1年の日数を1太陽年に近似させている。ユリウス暦や、現在、世界の多くの地域で使用されているグレゴリオ暦は、太陽暦の1種である。

太陰暦 - Wikipedia

太陰暦(たいいんれき、英: lunar calendar、亜: تقويم قمري‎)は、月の満ち欠けの周期を基にした暦(暦法)である。

西暦とは

西暦とは何か?という疑問が出てきた。西暦 2017年というので、日本では西暦を使っているのではないか?と思った。Wikipedia先生に教えてもらう。

西暦 - Wikipedia

イエス・キリストが生まれたとされる年の翌年を元年(紀元)とした紀年法である。

紀年法 - Wikipedia

紀年法(きねんぽう)とは、年を数えたり、記録する方法をいう

西暦は年の数え方を示しているだけで、1年を定義するものではないということが分かった。

1年の長さはグレゴリオ暦で定義しており、西暦はイエス・キリストが生まれた年から数えるという決まりを表している。”暦”という単語がややこしい。

UNIX時間とは

コンピュータ関係の人なら知っているが、1970年1月1日0時0分0秒からの経過時間である。今までのJavaのDateクラスやCalendarクラスは、UNIX時間をベースとして作られていた。

UNIX時間 - Wikipedia

コンピューターシステム上での時刻表現の一種。UNIXエポック、すなわち協定世界時 (UTC) での1970年1月1日真夜中(午前0時0分0秒)の時刻からの形式的な経過秒数(すなわち、実質的な経過秒数から、その間に挿入された閏秒を引き、削除された閏秒を加えたもの)として表される。

日付関係API

ようやく基礎知識が身についた。Date and Time APIを触っていく。

利用するクラス

以下のクラスが中心的なクラスとなる。

クラス名 説明
LocalDateTime 日付と時間を保持する
OffsetDateTime 時差を考慮して日付と時間を保持する
ZonedDateTime タイムゾーンを考慮して日付と時間を保持する
Duration 時間間隔を表す
Period 年月日で時間間隔を表す

LocalDateTimeを中心に使いつつ、UTC時間や時差を考慮するようなシステムならばOffsetDateTimeを使う。夏時間の切り替えや地域間の時間差を扱う場合は、ZonedDateTimeを使う。

DateクラスやCalendarクラスに比べて、分かりやすくなったと思う。特にイミュータブルになった点が一番気に入った。

DateクラスやCalendarクラスを使っているシステムは、LocalDateTimeなどを混ぜずに今まで通りの方が良さそう。1から作るシステムは、新しいAPIを使っていくのが分かりやすいと思う。

サンプルコード

Sample/Main.java at master · eiKatou/Sample

インスタンスを生成する

LocalDateTime.now();
LocalDateTime.of(2017, Month.OCTOBER, 3, 15, 50);
LocalDateTime.parse("2017-08-13T12:12:35");

年や月や時刻などを設定する

localDateTime.withYear(1999);
localDateTime.withMonth(3);

時刻を進めたり戻したりする

localDateTime.plusYears(2);
localDateTime.plusDays(3);
localDateTime.minusDays(1);

日時をフォーマットして出力する
アルファベット以外はシングルクォートで囲むこと。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy'年'MM'月'dd'日 'HH'時'mm'分'ss'秒'");
localDateTime.format(formatter)

日時間隔を扱う

LocalDateTime.now().minus(Duration.ofHours(30))
// 1年2ヶ月3日の間隔
Period period1 = Period.of(1, 2, 3);
LocalDateTime.now().plus(period1)

時差付きの日時を生成する

OffsetDateTime.of(2017, 9, 5, 16, 24, 45, 500_000_000, ZoneOffset.of("+09:00"))

参考書籍

Java7/8を勉強するのにおすすめの本。
今回も参考にさせていただいた。

現場で使える[最新]Java SE 7/8 速攻入門
櫻庭 祐一
技術評論社
売り上げランキング: 467,147