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 — واجهة البرمجة متطابقة تقريبًا.
  • مع ظهور 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.

لماذا نحتاج إلى backport لـ java.time؟

قبل إدخال java.time في Java 8 (2014)، كان المطورون يستخدمون java.util.Date و java.util.Calendar. هذه الفئات لها عيوب خطيرة: Date قابل للتعديل، Calendar يستخدم ثوابت غير بديهية (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

تتم الإضافة في خطوتين: إضافة الاعتمادية في build.gradle (على مستوى التطبيق) والتهيئة في فئة Application. مهم: ThreeTenABP يتطلب compileSdk على الأقل 21 وإصدار Gradle على الأقل 4.0.

تُضاف الاعتمادية في قسم الاعتماديات: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0". منذ إصدار 1.4.0، لم تتم تحديث المكتبة، حيث أنها مستقرة وتغطي جميع الحالات الضرورية.

وفقًا لـ الوثائق الرسمية، تشمل المكتبة tzdata في assets. إذا كان التطبيق يحتوي بالفعل على مجلد assets بملفات أخرى، فإن ThreeTenABP يتعايش معها بشكل صحيح. يبلغ حجم tzdata حوالي 200 كيلوبايت عند الضغط.

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. واجهة البرمجة متطابقة تقريبًا مع 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 بتحويل البايت كود بحيث تعمل استدعاءات java.time على API قديمة بدون مكتبات إضافية.

مزايا desugaring: يستخدم حزمة java.time الأصلية (ليس org.threeten.bp)، لا يتطلب تهيئة، تكامل كامل مع Android Studio. العيوب: يتطلب AGP 4.0+، يزيد وقت التجميع، قد يزداد حجم APK بمقدار 2-3 ميجابايت.

ThreeTenABP يظل الخيار الأفضل للمشاريع القديمة التي لا يمكنها تحديث AGP إلى 4.0+، أو حيث يكون حجم APK حاسمًا. ThreeTenABP أيضًا أسهل في الإعداد — مجرد اعتمادية واحدة وسطر واحد للتهيئة. وفقًا لـ Stack Overflow (2024)، حوالي 30% من المشاريع ذات minSdk < 26 لا تزال تستخدم ThreeTenABP بدلاً من desugaring.

أمثلة الاستخدام

المثال الأول يوضح العمل مع التواريخ باستخدام ThreeTenABP. واجهة البرمجة مطابقة لـ 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 — استبدال 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.

ما هي إصدارات Android التي يدعمها ThreeTenABP؟

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 com.jakewharton.threetenabp:threetenabp:1.4.0 ويتطلب تهيئة AndroidThreeTen.init(this) في Application.onCreate().
  • يستخدم حزمة org.threeten.bp بدلاً من java.time — واجهة البرمجة متطابقة تقريبًا، مما يبسط الترحيل عند الانتقال إلى 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 تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا