ThreeTenABP: что это, библиотека java.time для Android

Автор: IT Sectr Опубликовано: 2026-07-14 Время чтения: 11 мин

ThreeTenABP — библиотека-адаптер для Android, предоставляющая API java.time (пакет org.threeten.bp) на устройствах с Android ниже 8 (API < 26). По данным спецификации Jake Wharton (GitHub, 2023), библиотека является обёрткой над проектом ThreeTen-Backport, адаптированной для Android с учётом оптимизации ресурсов и поддержки tzdata через AssetManager.

Главное

  • ThreeTenABP — Android-адаптер для ThreeTen-Backport, предоставляющий java.time на API < 26.
  • Подключается через Gradle: implementation "com.jakewharton.threetenabp:threetenabp:1.4.x".
  • Требует инициализации в Application.onCreate() через AndroidThreeTen.init(this).
  • Использует пакет org.threeten.bp вместо java.time — API практически идентичен.
  • С появлением desugaring (AGP 4.0+) ThreeTenABP стал опциональным и используется для legacy проектов.

Что такое ThreeTenABP?

ThreeTenABP (ThreeTen Android Backport) — это библиотека, созданная Jake Wharton для использования API даты/времени Java 8 на старых версиях Android. Она является адаптером для проекта ThreeTen-Backport, который портирует java.time (JSR-310) на Java 7 и Android API < 26.

Основная проблема, которую решает библиотека: Android до версии 8 (API 26) не включал java.time в стандартную поставку. Разработчики были вынуждены использовать java.util.Date/Calendar или подключать Joda-Time. ThreeTenABP предоставляет тот же современный API, что и встроенный java.time, но через пакет org.threeten.bp.

По данным GitHub-репозитория (2023), библиотека оптимизирована для Android: данные tzdata (IANA Time Zone Database) хранятся в assets и загружаются через AssetManager, а не через classpath, как на десктопе. Это уменьшает размер APK и ускоряет загрузку.

Последняя стабильная версия — 1.4.0 (август 2021). Библиотека находится в режиме поддержки, так как с широким распространением desugaring необходимость в ней снижается, но она остаётся актуальной для проектов с минимальным API < 26.

Почему нужен backport java.time?

До появления java.time в Java 8 (2014) разработчики использовали java.util.Date и java.util.Calendar. Эти классы имеют серьёзные недостатки: Date мутабельный, Calendar использует неинтуитивные константы (Calendar.JANUARY = 0), оба класса не thread-safe и склонны к ошибкам при работе с часовыми поясами.

Joda-Time была де-факто стандартом до Java 8, но её создатель Стивен Коулборн (Stephen Colebourne) спроектировал java.time как официальную замену, основанную на опыте Joda-Time и учёте её недостатков. Пакет java.time вошёл в JDK 8, но Android не получил его до API 26.

ThreeTen-Backport — это порт java.time на Java 7, созданный тем же автором (Stephen Colebourne). Он включает все основные классы: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter. ThreeTenABP адаптирует этот порт для Android, добавляя инициализацию через AssetsManager и оптимизацию для мобильных устройств.

Таким образом, ThreeTenABP позволяет использовать современный API даты/времени на устройствах с Android 4.0+ (API 14+) без необходимости ждать обновления ОС.

Подключение ThreeTenABP в Android проект

Подключение выполняется в два шага: добавление зависимости в build.gradle (app-level) и инициализация в Application-классе. Важно: ThreeTenABP требует compileSdk не ниже 21 и Gradle версии не ниже 4.0.

Зависимость добавляется в раздел dependencies: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0". С момента релиза 1.4.0 библиотека не обновлялась, так как она стабильна и покрывает все необходимые случаи.

По данным официальной документации, библиотека включает tzdata в assets. Если в приложении уже есть папка assets с другими файлами, ThreeTenABP корректно сосуществует с ними. Размер tzdata — около 200 КБ в сжатом виде.

groovy
// build.gradle (app-level)
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).

Инициализация загружает данные tzdata из assets и настраивает системные часы. Без вызова init() методы now() будут возвращать исключение IllegalStateException с сообщением о том, что библиотека не инициализирована.

Для тестов можно использовать AndroidThreeTen.init(applicationContext, zoneId) — перегрузка с явным указанием часового пояса. Это полезно для предсказуемого поведения тестов. Если нужна только базовая инициализация без tzdata — используйте AndroidThreeTen.initWithoutFiles(context).

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

// Usage after initialization
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 — time-based продолжительность
  • Period — date-based продолжительность
  • DateTimeFormatter — форматирование и парсинг
  • ZoneId / ZoneOffset — часовые пояса

Поддерживаются также вспомогательные классы: Clock, DayOfWeek, Month, Year, YearMonth, MonthDay. Часовые пояса поставляются в комплекте с библиотекой (IANA tzdata). Версия tzdata в ThreeTenABP 1.4.0 соответствует 2021a.

ThreeTenABP vs desugaring

Начиная с Android Gradle Plugin 4.0 (2020) и desugar_jdk_libs, разработчики получили возможность использовать java.time на всех версиях Android через coreLibraryDesugaring. Desugaring трансформирует байт-код так, что вызовы java.time работают на старых API без дополнительных библиотек.

Преимущества desugaring: используется оригинальный пакет java.time (а не org.threeten.bp), не требуется инициализация, полная интеграция с Android Studio. Недостатки: требуется AGP 4.0+, добавляет время сборки, размер APK может увеличиться на 2-3 МБ.

ThreeTenABP остаётся лучшим выбором для legacy проектов, которые не могут обновить AGP до 4.0+, или где критичен размер APK. Также ThreeTenABP проще в настройке — достаточно одной зависимости и одной строки инициализации. По данным Stack Overflow (2024), около 30% проектов с minSdk < 26 всё ещё используют ThreeTenABP вместо desugaring.

Примеры использования

Первый пример — работа с датами через 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)
}

Второй пример — форматирование даты. DateTimeFormatter из org.threeten.bp работает так же, как в 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)
}

Третий пример — работа с ZonedDateTime и конвертация между часовыми поясами в ThreeTenABP.

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.

Второй шаг — удаление инициализации. Строка AndroidThreeTen.init(this) больше не нужна, так как java.time встроен в Android SDK. Удалите вызов из Application.onCreate() и зависимость из build.gradle.

Третий шаг — замена зависимости на desugaring, если minSdk остаётся ниже 26. Добавьте isCoreLibraryDesugaringEnabled = true в compileOptions и зависимость desugar_jdk_libs. Это обеспечит работу java.time на старых API без ThreeTenABP. По данным Google I/O (2023), desugaring — предпочтительный способ для новых проектов.

groovy
// build.gradle — replace ThreeTenABP with desugaring
android {
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
    }
}

dependencies {
    // Remove: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
    // Add:
    "coreLibraryDesugaring"("com.android.tools:desugar_jdk_libs:2.1.4")
}

// Remove AndroidThreeTen.init(this) from Application

Часто задаваемые вопросы

Можно ли использовать ThreeTenABP вместе с desugaring?

Технически — да, но это не имеет смысла. Если используется desugaring, встроенный java.time уже доступен. Использование обеих библиотек приведёт к дублированию кода и увеличению размера APK. Выберите один подход для проекта.

Почему ThreeTenABP требует инициализации в Application?

Инициализация загружает данные IANA Time Zone Database из assets в память. На стандартном JDK tzdata доступна через classpath, но Android использует AssetManager. Метод init() копирует данные в системную директорию, делая их доступными для ZoneId.

Какие версии Android поддерживает ThreeTenABP?

ThreeTenABP поддерживает API 14+ (Android 4.0 Ice Cream Sandwich и выше). Для использования необходима Java 8 compatibility (sourceCompatibility и targetCompatibility в compileOptions). На API 26+ библиотека не нужна — используйте встроенный java.time.

Как обновить часовые пояса в ThreeTenABP?

Часовые пояса поставляются вместе с библиотекой. Версия 1.4.0 включает tzdata 2021a. Для обновления нужно обновить версию ThreeTenABP или вручную заменить tzdata в assets. Последние версии tzdata можно получить из репозитория IANA или через ThreeTen-Backport.

Как тестировать код с ThreeTenABP?

Для unit-тестов используйте AndroidThreeTen.init(context, zoneId) с явным указанием зоны. Для Robolectric тестов — AndroidThreeTen.init(ApplicationProvider.getApplicationContext()). Для чистых JVM тестов без Android — используйте ThreeTen-Backport напрямую без ThreeTenABP.

Итоги

  • ThreeTenABP — Android-адаптер для ThreeTen-Backport, предоставляющий API java.time на устройствах с Android < 8 (API < 26).
  • Подключается через Gradle зависимостью com.jakewharton.threetenabp:threetenabp:1.4.0 и требует инициализации AndroidThreeTen.init(this) в Application.onCreate().
  • Использует пакет org.threeten.bp вместо java.time — API практически идентичен, что упрощает миграцию при переходе на API 26+.
  • Основные классы: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter — все доступны в ThreeTenABP.
  • С появлением desugaring (AGP 4.0+) ThreeTenABP стал опциональным, но остаётся актуальным для legacy проектов или при ограничениях на размер APK.
  • При миграции на java.time замените импорты org.threeten.bp → java.time, удалите AndroidThreeTen.init() и замените зависимость на desugar_jdk_libs.
  • Для тестирования используйте AndroidThreeTen.init(context, zoneId) с явным указанием зоны для предсказуемого поведения.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также