Android(Kotlin)で ZonedDateTime を使う

September 18, 2020

はじめに

日時処理をまあまあ記述しなければいけない場合、java.util.Calendar しか使えないのは(使いづらくて)辛いなーと思います。java.time.ZonedDateTime で代替できそうなので試してみます。

実装内容

概要

  • デフォルトでは使えない java.time.ZonedDateTime を使えるようにする
  • 現時刻を java.util.Calendarjava.time.ZonedDateTime で取得
  • それぞれ同形式で表示
  • それぞれの UNIX 時間をミリ秒で表示

詳細

app/build.gradle

こちらに従い、 アプリの最小 API レベルを気にせずに java.time を使えるようにします。

@@ -22,6 +22,12 @@ android {
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
+
+    compileOptions {
+        coreLibraryDesugaringEnabled true
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
 }

 dependencies {
@@ -32,5 +38,6 @@ dependencies {
     testImplementation 'junit:junit:4.12'
     androidTestImplementation 'androidx.test.ext:junit:1.1.1'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'

 }

app/src/main/java/com/example/myapplication/MainActivity.kt

ZonedDateTimeCalendar、それぞれで簡単な動作確認してみました。

ZonedDateTime のクラス名からわかる通り、内部的にタイムゾーンを保有しており、 Calendar 同様、簡単に UNIX 時間を取得できます。

ちなみに CalendartimeInMillis メソッドは結構使うので、ZonedDateTime にも拡張メソッドとして timeInMillis を用意して試してみました。

package com.example.myapplication

import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import java.text.SimpleDateFormat
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.*

class MainActivity : AppCompatActivity(R.layout.activity_main) {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val zonedDateTime = ZonedDateTime.now()
        val calendar = Calendar.getInstance()

        val pattern = "yyyy/MM/dd HH:mm:ss.SSS"
        val locale = Locale.JAPAN
        val dateTimeFormatter = DateTimeFormatter.ofPattern(pattern, locale)
        val simpleDateFormat = SimpleDateFormat(pattern, locale)

        findViewById<TextView>(R.id.textViewZonedDateTimeFormat).apply {
            text = dateTimeFormatter.format(zonedDateTime)
        }
        findViewById<TextView>(R.id.textViewZonedDateTimeTimeInMillis).apply {
            text = zonedDateTime.timeInMillis.toString()
        }
        findViewById<TextView>(R.id.textViewCalendarFormat).apply {
            text = simpleDateFormat.format(calendar.time)
        }
        findViewById<TextView>(R.id.textViewCalendarTimeInMillis).apply {
            text = calendar.timeInMillis.toString()
        }
    }
}

val ZonedDateTime.timeInMillis: Long
    get() = toInstant().toEpochMilli()

app/src/main/res/layout/activity_main.xml

特筆すべき点はありません。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textViewZonedDateTimeFormat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textViewZonedDateTimeTimeInMillis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textViewCalendarFormat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textViewCalendarTimeInMillis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

おわりに

開発では、本記事で触れていないメソッドも使ったりしていますが、

java.util.Calendar は使わずに、java.time.ZonedDateTime 使う」

で良さそうですね。


Product

「いつやるかは決めてないけれど、必ずやらなければいけないタスク」を忘れないためのアプリ