ThreeTenABP: それは何か、Android向けjava.timeライブラリ

著者: IT Sectr 公開日: 2026-07-14 読了時間: 11 分

ThreeTenABP は、Android 8(API < 26)未満のデバイスにjava.time API(org.threeten.bpパッケージ)を提供するAndroid用アダプターライブラリです。Jake Wharton(GitHub、2023)の仕様によると、このライブラリはThreeTen-Backportプロジェクトのラッパーであり、リソース最適化とAssetManagerを通じたtzdataサポートを備えてAndroid向けに適応されています。

重要なポイント

  • ThreeTenABP はThreeTen-Backport用のAndroidアダプターであり、API < 26でjava.timeを提供します。
  • Gradle経由で追加:implementation "com.jakewharton.threetenabp:threetenabp:1.4.x"。
  • Application.onCreate()でのAndroidThreeTen.init(this)による初期化が必要です。
  • java.timeの代わりにorg.threeten.bpパッケージを使用 — APIはほぼ同一です。
  • desugaring(AGP 4.0+)の登場により、ThreeTenABPはオプションとなり、レガシープロジェクトで使用されています。

ThreeTenABPとは?

ThreeTenABP(ThreeTen Android Backport)は、Jake Whartonによって作成されたライブラリで、古いAndroidバージョンでJava 8の日時APIを使用するためのものです。これはThreeTen-Backportプロジェクトのアダプターであり、java.time(JSR-310)をJava 7およびAndroid API < 26に移植します。

このライブラリが解決する主な問題:Androidバージョン8(API 26)以前は、java.timeが標準配布に含まれていませんでした。開発者はjava.util.Date/Calendarを使用するか、Joda-Timeを追加する必要がありました。ThreeTenABPは、組み込みのjava.timeと同じ最新のAPIを提供しますが、org.threeten.bpパッケージを介して提供します。

GitHubリポジトリ(2023)によると、このライブラリはAndroid向けに最適化されています:tzdata(IANA Time Zone Database)はassetsに保存され、デスクトップのようにclasspathではなくAssetManagerを介してロードされます。これによりAPKサイズが削減され、ロードが高速化されます。

最新の安定版は1.4.0(2021年8月)です。このライブラリはメンテナンスモードにあり、desugaringの広範な採用に伴い必要性は減少していますが、最小API < 26のプロジェクトでは依然として重要です。

なぜjava.timeのバックポートが必要か?

Java 8(2014年)でjava.timeが導入される前、開発者はjava.util.Datejava.util.Calendarを使用していました。これらのクラスには深刻な欠点があります:Dateは可変、Calendarは直感的でない定数を使用(Calendar.JANUARY = 0)、両方のクラスはスレッドセーフではなく、タイムゾーンを扱う際にエラーが発生しやすいです。

Joda-TimeはJava 8以前のデファクトスタンダードでしたが、その作成者Stephen Colebourneは、Joda-Timeの経験とその欠点に対処した上で、java.timeを公式の代替として設計しました。java.timeパッケージはJDK 8に含まれていましたが、AndroidはAPI 26までそれを受け取りませんでした。

ThreeTen-Backportは、同じ著者(Stephen Colebourne)によって作成されたjava.timeのJava 7への移植です。主要なクラスをすべて含みます:LocalDate、LocalTime、LocalDateTime、ZonedDateTime、Instant、Duration、Period、DateTimeFormatter。ThreeTenABPはこの移植をAndroid向けに適応し、AssetsManagerを介した初期化とモバイルデバイス向けの最適化を追加します。

したがって、ThreeTenABPを使用すると、OSのアップデートを待つことなく、Android 4.0+(API 14+)のデバイスで最新の日時APIを使用できます。

AndroidプロジェクトへのThreeTenABPの追加

追加は2つのステップで行います:build.gradle(アプリレベル)に依存関係を追加し、Applicationクラスで初期化します。重要:ThreeTenABPには少なくとも21のcompileSdkと少なくとも4.0のGradleバージョンが必要です。

依存関係はdependenciesセクションに追加されます:implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"。1.4.0のリリース以降、ライブラリは更新されていません。安定しており、必要なすべてのケースをカバーしているためです。

公式ドキュメントによると、ライブラリにはassetsにtzdataが含まれています。アプリにすでに他のファイルを含むassetsフォルダがある場合、ThreeTenABPはそれらと正しく共存します。tzdataのサイズは圧縮状態で約200KBです。

groovy
// build.gradle(アプリレベル)
android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
}

ThreeTenABPの初期化

org.threeten.bpのクラスを使用する前に、ライブラリを初期化する必要があります。初期化はApplication.onCreate()でAndroidThreeTen.init(this)を呼び出して1回実行されます。

初期化はassetsからtzdataデータをロードし、システムクロックを設定します。init()を呼び出さないと、now()メソッドはライブラリが初期化されていないというメッセージとともにIllegalStateExceptionをスローします。

テスト用には、AndroidThreeTen.init(applicationContext, zoneId)を使用できます — 明示的なタイムゾーン指定を伴うオーバーロードです。これはテストで予測可能な動作に役立ちます。tzdataなしで基本的な初期化のみが必要な場合は、AndroidThreeTen.initWithoutFiles(context)を使用してください。

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}

// 初期化後の使用
val today = LocalDate.now()
val now = LocalDateTime.now()

どのクラスが利用可能か?

ThreeTenABPは、java.timeの主要なクラスをすべてorg.threeten.bpパッケージで提供します。APIは元のjava.timeとほぼ同一であり、API 26+への移行を容易にします。

主要なクラス:

  • LocalDate — 時間とタイムゾーンのない日付
  • LocalTime — 日付とタイムゾーンのない時間
  • LocalDateTime — タイムゾーンのない日付と時間
  • ZonedDateTime — タイムゾーン付きの日付と時間
  • OffsetDateTime — 固定オフセット付きの日付と時間
  • OffsetTime — 固定オフセット付きの時間
  • Instant — UTCの時点
  • Duration — 時間ベースの期間
  • Period — 日付ベースの期間
  • DateTimeFormatter — フォーマットと解析
  • ZoneId / ZoneOffset — タイムゾーン

ヘルパークラスもサポートされています:Clock、DayOfWeek、Month、Year、YearMonth、MonthDay。タイムゾーンはライブラリにバンドルされています(IANA tzdata)。ThreeTenABP 1.4.0のtzdataバージョンは2021aに対応しています。

ThreeTenABP vs desugaring

Android Gradle Plugin 4.0(2020年)とdesugar_jdk_libs以降、開発者はcoreLibraryDesugaringを介してすべてのAndroidバージョンでjava.timeを使用できるようになりました。Desugaringはバイトコードを変換し、追加のライブラリなしで古いAPIでjava.time呼び出しが機能するようにします。

Desugaringの利点:元のjava.timeパッケージを使用(org.threeten.bpではない)、初期化不要、Android Studioとの完全統合。欠点:AGP 4.0+が必要、ビルド時間が増加、APKサイズが2-3MB増加する可能性があります。

ThreeTenABPは、AGPを4.0+に更新できないレガシープロジェクト、またはAPKサイズが重要な場合に最適な選択肢であり続けています。ThreeTenABPはセットアップも簡単です — たった1つの依存関係と1行の初期化です。Stack Overflow(2024)によると、minSdk < 26のプロジェクトの約30%が今でもdesugaringの代わりにThreeTenABPを使用しています。

使用例

最初の例は、ThreeTenABPを使用した日付操作を示しています。APIはjava.timeと同じですが、インポートはorg.threeten.bpからになります。これにより、移行後にインポートの置き換えのみが必要なコードを書くことができます。

kotlin
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalTime
import org.threeten.bp.Duration

fun isWeekend(date: LocalDate): Boolean {
    val dayOfWeek = date.getDayOfWeek()
    return dayOfWeek == DayOfWeek.SATURDAY ||
           dayOfWeek == DayOfWeek.SUNDAY
}

fun timeBetween(
    start: LocalTime, end: LocalTime
): Duration {
    return Duration.between(start, end)
}

2番目の例は日付のフォーマットを示しています。org.threeten.bpのDateTimeFormatterはjava.timeと同じように動作します。

kotlin
import org.threeten.bp.LocalDateTime
import org.threeten.bp.format.DateTimeFormatter

fun formatTimestamp(dateTime: LocalDateTime): String {
    val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")
    return dateTime.format(formatter)
}

3番目の例は、ThreeTenABPでのZonedDateTimeの操作とタイムゾーン間の変換を示しています。

kotlin
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.ZoneId

fun convertTimeZone(
    time: ZonedDateTime,
    targetZone: ZoneId
): ZonedDateTime {
    return time.withZoneSameInstant(targetZone)
}

ThreeTenABPから組み込みjava.timeへの移行

