趣味で西暦・和暦変換処理を作っていて不思議な現象にあいました。
LocalDate を Date に変換する必要があったので、ネットで調べたらいくつかのサイトがヒットしました。
String、Date、LocalDateの変換 - Qiita
java.util.Date型にjava.time.LocalDateを変換する java-8 java-time | CODE Q&A [日本語]
簡単なサンプルを試しました。
public static void main(String[] args) throws Exception { LocalDate ld = LocalDate.of(2018, 3, 24); Date date = Date.from(ld.atStartOfDay(ZoneId.systemDefault()).toInstant()); System.out.println(date); }
実行結果。
Sat Mar 24 00:00:00 JST 2018
なんの問題もないですね。解決・・・
と思っていたのですが、大昔の変換も行う必要があるので、ひとまず 1850 年で試しました。
public static void main(String[] args) throws Exception { LocalDate ld = LocalDate.of(1850, 1, 1); Date date = Date.from(ld.atStartOfDay(ZoneId.systemDefault()).toInstant()); System.out.println(date); }
実行結果。
Mon Dec 31 23:41:01 JST 1849
ずれとるやないかい!!!!!!!!!
いろいろな日付で試してみるとどうやら 1888 年 1 月 1 日以前だと 18 分 59 秒ずれるみたいです。1888 年 1 月 2 日だとずれません。
ググってみたけれど同じ現象で困っている人は見つけられませんでした。
とりあえず、いったん文字列に変換することで、怪現象を回避した処理は作れたので、原因は継続調査ということにしておきたいと思います。
Java はちょっと古めの 1.8 です。詳細は下記参照。
C:\Users\yyama>java -version java version "1.8.0_161" Java(TM) SE Runtime Environment (build 1.8.0_161-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
もう気になって夜しか眠れません。
解決したら追記します。
以下、2018 年 5 月 19 日追記
解決しました!!!
コメント欄に fog_og_frog2 様より情報をいただきました。
tz databaseの1888年以前の時差は2秒ずれてる? - きしだのはてな
引用:
Transition[Overlap at 1888-01-01T00:18:59+09:18:59 to +09:00] Transition[Gap at 1948-05-02T02:00+09:00 to +10:00] Transition[Overlap at 1948-09-11T02:00+10:00 to +09:00] Transition[Gap at 1949-04-03T02:00+09:00 to +10:00] Transition[Overlap at 1949-09-10T02:00+10:00 to +09:00] Transition[Gap at 1950-05-07T02:00+09:00 to +10:00] Transition[Overlap at 1950-09-09T02:00+10:00 to +09:00] Transition[Gap at 1951-05-06T02:00+09:00 to +10:00] Transition[Overlap at 1951-09-08T02:00+10:00 to +09:00]
一番上の行にあるとおり、1888 年 1 月 1日に UTC +09:18:59 から UTC +09:00:00 に変更された記載が読み取れます。
1887 年 12 月 31 日 23 時 59 分 59 秒の次は 1888 年 1 月 1 日 0 時 18 分 59 秒 になるということですね。
したがって 1888 年 1 月 1 日 0 時 0 分 0 秒 から、0 時 18 分 58 秒までは 1887 年 12 月 31 日と解釈されてしまいます。
public static void main(String[] args) { // 1888 年 1 月 1 日 0 時 0 分 0 秒 ずれる LocalDateTime ld = LocalDateTime.of(1888, 1, 1, 0, 0, 0); Date date = Date.from(ld.toInstant(ZoneId.systemDefault().getRules().getOffset(ld))); System.out.println(date); // 1888 年 1 月 1 日 0 時 18 分 58 秒 ずれる LocalDateTime ld2 = LocalDateTime.of(1888, 1, 1, 0, 18, 58); Date date2 = Date.from(ld2.toInstant(ZoneId.systemDefault().getRules().getOffset(ld2))); System.out.println(date2); // 1888 年 1 月 1 日 0 時 18 分 59 秒 ずれない LocalDateTime ld3 = LocalDateTime.of(1888, 1, 1, 0, 18, 59); Date date3 = Date.from(ld3.toInstant(ZoneId.systemDefault().getRules().getOffset(ld3))); System.out.println(date3); }
結果
Sat Dec 31 23:41:01 JST 1887 Sat Dec 31 23:59:59 JST 1887 Sun Jan 01 00:18:59 JST 1888
怪現象の原因が判明してすっきりしました。
情報をくださった fog_og_frog2 様 本当にありがとうございました。

- 作者: 中山清喬,国本大悟
- 出版社/メーカー: インプレス
- 発売日: 2014/08/07
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (19件) を見る

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)
- 作者: Dustin Boswell,Trevor Foucher,須藤功平,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2012/06/23
- メディア: 単行本(ソフトカバー)
- 購入: 68人 クリック: 1,802回
- この商品を含むブログ (138件) を見る

- 作者: 結城浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2004/06/19
- メディア: 大型本
- 購入: 51人 クリック: 762回
- この商品を含むブログ (397件) を見る