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) ไลบรารีนี้เป็น wrapper รอบโครงการ 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 กลายเป็นตัวเลือกและใช้สำหรับโปรเจกต์เดิม

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

ทำไมต้องใช้ java.time backport?

ก่อนที่จะมีการนำ java.time มาใช้ใน Java 8 (2014) นักพัฒนาใช้ java.util.Date และ java.util.Calendar คลาสเหล่านี้มีข้อเสียร้ายแรง: Date สามารถเปลี่ยนแปลงได้ Calendar ใช้ค่าคงที่ที่ไม่ intuitive (Calendar.JANUARY = 0) ทั้งสองคลาสไม่ปลอดภัยต่อเธรดและมีแนวโน้มที่จะเกิดข้อผิดพลาดเมื่อทำงานกับเขตเวลา

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

การเพิ่มทำได้สองขั้นตอน: เพิ่ม dependencies ใน build.gradle (ระดับแอป) และเริ่มต้นในคลาส Application สำคัญ: ThreeTenABP ต้องการ compileSdk อย่างน้อย 21 และ Gradle เวอร์ชันอย่างน้อย 4.0

dependencies ถูกเพิ่มในส่วน dependencies: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0" ตั้งแต่การเปิดตัว 1.4.0 ไลบรารียังไม่ได้รับการอัปเดต เนื่องจากมันเสถียรและครอบคลุมทุกกรณีที่จำเป็น

ตาม เอกสารทางการ ไลบรารีรวม tzdata ไว้ใน assets หากแอปมีโฟลเดอร์ assets พร้อมไฟล์อื่นอยู่แล้ว ThreeTenABP ทำงานร่วมกับไฟล์เหล่านั้นได้อย่างถูกต้อง ขนาดของ tzdata ประมาณ 200 KB เมื่อบีบอัด

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)

การเริ่มต้นโหลดข้อมูล 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)
    }
}

// การใช้งานหลังเริ่มต้น
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) เวอร์ชัน tzdata ใน ThreeTenABP 1.4.0 ตรงกับ 2021a

ThreeTenABP เทียบกับ desugaring

เริ่มจาก Android Gradle Plugin 4.0 (2020) และ desugar_jdk_libs นักพัฒนามีความสามารถในการใช้ java.time บน Android ทุกเวอร์ชันผ่าน coreLibraryDesugaring Desugaring แปลง bytecode เพื่อให้การเรียก java.time ทำงานบน API เก่าโดยไม่ต้องใช้ไลบรารีเพิ่มเติม

ข้อดีของ desugaring: ใช้แพ็กเกจ java.time ดั้งเดิม (ไม่ใช่ org.threeten.bp) ไม่ต้องเริ่มต้น ผสานรวมกับ Android Studio อย่างสมบูรณ์ ข้อเสีย: ต้องการ AGP 4.0+, เพิ่มเวลาในการ build, ขนาด APK อาจเพิ่มขึ้น 2-3 MB

ThreeTenABP ยังคงเป็นตัวเลือกที่ดีที่สุดสำหรับโปรเจกต์เดิมที่ไม่สามารถอัปเดต AGP เป็น 4.0+ หรือที่ขนาด APK มีความสำคัญ ThreeTenABP ยังตั้งค่าได้ง่ายกว่า — แค่ dependencies หนึ่งรายการและการเริ่มต้นหนึ่งบรรทัด ตาม Stack Overflow (2024) ประมาณ 30% ของโปรเจกต์ที่มี minSdk < 26 ยังคงใช้ ThreeTenABP แทน desugaring

ตัวอย่างการใช้งาน

ตัวอย่างแรกแสดงการทำงานกับวันที่โดยใช้ ThreeTenABP API เหมือนกับ java.time แต่ import มาจาก org.threeten.bp ซึ่งช่วยให้คุณเขียนโค้ดที่หลังจากการย้ายต้องการเพียงแค่เปลี่ยน 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)
}

ตัวอย่างที่สองแสดงการจัดรูปแบบวันที่ 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 ในตัว กระบวนการย้ายรวมหลายขั้นตอนและต้องการการทดสอบอย่างละเอียด

ขั้นตอนแรกคือการเปลี่ยน import การ import จาก 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() และ dependencies จาก build.gradle

ขั้นตอนที่สามคือการแทนที่ dependencies ด้วย desugaring หาก minSdk ยังคงต่ำกว่า 26 เพิ่ม isCoreLibraryDesugaringEnabled = true ใน compileOptions และ dependencies desugar_jdk_libs ซึ่งจะทำให้ java.time ทำงานบน API เก่าโดยไม่ต้องใช้ ThreeTenABP ตาม 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")
}

// ลบ AndroidThreeTen.init(this) ออกจาก Application

คำถามที่พบบ่อย

สามารถใช้ 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 (sourceCompatibility และ targetCompatibility ใน compileOptions) บน API 26+ ไม่จำเป็นต้องใช้ไลบรารี — ใช้ java.time ในตัว

จะอัปเดตเขตเวลาใน ThreeTenABP ได้อย่างไร?

เขตเวลามาพร้อมกับไลบรารี เวอร์ชัน 1.4.0 รวม tzdata 2021a ในการอัปเดต คุณต้องอัปเดตเวอร์ชัน ThreeTenABP หรือแทนที่ tzdata ใน assets ด้วยตนเอง เวอร์ชันล่าสุดของ tzdata สามารถหาได้จากพื้นที่เก็บ IANA หรือผ่าน ThreeTen-Backport

จะทดสอบโค้ดกับ ThreeTenABP ได้อย่างไร?

สำหรับการทดสอบหน่วย ใช้ 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 dependencies 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 กลายเป็นตัวเลือก แต่ยังคงมีความเกี่ยวข้องสำหรับโปรเจกต์เดิมหรือเมื่อขนาด APK มีข้อจำกัด
  • เมื่อย้ายไปยัง java.time ให้เปลี่ยน import org.threeten.bp → java.time ลบ AndroidThreeTen.init() และแทนที่ dependencies ด้วย desugar_jdk_libs
  • สำหรับการทดสอบ ใช้ AndroidThreeTen.init(context, zoneId) พร้อมการระบุเขตอย่างชัดเจนเพื่อพฤติกรรมที่คาดเดาได้

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม