Slide 1

Slide 1 text

java.time を Android で使う 関西モバイルアプリ研究会 A #3 @takuji31

Slide 2

Slide 2 text

自己紹介 西林 拓志(にしばやし たくじ) Twitter/GitHub takuji31 Sansan 株式会社 技術本部 Mobile Application グループ Eight Android エンジニア Android (2009〜) Kotlin (2014〜) 1

Slide 3

Slide 3 text

java.time 使ってますか? 2

Slide 4

Slide 4 text

Java で日付関連クラスといえば 3

Slide 5

Slide 5 text

java.util.Date 4

Slide 6

Slide 6 text

java.util.Calendar 5

Slide 7

Slide 7 text

java.util.Date / java.util.Calendar java.util.Date は 1970/01/01 00:00:00.000 からの秒数を表したクラス タイムゾーンや歴(カレンダー)の情報はない java.util.Calendar は現在の日時を表したクラス タイムゾーンや暦の情報が含まれる よく使われる具象クラスは GregorianCalendar 古い API でよく使われる たとえば Realm の日付型は java.util.Date 6

Slide 8

Slide 8 text

Date と Calendar の問題点 7

Slide 9

Slide 9 text

問題点 やれることが少ない、制限が多い 範囲を表すクラスがない 差分計算 年は 1900〜 月は zero indexed Mutable である final や val でも setter で値が書き換わってしまう etc. 8

Slide 10

Slide 10 text

2024 年に積極的に使う API ではない 9

Slide 11

Slide 11 text

代替ライブラリー使う? 10

Slide 12

Slide 12 text

Joda-Time 11

Slide 13

Slide 13 text

ThreeTen Backport 12

Slide 14

Slide 14 text

ThreeTen Android Backport 13

Slide 15

Slide 15 text

一昔前なら ThreeTen Android Backport 使いましょうだった 14

Slide 16

Slide 16 text

ThreeTen -> 310 -> JSR310 -> java.time 15

Slide 17

Slide 17 text

今なら java.time 使ったらよい 16

Slide 18

Slide 18 text

でも java.time って Java 8 からなんでしょ? 17

Slide 19

Slide 19 text

今なら java.time 使えます 18

Slide 20

Slide 20 text

D8 19

Slide 21

Slide 21 text

D8 の API desugaring で Java8 以上の一部 API が使える 20

Slide 22

Slide 22 text

see. https://developer.android.com/studio/write/java8- support-table 21

Slide 23

Slide 23 text

how to enable D8 API desugaring 22

Slide 24

Slide 24 text

Android Gradle Plugin 4.0.0+ 23

Slide 25

Slide 25 text

build.gradle.kts android { defaultConfig { multiDexEnabled = true } compileOptions { isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_1_8 // 11 でもOK targetCompatibility = JavaVersion.VERSION_1_8 } } dependencies { coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3") } 24

Slide 26

Slide 26 text

java.time の使い方 25

Slide 27

Slide 27 text

java.time のクラスたち Instant LocalDateTime LocalDate LocalTime OffsetDateTime ZonedDateTime Duration Period 26

Slide 28

Slide 28 text

今回はよく使う 3 つだけ紹介 27

Slide 29

Slide 29 text

Instant 28

Slide 30

Slide 30 text

Date っぽいやつ 29

Slide 31

Slide 31 text

使い方 val now = Instant.now() now.epochSecond // 1970/01/01 00:00:00 からの経過秒数 now.toEpochMilli() // 1970/01/01 00:00:00 からの経過ミリ秒数 now.nano // ナノ秒 val secondLater = now + Duration.ofSeconds(1) // 1 秒後 val sameTimeOfYesterday = now - Duration.ofDays(-1) // 昨日の同じ時間 30

Slide 32

Slide 32 text

LocalDateTime 31

Slide 33

Slide 33 text

タイムゾーンを含まない DateTime 32

Slide 34

Slide 34 text

LocalDate + LocalTime 33

Slide 35

Slide 35 text

使い方 val now = LocalDateTime.now() now.year // 2024 now.month // 4 now.dayOfMonth // 25 val eventStartAt = LocalDateTime.of(2024, 4, 25, 18, 30, 0) // 2024/04/25 18:30:00 val eventEndAt = eventStartAt + Duration.ofMinutes(90) // 2024/04/25 20:00:00 val roomOpenAt = eventStartAt - Duration.ofMinutes(30) // 2024/04/25 18:00:00 34

Slide 36

Slide 36 text

ZonedDateTime 35

Slide 37

Slide 37 text

タイムゾーンの情報を含む DateTime 36

Slide 38

Slide 38 text

使い方 val now = ZonedDateTime.now() now.year // 2024 now.month // 4 now.dayOfMonth // 25 // convert other classes val nowInstant = now.toInstant() val nowLocalDateTime = now.toLocalDateTime() val currentZone = ZoneId.systemDefault() // Asia/Tokyo val JST = ZoneId.of("Asia/Tokyo") val UTC = ZoneId.of("UTC") val eventStartAtUTC = ZonedDateTime.now(UTC) // 2024/04/25 9:30:00 val eventEndAt = eventStartAtUTC + Duration.ofMinutes(90) // 2024/04/25 11:00:00 val roomOpenAt = eventStartAtUTC - Duration.ofMinutes(30) // 2024/04/25 9:00:00 37

Slide 39

Slide 39 text

Let's java.time 38