minSdkを26に引き上げる際、ThreeTenABPを削除して組み込みのjava.timeに切り替えることができます。移行プロセスにはいくつかのステップが含まれ、徹底的なテストが必要です。

最初のステップはインポートの置き換えです。org.threeten.bpからのインポートをjava.timeに変更します。ほとんどの場合、クラス名は一致します:LocalDate → java.time.LocalDate、ZonedDateTime → java.time.ZonedDateTime。例外はDateTimeFormatterです — ThreeTenABPではorg.threeten.bp.formatにあり、java.timeではjava.time.formatにあります。

2番目のステップは初期化の削除です。AndroidThreeTen.init(this)の行はもはや必要ありません。java.timeはAndroid SDKに組み込まれているためです。Application.onCreate()から呼び出しを削除し、build.gradleから依存関係を削除してください。

3番目のステップは、minSdkが26未満のままの場合、依存関係をdesugaringに置き換えることです。compileOptionsでisCoreLibraryDesugaringEnabled = trueとdesugar_jdk_libs依存関係を追加します。これにより、ThreeTenABPなしで古いAPIでjava.timeが動作することが保証されます。Google I/O(2023)によると、desugaringは新しいプロジェクトの推奨アプローチです。

groovy
// build.gradle — ThreeTenABPをdesugaringに置き換え
android {
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
    }
}

dependencies {
    // 削除:implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
    // 追加:
    "coreLibraryDesugaring"("com.android.tools:desugar_jdk_libs:2.1.4")
}

// ApplicationからAndroidThreeTen.init(this)を削除

よくある質問

ThreeTenABPをdesugaringと一緒に使用できますか?

技術的には — はい、しかし意味がありません。desugaringが使用されている場合、組み込みのjava.timeはすでに利用可能です。両方のライブラリを使用すると、コードの重複とAPKサイズの増加につながります。プロジェクトに一つのアプローチを選択してください。

なぜThreeTenABPはApplicationでの初期化が必要ですか?

初期化は、IANA Time Zone Databaseをassetsからメモリにロードします。標準JDKでは、tzdataはclasspathを介して利用可能ですが、AndroidはAssetManagerを使用します。init()メソッドはデータをシステムディレクトリにコピーし、ZoneIdが利用できるようにします。

ThreeTenABPはどのAndroidバージョンをサポートしていますか?

ThreeTenABPはAPI 14+(Android 4.0 Ice Cream Sandwich以上)をサポートしています。Java 8互換性が必要です(compileOptionsのsourceCompatibilityとtargetCompatibility)。API 26+では、ライブラリは不要です — 組み込みのjava.timeを使用してください。

ThreeTenABPでタイムゾーンを更新するには?

タイムゾーンはライブラリにバンドルされています。バージョン1.4.0にはtzdata 2021aが含まれています。更新するには、ThreeTenABPのバージョンを更新するか、assets内のtzdataを手動で置き換える必要があります。最新のtzdataバージョンは、IANAリポジトリまたはThreeTen-Backportから入手できます。

ThreeTenABPでコードをテストするには?

単体テストには、明示的なゾーン指定でAndroidThreeTen.init(context, zoneId)を使用してください。Robolectricテストには — AndroidThreeTen.init(ApplicationProvider.getApplicationContext())。Androidなしの純粋なJVMテストには — ThreeTenABPなしで直接ThreeTen-Backportを使用してください。

まとめ

  • ThreeTenABP はThreeTen-BackportのAndroidアダプターであり、Android < 8(API < 26)のデバイスにjava.time APIを提供します。
  • Gradle依存関係com.jakewharton.threetenabp:threetenabp:1.4.0で追加され、Application.onCreate()でのAndroidThreeTen.init(this)の初期化が必要です。
  • java.timeの代わりにorg.threeten.bpパッケージを使用 — APIはほぼ同一で、API 26+への移行を簡素化します。
  • 主要なクラス:LocalDate、LocalTime、LocalDateTime、ZonedDateTime、Instant、Duration、Period、DateTimeFormatter — すべてThreeTenABPで利用可能です。
  • desugaring(AGP 4.0+)の登場により、ThreeTenABPはオプションになりましたが、レガシープロジェクトやAPKサイズに制約がある場合に重要です。
  • java.timeに移行する際は、インポートをorg.threeten.bp → java.timeに変更し、AndroidThreeTen.init()を削除し、依存関係をdesugar_jdk_libsに置き換えてください。
  • テストには、予測可能な動作のために明示的なゾーン指定でAndroidThreeTen.init(context, zoneId)を使用してください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください