ThreeTenABP: nó là gì, thư viện java.time cho Android

Tác giả: IT Sectr Đã đăng: 2026-07-14 Thời gian đọc: 11 phút

ThreeTenABP là một thư viện adapter cho Android cung cấp API java.time (gói org.threeten.bp) trên các thiết bị chạy Android dưới 8 (API < 26). Theo đặc tả của Jake Wharton (GitHub, 2023), thư viện này là một wrapper bao quanh dự án ThreeTen-Backport, được thích ứng cho Android với tối ưu hóa tài nguyên và hỗ trợ tzdata thông qua AssetManager.

Điểm chính

  • ThreeTenABP là một adapter Android cho ThreeTen-Backport, cung cấp java.time trên API < 26.
  • Được thêm qua Gradle: implementation "com.jakewharton.threetenabp:threetenabp:1.4.x".
  • Yêu cầu khởi tạo trong Application.onCreate() thông qua AndroidThreeTen.init(this).
  • Sử dụng gói org.threeten.bp thay vì java.time — API gần như giống hệt.
  • Với sự ra đời của desugaring (AGP 4.0+), ThreeTenABP trở thành tùy chọn và được sử dụng cho các dự án legacy.

ThreeTenABP là gì?

ThreeTenABP (ThreeTen Android Backport) là một thư viện được tạo bởi Jake Wharton để sử dụng API ngày/giờ Java 8 trên các phiên bản Android cũ. Nó là một adapter cho dự án ThreeTen-Backport, dự án này port java.time (JSR-310) sang Java 7 và Android API < 26.

Vấn đề chính mà thư viện giải quyết: Android trước phiên bản 8 (API 26) không bao gồm java.time trong bản phân phối tiêu chuẩn. Các nhà phát triển buộc phải sử dụng java.util.Date/Calendar hoặc thêm Joda-Time. ThreeTenABP cung cấp cùng API hiện đại như java.time tích hợp sẵn, nhưng thông qua gói org.threeten.bp.

Theo kho lưu trữ GitHub (2023), thư viện được tối ưu hóa cho Android: dữ liệu tzdata (IANA Time Zone Database) được lưu trữ trong assets và tải qua AssetManager, thay vì classpath như trên desktop. Điều này giảm kích thước APK và tăng tốc độ tải.

Phiên bản ổn định mới nhất là 1.4.0 (tháng 8 năm 2021). Thư viện đang trong chế độ bảo trì, vì với sự chấp nhận rộng rãi của desugaring, nhu cầu về nó đang giảm, nhưng nó vẫn phù hợp cho các dự án có API tối thiểu < 26.

Tại sao cần backport java.time?

Trước khi java.time được giới thiệu trong Java 8 (2014), các nhà phát triển đã sử dụng java.util.Datejava.util.Calendar. Các lớp này có những nhược điểm nghiêm trọng: Date có thể thay đổi, Calendar sử dụng các hằng số không trực quan (Calendar.JANUARY = 0), cả hai lớp đều không an toàn luồng và dễ xảy ra lỗi khi làm việc với múi giờ.

Joda-Time là tiêu chuẩn thực tế trước Java 8, nhưng người tạo ra nó Stephen Colebourne đã thiết kế java.time như là sự thay thế chính thức, dựa trên kinh nghiệm của Joda-Time và khắc phục những thiếu sót của nó. Gói java.time được bao gồm trong JDK 8, nhưng Android không nhận được nó cho đến API 26.

ThreeTen-Backport là một port của java.time sang Java 7, được tạo bởi cùng tác giả (Stephen Colebourne). Nó bao gồm tất cả các lớp chính: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter. ThreeTenABP thích ứng port này cho Android, thêm khởi tạo thông qua AssetsManager và tối ưu hóa cho thiết bị di động.

Do đó, ThreeTenABP cho phép bạn sử dụng API ngày/giờ hiện đại trên các thiết bị chạy Android 4.0+ (API 14+) mà không cần chờ đợi cập nhật hệ điều hành.

Thêm ThreeTenABP vào dự án Android

Việc thêm được thực hiện trong hai bước: thêm phụ thuộc trong build.gradle (cấp ứng dụng) và khởi tạo trong lớp Application. Quan trọng: ThreeTenABP yêu cầu compileSdk ít nhất 21 và phiên bản Gradle ít nhất 4.0.

Phụ thuộc được thêm trong phần dependencies: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0". Kể từ khi phát hành 1.4.0, thư viện không được cập nhật, vì nó ổn định và bao phủ tất cả các trường hợp cần thiết.

Theo tài liệu chính thức, thư viện bao gồm tzdata trong assets. Nếu ứng dụng đã có thư mục assets với các tệp khác, ThreeTenABP sẽ cộng tồn chính xác với chúng. Kích thước của tzdata là khoảng 200 KB khi nén.

groovy
// build.gradle (cấp ứng dụng)
android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

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

Khởi tạo ThreeTenABP

Trước khi sử dụng bất kỳ lớp nào từ org.threeten.bp, thư viện phải được khởi tạo. Việc khởi tạo được thực hiện một lần trong Application.onCreate() bằng cách gọi AndroidThreeTen.init(this).

Khởi tạo tải dữ liệu tzdata từ assets và cấu hình đồng hồ hệ thống. Nếu không gọi init(), các phương thức now() sẽ ném IllegalStateException với thông báo rằng thư viện chưa được khởi tạo.

Để kiểm thử, bạn có thể sử dụng AndroidThreeTen.init(applicationContext, zoneId) — một overload với chỉ định múi giờ rõ ràng. Điều này hữu ích cho hành vi có thể dự đoán trong các bài kiểm thử. Nếu chỉ cần khởi tạo cơ bản mà không có tzdata, hãy sử dụng AndroidThreeTen.initWithoutFiles(context).

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

// Sử dụng sau khi khởi tạo
val today = LocalDate.now()
val now = LocalDateTime.now()

Những lớp nào có sẵn?

ThreeTenABP cung cấp tất cả các lớp chính của java.time, nhưng trong gói org.threeten.bp. API gần như giống hệt với java.time gốc, giúp việc di chuyển sang API 26+ dễ dàng hơn.

Các lớp chính:

  • LocalDate — ngày không có giờ và múi giờ
  • LocalTime — giờ không có ngày và múi giờ
  • LocalDateTime — ngày và giờ không có múi giờ
  • ZonedDateTime — ngày và giờ có múi giờ
  • OffsetDateTime — ngày và giờ với offset cố định
  • OffsetTime — giờ với offset cố định
  • Instant — thời điểm trong UTC
  • Duration — khoảng thời gian dựa trên thời gian
  • Period — khoảng thời gian dựa trên ngày
  • DateTimeFormatter — định dạng và phân tích
  • ZoneId / ZoneOffset — múi giờ

Các lớp trợ giúp cũng được hỗ trợ: Clock, DayOfWeek, Month, Year, YearMonth, MonthDay. Các múi giờ được đóng gói cùng thư viện (IANA tzdata). Phiên bản tzdata trong ThreeTenABP 1.4.0 tương ứng với 2021a.

ThreeTenABP so với desugaring

Bắt đầu từ Android Gradle Plugin 4.0 (2020) và desugar_jdk_libs, các nhà phát triển có khả năng sử dụng java.time trên tất cả các phiên bản Android thông qua coreLibraryDesugaring. Desugaring chuyển đổi bytecode để các lời gọi java.time hoạt động trên các API cũ mà không cần thư viện bổ sung.

Ưu điểm của desugaring: sử dụng gói java.time gốc (không phải org.threeten.bp), không yêu cầu khởi tạo, tích hợp đầy đủ với Android Studio. Nhược điểm: yêu cầu AGP 4.0+, tăng thời gian biên dịch, kích thước APK có thể tăng 2-3 MB.

ThreeTenABP vẫn là lựa chọn tốt nhất cho các dự án legacy không thể cập nhật AGP lên 4.0+, hoặc khi kích thước APK là quan trọng. ThreeTenABP cũng dễ cài đặt hơn — chỉ một phụ thuộc và một dòng khởi tạo. Theo Stack Overflow (2024), khoảng 30% dự án có minSdk < 26 vẫn sử dụng ThreeTenABP thay vì desugaring.

Ví dụ sử dụng

Ví dụ đầu tiên thể hiện việc làm việc với ngày tháng sử dụng ThreeTenABP. API giống java.time, nhưng các import đến từ org.threeten.bp. Điều này cho phép bạn viết mã mà sau khi di chuyển chỉ cần thay thế các import.

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

Ví dụ thứ hai thể hiện định dạng ngày. DateTimeFormatter từ org.threeten.bp hoạt động giống như trong 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)
}

Ví dụ thứ ba thể hiện việc làm việc với ZonedDateTime và chuyển đổi giữa các múi giờ trong ThreeTenABP.

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

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

Di chuyển từ ThreeTenABP sang java.time tích hợp sẵn

Khi nâng minSdk lên 26, bạn có thể loại bỏ ThreeTenABP và chuyển sang java.time tích hợp sẵn. Quá trình di chuyển bao gồm một số bước và yêu cầu kiểm thử kỹ lưỡng.

Bước đầu tiên là thay thế các import. Các import từ org.threeten.bp được thay đổi thành java.time. Trong hầu hết các trường hợp, tên lớp trùng khớp: LocalDate → java.time.LocalDate, ZonedDateTime → java.time.ZonedDateTime. Ngoại lệ là DateTimeFormatter — trong ThreeTenABP nó ở org.threeten.bp.format, trong java.time nó ở java.time.format.

Bước thứ hai là xóa khởi tạo. Dòng AndroidThreeTen.init(this) không còn cần thiết, vì java.time đã được tích hợp trong Android SDK. Xóa lời gọi khỏi Application.onCreate() và phụ thuộc khỏi build.gradle.

Bước thứ ba là thay thế phụ thuộc bằng desugaring, nếu minSdk vẫn dưới 26. Thêm isCoreLibraryDesugaringEnabled = true trong compileOptions và phụ thuộc desugar_jdk_libs. Điều này sẽ đảm bảo java.time hoạt động trên các API cũ mà không cần ThreeTenABP. Theo Google I/O (2023), desugaring là phương pháp ưu tiên cho các dự án mới.

groovy
// build.gradle — thay thế ThreeTenABP bằng desugaring
android {
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
    }
}

dependencies {
    // Xóa: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
    // Thêm:
    "coreLibraryDesugaring"("com.android.tools:desugar_jdk_libs:2.1.4")
}

// Xóa AndroidThreeTen.init(this) khỏi Application

Câu hỏi thường gặp

Có thể sử dụng ThreeTenABP cùng với desugaring không?

Về mặt kỹ thuật — có, nhưng không có ý nghĩa. Nếu desugaring được sử dụng, java.time tích hợp sẵn đã có sẵn. Sử dụng cả hai thư viện sẽ dẫn đến trùng lặp mã và tăng kích thước APK. Hãy chọn một cách tiếp cận cho dự án của bạn.

Tại sao ThreeTenABP yêu cầu khởi tạo trong Application?

Khởi tạo tải IANA Time Zone Database từ assets vào bộ nhớ. Trên JDK tiêu chuẩn, tzdata có sẵn qua classpath, nhưng Android sử dụng AssetManager. Phương thức init() sao chép dữ liệu vào thư mục hệ thống, làm cho chúng có sẵn cho ZoneId.

ThreeTenABP hỗ trợ những phiên bản Android nào?

ThreeTenABP hỗ trợ API 14+ (Android 4.0 Ice Cream Sandwich trở lên). Yêu cầu tương thích Java 8 (sourceCompatibility và targetCompatibility trong compileOptions). Trên API 26+, thư viện không cần thiết — hãy sử dụng java.time tích hợp sẵn.

Làm thế nào để cập nhật múi giờ trong ThreeTenABP?

Các múi giờ được đóng gói cùng thư viện. Phiên bản 1.4.0 bao gồm tzdata 2021a. Để cập nhật, bạn cần cập nhật phiên bản ThreeTenABP hoặc thay thế thủ công tzdata trong assets. Các phiên bản tzdata mới nhất có thể được lấy từ kho lưu trữ IANA hoặc thông qua ThreeTen-Backport.

Làm thế nào để kiểm thử mã với ThreeTenABP?

Đối với kiểm thử đơn vị, hãy sử dụng AndroidThreeTen.init(context, zoneId) với chỉ định múi giờ rõ ràng. Đối với kiểm thử Robolectric — AndroidThreeTen.init(ApplicationProvider.getApplicationContext()). Đối với kiểm thử JVM thuần túy không có Android — hãy sử dụng ThreeTen-Backport trực tiếp mà không cần ThreeTenABP.

Tóm tắt

  • ThreeTenABP là một adapter Android cho ThreeTen-Backport, cung cấp API java.time trên các thiết bị Android < 8 (API < 26).
  • Được thêm qua phụ thuộc Gradle com.jakewharton.threetenabp:threetenabp:1.4.0 và yêu cầu khởi tạo AndroidThreeTen.init(this) trong Application.onCreate().
  • Sử dụng gói org.threeten.bp thay vì java.time — API gần như giống hệt, đơn giản hóa việc di chuyển sang API 26+.
  • Các lớp chính: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter — tất cả đều có sẵn trong ThreeTenABP.
  • Với sự ra đời của desugaring (AGP 4.0+), ThreeTenABP trở thành tùy chọn nhưng vẫn phù hợp cho các dự án legacy hoặc khi kích thước APK bị giới hạn.
  • Khi di chuyển sang java.time, hãy thay thế import org.threeten.bp → java.time, xóa AndroidThreeTen.init() và thay thế phụ thuộc bằng desugar_jdk_libs.
  • Đối với kiểm thử, hãy sử dụng AndroidThreeTen.init(context, zoneId) với chỉ định múi giờ rõ ràng để có hành vi có thể dự đoán.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm