ThreeTenABP: vad är det, java.time-bibliotek för Android

Författare: IT Sectr Publicerad: 2026-07-14 Lästid: 11 min

ThreeTenABP — adapterbibliotek för Android, som tillhandahåller java.time API (paketet org.threeten.bp) på enheter med Android under 8 (API < 26). Enligt specifikationen Jake Wharton (GitHub, 2023) är biblioteket ett omslag kring projektet ThreeTen-Backport, anpassat för Android med hänsyn till resursoptimering och stöd för tzdata via AssetManager.

Huvudpunkter

  • ThreeTenABP — Android-adapter för ThreeTen-Backport, som tillhandahåller java.time på API < 26.
  • Ansluts via Gradle: implementation ”com.jakewharton.threetenabp:threetenabp:1.4.x”.
  • Kräver initialisering i Application.onCreate() via AndroidThreeTen.init(this).
  • Använder paketet org.threeten.bp istället för java.time — API:et är praktiskt taget identiskt.
  • Med tillkomsten av desugaring (AGP 4.0+) har ThreeTenABP blivit valfritt och används för legacy-projekt.

Vad är ThreeTenABP?

ThreeTenABP (ThreeTen Android Backport) — ett bibliotek skapat av Jake Wharton för att använda Java 8 datum/tid API på äldre Android-versioner. Det är en adapter för projektet ThreeTen-Backport, som porterar java.time (JSR-310) till Java 7 och Android API < 26.

Huvudproblemet som biblioteket löser: Android upp till version 8 (API 26) inkluderade inte java.time i standardutbudet. Utvecklare var tvungna att använda java.util.Date/Calendar eller lägga till Joda-Time. ThreeTenABP tillhandahåller samma moderna API som inbyggd java.time, men via paketet org.threeten.bp.

Enligt GitHub-repository (2023) är biblioteket optimerat för Android: tzdata-data (IANA Time Zone Database) lagras i assets och laddas via AssetManager, inte via classpath som på skrivbordet. Detta minskar APK-storleken och snabbar upp laddningen.

Senaste stabila versionen — 1.4.0 (augusti 2021). Biblioteket är i supportläge, eftersom behovet av det minskar i takt med den breda spridningen av desugaring, men det förblir relevant för projekt med minimal API < 26.

Varför behövs backport av java.time?

Innan java.time kom i Java 8 (2014) använde utvecklare java.util.Date och java.util.Calendar. Dessa klasser har allvarliga brister: Date är muterbar, Calendar använder ointuitiva konstanter (Calendar.JANUARY = 0), båda klasserna är inte trådsäkra och benägna att fel vid arbete med tidszoner.

Joda-Time var de facto-standard före Java 8, men dess skapare Stephen Colebourne designade java.time som officiell ersättning, baserad på erfarenheterna från Joda-Time och med hänsyn till dess brister. Paketet java.time ingick i JDK 8, men Android fick det inte förrän API 26.

ThreeTen-Backport — en port av java.time till Java 7, skapad av samma författare (Stephen Colebourne). Den innehåller alla huvudklasser: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter. ThreeTenABP anpassar denna port för Android, med initialisering via AssetsManager och optimering för mobila enheter.

ThreeTenABP gör det alltså möjligt att använda modernt datum/tid API på enheter med Android 4.0+ (API 14+) utan att vänta på en OS-uppdatering.

Ansluta ThreeTenABP i Android-projekt

Anslutning görs i två steg: lägga till beroendet i build.gradle (app-level) och initialisering i Application-klassen. Viktigt: ThreeTenABP kräver compileSdk inte lägre än 21 och Gradle-version inte lägre än 4.0.

Beroendet läggs till i dependencies-sektionen: implementation ”com.jakewharton.threetenabp:threetenabp:1.4.0”. Sedan version 1.4.0 släpptes har biblioteket inte uppdaterats, eftersom det är stabilt och täcker alla nödvändiga fall.

Enligt officiell dokumentation innehåller biblioteket tzdata i assets. Om appen redan har en assets-mapp med andra filer samexisterar ThreeTenABP korrekt med dem. Tzdata är cirka 200 KB i komprimerad form.

groovy
// build.gradle (app-nivå)
android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

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

Initialisera ThreeTenABP

Innan du använder någon klass från org.threeten.bp måste biblioteket initialiseras. Initialisering görs en gång i Application.onCreate() via anropet AndroidThreeTen.init(this).

Initialisering laddar tzdata-data från assets och konfigurerar systemklockan. Utan anrop till init() kommer now()-metoderna att kasta IllegalStateException med meddelande om att biblioteket inte är initialiserat.

För tester kan AndroidThreeTen.init(applicationContext, zoneId) användas — överlagring med explicit angivelse av tidszon. Detta är användbart för förutsägbart testbeteende. Om endast grundläggande initialisering utan tzdata behövs — använd AndroidThreeTen.initWithoutFiles(context).

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

// Användning efter initialisering
val today = LocalDate.now()
val now = LocalDateTime.now()

Vilka klasser finns tillgängliga?

ThreeTenABP tillhandahåller alla huvudklasser i java.time, men i paketet org.threeten.bp. API:et är praktiskt taget identiskt med ursprunglig java.time, vilket förenklar migrering vid övergång till API 26+.

Huvudklasser:

  • LocalDate — datum utan tid och tidszon
  • LocalTime — tid utan datum och tidszon
  • LocalDateTime — datum och tid utan tidszon
  • ZonedDateTime — datum och tid med tidszon
  • OffsetDateTime — datum och tid med fast offset
  • OffsetTime — tid med fast offset
  • Instant — tidpunkt i UTC
  • Duration — time-based varaktighet
  • Period — date-based period
  • DateTimeFormatter — formatering och tolkning
  • ZoneId / ZoneOffset — tidszoner

Även hjälpklasser stöds: Clock, DayOfWeek, Month, Year, YearMonth, MonthDay. Tidszoner levereras med biblioteket (IANA tzdata). Tzdata-versionen i ThreeTenABP 1.4.0 motsvarar 2021a.

ThreeTenABP vs desugaring

Från och med Android Gradle Plugin 4.0 (2020) och desugar_jdk_libs har utvecklare fått möjlighet att använda java.time på alla Android-versioner via coreLibraryDesugaring. Desugaring transformerar bytekod så att java.time-anrop fungerar på gamla API:er utan extra bibliotek.

Fördelar med desugaring: det ursprungliga java.time-paketet används (inte org.threeten.bp), ingen initialisering krävs, full integration med Android Studio. Nackdelar: kräver AGP 4.0+, ökar byggtiden, APK-storleken kan öka med 2-3 MB.

ThreeTenABP förblir det bästa valet för legacy-projekt som inte kan uppdatera AGP till 4.0+, eller där APK-storlek är kritisk. ThreeTenABP är också enklare att konfigurera — ett beroende och en rad initialisering räcker. Enligt Stack Overflow (2024) använder cirka 30% av projekten med minSdk < 26 fortfarande ThreeTenABP istället för desugaring.

Användningsexempel

Första exemplet — arbete med datum via ThreeTenABP. API:et är identiskt med java.time, men importerna kommer från org.threeten.bp. Detta gör det möjligt att skriva kod som efter migrering endast kräver byte av importer.

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)
}

Andra exemplet — datumformatering. DateTimeFormatter från org.threeten.bp fungerar som i 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)
}

Tredje exemplet — arbete med ZonedDateTime och konvertering mellan tidszoner i ThreeTenABP.

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

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

Migrering från ThreeTenABP till inbyggd java.time

När minSdk höjs till 26 kan man lämna ThreeTenABP och gå över till inbyggd java.time. Migreringsprocessen omfattar flera steg och kräver noggrann testning.

Första steget — byte av importer. Importer från org.threeten.bp ändras till java.time. I de flesta fall överensstämmer klassnamnen: LocalDate → java.time.LocalDate, ZonedDateTime → java.time.ZonedDateTime. Undantaget är DateTimeFormatter — i ThreeTenABP är den i org.threeten.bp.format, i java.time — i java.time.format.

Andra steget — borttagning av initialisering. Rader AndroidThreeTen.init(this) behövs inte längre, eftersom java.time är inbyggt i Android SDK. Ta bort anropet från Application.onCreate() och beroendet från build.gradle.

Tredje steget — ersätt beroendet med desugaring, om minSdk förblir under 26. Lägg till isCoreLibraryDesugaringEnabled = true i compileOptions och beroendet desugar_jdk_libs. Detta säkerställer att java.time fungerar på gamla API:er utan ThreeTenABP. Enligt Google I/O (2023) är desugaring den föredragna metoden för nya projekt.

groovy
// build.gradle — ersätt ThreeTenABP med desugaring
android {
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
    }
}

dependencies {
    // Ta bort: implementation ”com.jakewharton.threetenabp:threetenabp:1.4.0”
    // Lägg till:
    "coreLibraryDesugaring"("com.android.tools:desugar_jdk_libs:2.1.4")
}

// Ta bort AndroidThreeTen.init(this) från Application

Vanliga frågor

Kan ThreeTenABP användas tillsammans med desugaring?

Tekniskt — ja, men det är inte meningsfullt. Om desugaring används är inbyggd java.time redan tillgänglig. Användning av båda biblioteken leder till kodduplicering och ökad APK-storlek. Välj en metod för projektet.

Varför kräver ThreeTenABP initialisering i Application?

Initialisering laddar IANA Time Zone Database-data från assets till minnet. På standard JDK är tzdata tillgänglig via classpath, men Android använder AssetManager. Metoden init() kopierar data till systemkatalogen, vilket gör dem tillgängliga för ZoneId.

Vilka Android-versioner stöder ThreeTenABP?

ThreeTenABP stöder API 14+ (Android 4.0 Ice Cream Sandwich och högre). För användning krävs Java 8 compatibility (sourceCompatibility och targetCompatibility i compileOptions). På API 26+ behövs inte biblioteket — använd inbyggd java.time.

Hur uppdaterar man tidszoner i ThreeTenABP?

Tidszoner levereras med biblioteket. Version 1.4.0 innehåller tzdata 2021a. För uppdatering måste ThreeTenABP-versionen uppdateras eller tzdata manuellt ersättas i assets. Senaste tzdata-versionerna kan hämtas från IANA-repository eller via ThreeTen-Backport.

Hur testar man kod med ThreeTenABP?

För enhetstester, använd AndroidThreeTen.init(context, zoneId) med explicit zonangivelse. För Robolectric-tester — AndroidThreeTen.init(ApplicationProvider.getApplicationContext()). För rena JVM-tester utan Android — använd direkt ThreeTen-Backport utan ThreeTenABP.

Sammanfattning

  • ThreeTenABP — Android-adapter för ThreeTen-Backport, som tillhandahåller java.time API på enheter med Android < 8 (API < 26).
  • Ansluts via Gradle-beroende com.jakewharton.threetenabp:threetenabp:1.4.0 och kräver initialisering AndroidThreeTen.init(this) i Application.onCreate().
  • Använder paketet org.threeten.bp istället för java.time — API:et är praktiskt taget identiskt, vilket förenklar migrering till API 26+.
  • Huvudklasser: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter — alla tillgängliga i ThreeTenABP.
  • Med tillkomsten av desugaring (AGP 4.0+) har ThreeTenABP blivit valfritt, men förblir relevant för legacy-projekt eller vid APK-storleksbegränsningar.
  • Vid migrering till java.time, byt importer org.threeten.bp → java.time, ta bort AndroidThreeTen.init() och ersätt beroendet med desugar_jdk_libs.
  • För testning, använd AndroidThreeTen.init(context, zoneId) med explicit zonangivelse för förutsägbart beteende.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också