DateIntervalFormatter — أساسيات تنسيق فترات التاريخ

المؤلف: IT Sectr نُشر: 2026-07-13 وقت القراءة: 11 دق

DateIntervalFormatter هي فئة من Foundation في iOS وmacOS مصممة لتنسيق نطاقات التاريخ إلى سلاسل مترجمة: «21–25 يوليو 2024»، «من 21 إلى 25 يوليو 2024» أو «Jul 21–25, 2024». وفقًا لـ Apple Developer Documentation, 2024، يقوم DateIntervalFormatter تلقائيًا بتحديد مكونات التاريخ التي يجب تكرارها (إذا كان النطاق ضمن شهر واحد، يظهر الشهر مرة واحدة)، ويقوم بتوطين الفواصل وترتيب الكلمات. على عكس الدمج اليدوي لتاريخين منسقين، تراعي هذه الفئة القواعد النحوية للغة. الفئة متاحة منذ iOS 8 وmacOS 10.10.

النقاط الرئيسية

  • DateIntervalFormatter — فئة Foundation لتنسيق نطاقات التاريخ (iOS 8+)
  • التجميع التلقائي — المكونات المتكررة (الشهر، السنة) تظهر مرة واحدة
  • فواصل مترجمة — قواعد نحوية: «إلى» (العربية)، شرطة (الإنجليزية)
  • خمسة أنماط للتاريخ — .none, .short, .medium, .long, .full لكل طرف من النطاق
  • أربعة أنماط للوقت — نفس مستويات التفاصيل للجزء الزمني من النطاق

ما هو DateIntervalFormatter؟

DateIntervalFormatter هي فئة فرعية من Formatter في Foundation تأخذ كائن DateInterval (نطاق بين تاريخين) وتعيد سلسلة مترجمة تصف ذلك النطاق. على سبيل المثال، للنطاق من 21 إلى 25 يوليو 2024، ستكون النتيجة «21–25 يوليو 2024» لـ ar_SA. تقوم الفئة بتجميع العناصر المتكررة بذكاء: إذا كان كلا التاريخين في نفس الشهر، يظهر اسم الشهر مرة واحدة.

القيمة الرئيسية لـ DateIntervalFormatter هي المعالجة التلقائية لقواعد النطاقات. عند التنسيق اليدوي، سيتعين على المطور مقارنة شهر/سنة البداية والنهاية، واختيار فاصل (شرطة، «إلى»، «bis»)، والتعامل مع الإعراب. يقوم DateIntervalFormatter بذلك تلقائيًا استنادًا إلى بيانات CLDR (مستودع البيانات المحلية المشتركة)، مما يقلل من الأخطاء في التطبيقات الدولية، خاصة للغات ذات القواعد المعقدة.

وفقًا لـ Unicode CLDR v44 (2024)، تختلف قواعد تنسيق فترات التاريخ بشكل كبير بين اللغات. تستخدم الألمانية حرف الجر «bis» (21.–25. Juli 2024)، والفرنسية تستخدم «au» (du 21 au 25 juillet 2024)، واليابانية تستخدم واصلة (2024 Jul 21–25). يغطي DateIntervalFormatter كل هذه الاختلافات دون الحاجة إلى تعليمات برمجية إضافية من المطور.

كيف يعمل DateIntervalFormatter في Foundation؟

مبدأ العمل لـ DateIntervalFormatter يعتمد على تحليل تاريخين يشكلان نطاقًا واختيار التمثيل النصي الأمثل مع مراعاة الإعدادات المحلية. تقوم الفئة بمقارنة مكونات التاريخ (السنة، الشهر، اليوم) واتخاذ قرارات التجميع: إذا كانت السنة نفسها، تظهر مرة واحدة؛ إذا كان الشهر نفسه، يظهر مرة واحدة؛ إذا اختلفت الأيام، يظهر نطاق الأيام.

النطاقar_SA
يوم واحد21 يوليو 2024
ضمن الشهر21–25 يوليو 2024
أشهر مختلفة21 يوليو – 5 أغسطس 2024
سنوات مختلفة25 ديسمبر 2024 – 5 يناير 2025
مع الوقت21 يوليو 2024، 14:30–16:45

منطق التجميع منفذ بناءً على قوالب CLDR. يتحقق المنسق من مساواة كل مكون تاريخ (Calendar.Component: year, month, day) بالترتيب من الأكبر إلى الأصغر. بمجرد اختلاف مكون، تظهر جميع المكونات الأصغر لكلا التاريخين. على سبيل المثال، لـ 21–25 يوليو: السنة متطابقة، الشهر متطابق، اليوم مختلف ← يظهر الشهر مرة واحدة، وتظهر الأيام لكل تاريخ.

ملاحظة مهمة: DateIntervalFormatter لا يدعم تخصيص الفاصل عبر API. يتم تحديد الفاصل بواسطة الإعدادات المحلية ولا يمكن تجاوزه. إذا كان هناك حاجة إلى فاصل غير قياسي (على سبيل المثال، «حتى» بدلاً من «إلى»)، فسيلزم تنسيق التواريخ يدويًا باستخدام DateFormatter ودمج السلاسل بفاصل مخصص.

أنماط تنسيق الفترات

DateIntervalFormatter يوفر مجموعتين من الأنماط: dateStyle وtimeStyle لكل طرف من النطاق. تعمل هذه الأنماط بشكل مشابه لـ DateFormatter: .none يخفي المكون، .short يعطي تنسيقًا قصيرًا (21/07/2024)، .medium (21 يول 2024)، .long (21 يوليو 2024)، .full (الأحد، 21 يوليو 2024). من خلال الجمع بين dateStyle وtimeStyle، يمكن تحقيق مستويات مختلفة من التفاصيل.

أمثلة على تركيبات الأنماط

  • dateStyle = .medium, timeStyle = .none — تاريخ فقط: «21–25 يوليو 2024»
  • dateStyle = .short, timeStyle = .short — تاريخ ووقت: «21/07/2024، 14:30 – 25/07/2024، 16:45»
  • dateStyle = .none, timeStyle = .short — وقت فقط: «14:30–16:45» (إذا كانت التواريخ متطابقة)
  • dateStyle = .long, timeStyle = .none — تاريخ طويل: «21–25 يوليو 2024»
  • dateStyle = .full, timeStyle = .short — تنسيق كامل: «الأحد، 21 يوليو 2024 – الخميس، 25 يوليو 2024»

مهم: dateStyle وtimeStyle يتم تطبيقهما على طرفي النطاق بالتساوي. لا يمكن تعيين أنماط مختلفة للبداية والنهاية (مثل .medium للبداية و.short للنهاية). إذا كانت هناك حاجة لأنماط مختلفة، فيجب تنسيق كل تاريخ باستخدام DateFormatter منفصل ودمج النتائج.

swift
import Foundation

let formatter = DateIntervalFormatter()

// تركيبات أنماط مختلفة
let startDate = Date()
let endDate = Date().addingTimeInterval(345600) // +4 أيام
let interval = DateInterval(start: startDate, end: endDate)

// تاريخ فقط، تنسيق متوسط
formatter.dateStyle = .medium
formatter.timeStyle = .none
print("تاريخ فقط: \(formatter.string(from: interval))")

// تنسيق قصير مع الوقت
formatter.dateStyle = .short
formatter.timeStyle = .short
print("قصير مع الوقت: \(formatter.string(from: interval))")

// تنسيق كامل
formatter.dateStyle = .full
formatter.timeStyle = .none
print("تاريخ كامل: \(formatter.string(from: interval))")

DateIntervalFormatter في Swift: أمثلة

الاستخدام الأساسي لـ DateIntervalFormatter يشمل إنشاء مثيل، تعيين الأنماط، واستدعاء string(from:). تقبل الطريقة DateInterval، وهي هيكل بخصائص start وend. يمكن إنشاء DateInterval من قيمتي Date أو تهيئته بـ Duration (iOS 16+). بعد التنسيق، تكون النتيجة جاهزة للعرض في واجهة المستخدم دون معالجة إضافية.

swift
import Foundation

let calendar = Calendar.current
let now = Date()

// أمثلة فترات محددة
let examples: [(title: String, start: Date, end: Date)] = [
    (
        "2-hour event",
        now,
        now.addingTimeInterval(7200)
    ),
    (
        "Week-long vacation",
        now,
        now.addingTimeInterval(604800)
    ),
    (
        "Cross-year period",
        calendar.date(from: DateComponents(
            year: 2024, month: 12, day: 25
        ))!,
        calendar.date(from: DateComponents(
            year: 2025, month: 1, day: 5
        ))!
    )
]

let intervalFormatter = DateIntervalFormatter()
intervalFormatter.dateStyle = .medium
intervalFormatter.timeStyle = .short

for (title, start, end) in examples {
    let interval = DateInterval(start: start, end: end)
    let result = intervalFormatter.string(from: interval)
    print("\(title): \(result)")
}

// تنسيق عبر Calendar (iOS 16+)
if let nextWeek = calendar.date(
    byAdding: .day, value: 7, to: now
) {
    let weekInterval = DateInterval(start: now, end: nextWeek)
    print("الأيام السبعة القادمة: \(intervalFormatter.string(from: weekInterval))")
}

