🎉

AndroidにおけるJSR-310実装

2020/10/24に公開

※ブログに書いたものと同じ記事です。
https://iwsksky.hatenablog.com/entry/2020/10/24/030307

ちょっとツイッターに流れてきた情報を見て気になったので改めて調べてみました。

[https://twitter.com/red_fat_daruma/status/1268177028915716102:embed]

TL;DL

  • ThreeTenABPでJSR-310を利用する場合は環境によらず同じtz databaseを参照する(はず
  • desugaringでJSR-310を利用する場合は実行環境により異なるtz databaseを参照する(はず

java.util.Date と JSR-310

java.util.Dateが使い勝手が悪いことは良く知られており、Java SE 8ではjava.util.Dateを置き換えるDate and Time APIが追加された。このAPIはJSR-310として標準化されており、インターフェースがデベロッパーフレンドリーであるだけでなくインスタンスがイミュータブル、スレッドセーフといった機能的な優位性を持つ。[1]

AndroidでのJSR-310実装方法の変遷

前述の通りJSR-310はJava SE 8からの機能である。Android Gradle plugin4.0.0以降でJSR-310のdesugaring対応がされたが[2]、それまではThreeTenBPやThreeTenABP[3]のようなJava6,7向けにJSR-310をバックポートしたライブラリを利用する必要があった。またThreeTenBPはJSR-310と完全に同じ振る舞いをするわけではないという点にも注意が必要でタイムゾーン(tz database)は独自に実装されておりJREではなくThreeTenBP自体にパッケージされたtz databaseを参照するため、tz databaseの更新のためにはThreeTenBPの更新が必要であった。[4][5]

tz databaseについて

世界各地域の標準時(time zone、タイムゾーン)情報をまとめたデータ群のことである、以下のように標準時からの差をタイムゾーンとオフセットにより定義する。厄介なのが世界各国でこの定義の更新は割と頻繁に行われているようで、年に数回はtz databaseの更新が行われていることだ。[6]

# Zone  NAME            GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Asia/Tokyo      9:18:59 -       LMT     1887 Dec 31 15:00u
                        9:00    -       JST     1896
                        9:00    -       CJT     1938
                        9:00    Japan   J%sT

ZonedDateTime: 2020-08-01 00:00:00 (Asia/Tokyo)
OffsetDateTime: 2020-08-01T00:00:00+09:00

Androidにおけるtz database

Android Gradle plugin4.0.0以降でJSR-310のdesugaring対応がされたと述べたが、これまでThreeTenABPで利用していたJSR-310に見えるものとdesugaringで利用可能となるJSR-310はtz databaseの取り扱いなど細かい部分で実は挙動が異なる。ThreeTenABPが参照するtz databaseはパッケージングされたものであるのに対してdesugaringしたJSR-310が参照するのはJava実行環境のtz databaseとなる。Android10以降の端末でいうと/system/apex/com.google.android.tzdata.apex に含まれているtz databaseを参照する。

またAndroid10以降でAPEXベースのモジュール更新メカニズム[7]が採用されたようでtz databaseの更新方法が変わっているようだが、Android9以前のOEMがAPKベースのメカニズムでtz databaseを端末にプッシュしていた方法と比べて今回の件について本質的な差異はないように思う。

まとめ

JSR-310で実装するといってもThreeTenABPを使うかdesugaringを使うかで参照するtz databaseは異なる。今後はdesguaringでJSR-310を利用するほうに流れていくと思うが、その場合実行環境によって異なるバージョンのtz databaseを参照することは避けられないのではないだろうか。

参考

[1] [https://builder.japan.zdnet.com/sp_oracle/35067620/:title]

[2] [https://developer.android.com/studio/write/java8-support#library-desugaring:title]

[3] [https://github.com/JakeWharton/ThreeTenABP:title]

[4] [https://www.coppermine.jp/docs/notepad/2016/12/threeten-extra-and-threeten-backport.html:title]

[5] [https://www.threeten.org/threetenbp/apidocs/org/threeten/bp/zone/TzdbZoneRulesProvider.html:title]

[6] [https://www.oracle.com/java/technologies/tzdata-versions.html:title]

[7] [https://source.android.com/devices/architecture/modular-system/timezone?hl=ja:title]

Discussion