DateIntervalFormatter وحجوزات التقويم: في تطبيقات الحجز (الفنادق، التذاكر)، تعتبر فترات التاريخ عنصرًا رئيسيًا في واجهة المستخدم. يعالج DateIntervalFormatter بشكل صحيح الفترات عبر السنوات (مثل 28 ديسمبر إلى 3 يناير)، مع تجميع الشهر والسنة لكل تاريخ على حدة. لمثل هذه السيناريوهات، يُوصى باستخدام dateStyle = .medium وtimeStyle = .none، وهو التنسيق الأكثر قابلية للقراءة للتواريخ بدون وقت.

swift
import Foundation

let formatter = DateIntervalFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .none

// أمثلة حجوزات
struct Booking {
    let checkIn: Date
    let checkOut: Date

    var formattedInterval: String {
        let interval = DateInterval(start: checkIn, end: checkOut)
        return formatter.string(from: interval)
    }
}

let booking = Booking(
    checkIn: calendar.date(from: DateComponents(
        year: 2024, month: 7, day: 21
    ))!,
    checkOut: calendar.date(from: DateComponents(
        year: 2024, month: 7, day: 25
    ))!
)
print("حجز: \(booking.formattedInterval)")

// الاستخدام مع إعدادات محلية مختلفة
let enFormatter = DateIntervalFormatter()
enFormatter.dateStyle = .medium
enFormatter.timeStyle = .none
enFormatter.locale = Locale(identifier: "en_US")
print("إنجليزي: \(enFormatter.string(from: interval))")

DateInterval مقابل DateIntervalFormatter: DateInterval هو هيكل يمثل نطاق تاريخ (بداية ونهاية). DateIntervalFormatter هو منسق يحول هذا الهيكل إلى سلسلة. يدعم DateInterval أيضًا التحقق من contains(Date) وintersection(with:)، وهو مفيد لمنطق الحجز (التحقق من تداخل التواريخ).

توطين فترات التاريخ

DateIntervalFormatter يقوم بتوطين المخرجات من خلال خاصية locale. افتراضيًا، يتم استخدام Locale.current، الإعدادات المحلية للجهاز. لعرض الفترات بلغة أخرى (مثل محتوى إنجليزي مع واجهة عربية)، قم بتعيين locale بشكل صريح. على عكس DateFormatter، لا يتطلب DateIntervalFormatter تعيين locale لبيانات الخادم. فهو دائمًا يستخدم منطق التجميع الداخلي المستند إلى CLDR.

الاختلافات اللغوية في تنسيق فترات التاريخ أكثر تعقيدًا بشكل ملحوظ من التواريخ الفردية. تستخدم العربية حرف الجر «إلى»: من 21 إلى 25 يوليو. تستخدم الإنجليزية شرطة بسيطة: Jul 21–25. تستخدم الفرنسية حرف الجر «au»: du 21 au 25 juillet. تستخدم الألمانية نقطة بعد الرقم وشرطة: 21.–25. Juli. يغطي DateIntervalFormatter كل هذه الاختلافات.

swift
import Foundation

let formatter = DateIntervalFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none

let start = Date()
let end = Date().addingTimeInterval(259200) // +3 أيام
let interval = DateInterval(start: start, end: end)

// عرض إعدادات محلية مختلفة
let localeIds = ["ru_RU", "en_US", "de_DE", "fr_FR", "ja_JP", "zh_CN"]
for localeId in localeIds {
    formatter.locale = Locale(identifier: localeId)
    print("\(localeId): \(formatter.string(from: interval))")
}

// توطين فترات الوقت
formatter.dateStyle = .none
formatter.timeStyle = .short

let todayStart = Date()
let todayEnd = Date().addingTimeInterval(3600)
let timeInterval = DateInterval(start: todayStart, end: todayEnd)

for localeId in ["ru_RU", "en_US", "de_DE"] {
    formatter.locale = Locale(identifier: localeId)
    print("\(localeId) الوقت: \(formatter.string(from: timeInterval))")
}

خصوصيات التوطين: للعربية، يستخدم DateIntervalFormatter حرف الجر «إلى» للصيغ الطويلة. للصيغ القصيرة، يستخدم الشرطة. يعتمد اختيار التنسيق على السياق: لقائمة الحجوزات استخدم .medium، للعرض التفصيلي استخدم .long أو .full.

مقارنة مع منسقات التاريخ الأخرى

DateIntervalFormatter يملأ مجال تنسيق نطاقات التاريخ، الذي لا تغطيه فئات Foundation الأخرى. DateFormatter ينسق التواريخ الفردية، RelativeDateTimeFormatter ينسق التواريخ النسبية (منذ/بعد)، DateComponentsFormatter ينسق المدة (ساعتان 30 دقيقة). كل من هذه الفئات تحل مهمة محددة ولا يمكن استخدامها بالتبادل.

الفئةالغرضمثال الإخراج
DateIntervalFormatterنطاق تاريخ21–25 يوليو 2024
DateFormatterتاريخ فردي21 يوليو 2024
RelativeDateTimeFormatterوقت نسبيمنذ 3 أيام
DateComponentsFormatterمدةساعتان 30 دقيقة
ISO8601DateFormatterتنسيق ISO 86012024-07-21T14:30:00Z

متى تستخدم DateIntervalFormatter: لعرض نطاقات التاريخ في واجهة المستخدم — حجوزات الفنادق، الأحداث، التصفية حسب التواريخ، سجل العمليات. لحساب المدة بين التواريخ، استخدم DateComponentsFormatter وليس DateIntervalFormatter، لأن الأخير غير مصمم لعرض المدة. يجب استخدام DateFormatter فقط للتواريخ الفردية، وليس لدمج تاريخين منسقين عبر تسلسل السلاسل، لأن هذا يؤدي إلى فقدان توطين الفاصل.

حالة طرفية: DateIntervalFormatter لا يدعم عرض الفترات المفتوحة (بدون تاريخ انتهاء). إذا كانت نهاية النطاق غير معروفة (مثل «من 21 يوليو»)، استخدم DateFormatter مع حرف الجر «من». أيضًا، DateIntervalFormatter لا يدعم الفترات مع وقت محدد لأيام مختلفة. يتم تطبيق الوقت على كل تاريخ على حدة، مما قد يبدو زائدًا عن الحاجة للفترات القصيرة.

الأسئلة الشائعة

ما هو DateIntervalFormatter؟

DateIntervalFormatter هي فئة Foundation لتنسيق نطاقات التاريخ في سلاسل مترجمة. متاحة منذ iOS 8، تقوم تلقائيًا بتجميع المكونات المتكررة (الشهر، السنة) واختيار الفاصل الصحيح للغة.

كيف يقوم DateIntervalFormatter بتجميع التواريخ؟

يقوم بمقارنة المكونات من السنة إلى اليوم. إذا تطابقت السنة، تظهر مرة واحدة. إذا تطابق الشهر، يظهر مرة واحدة. الأيام المختلفة تظهر كنطاق. هذا يعطي «21–25 يوليو 2024» بدلاً من «21 يوليو 2024 – 25 يوليو 2024».

هل يمكن تغيير فاصل النطاق؟

لا، يتم تحديد الفاصل بواسطة الإعدادات المحلية ولا يمكن تخصيصه عبر API. لفاصل مخصص (مثل «حتى» بدلاً من «إلى»)، قم بتنسيق كل تاريخ باستخدام DateFormatter منفصل ودمج السلاسل يدويًا.

ما الفرق بين DateIntervalFormatter وDateFormatter؟

DateIntervalFormatter ينسق نطاق تاريخ (تاريخين) كوحدة واحدة مع تجميع المكونات. DateFormatter ينسق تاريخًا فرديًا. للنطاقات، استخدم دائمًا DateIntervalFormatter لأنه يوفر توطينًا صحيحًا للفاصل.

كيف يتم تنسيق فاصل بسنوات مختلفة؟

تلقائيًا — يكتشف DateIntervalFormatter أن السنوات مختلفة ويعرض التواريخ الكاملة لكلا الطرفين: «25 ديسمبر 2024 – 5 يناير 2025». لا يلزم أي تكوين إضافي، فقط قم بتعيين dateStyle.

الملخص

  • DateIntervalFormatter — فئة متخصصة لتنسيق نطاقات التاريخ (iOS 8+)
  • التجميع التلقائي — المكونات المتكررة (السنة، الشهر) تظهر مرة واحدة للنطاق بأكمله
  • فواصل مترجمة — «إلى» (العربية)، «bis» (الألمانية) تلقائيًا
  • أنماط التاريخ والوقت — تركيبات .none, .short, .medium, .long, .full لكل طرف من النطاق
  • ليس للمدة — لحساب المدة استخدم DateComponentsFormatter
  • لا توجد فواصل مخصصة — للحالات غير القياسية يلزم التنسيق اليدوي
  • التكامل مع DateInterval — هيكل DateInterval يوفر عمليات contains وintersection

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

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

اقرأ أيضًا