DateIntervalFormatter — اصول، قالب‌بندی بازه‌های تاریخ

نویسنده: IT Sectr منتشر شده: 2026-07-13 زمان مطالعه: 11 دقیقه

DateIntervalFormatter یک کلاس Foundation در iOS و macOS است که برای قالب‌بندی محدوده‌های تاریخ به رشته‌های بومی‌سازی شده طراحی شده است: «۲۱–۲۵ ژوئیه ۲۰۲۴»، «از ۲۱ تا ۲۵ ژوئیه ۲۰۲۴» یا «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 (محدوده بین دو تاریخ) را دریافت می‌کند و یک رشته بومی‌سازی شده با توضیح این محدوده برمی‌گرداند. به عنوان مثال، برای محدوده ۲۱ تا ۲۵ ژوئیه ۲۰۲۴، نتیجه برای fa_IR «۲۱–۲۵ ژوئیه ۲۰۲۴» و برای en_US «Jul 21–25, 2024» خواهد بود. این کلاس عناصر تکراری را هوشمندانه گروه‌بندی می‌کند: اگر هر دو تاریخ در یک ماه باشند، نام ماه یک بار نمایش داده می‌شود.

ارزش اصلی DateIntervalFormatter پردازش خودکار گرامر بازه‌ها است. در قالب‌بندی دستی، برنامه‌نویس باید ماه/سال شروع و پایان را مقایسه کند، جداکننده (خط تیره، «تا»، «to»، «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 بر اساس تجزیه و تحلیل دو تاریخ تشکیل‌دهنده بازه و انتخاب نمایش متنی بهینه با در نظر گرفتن locale است. کلاس اجزای تاریخ (سال، ماه، روز) را مقایسه کرده و درباره گروه‌بندی تصمیم می‌گیرد: اگر سال یکسان است — یک بار نمایش داده می‌شود؛ اگر ماه یکسان است — یک بار نمایش داده می‌شود؛ اگر روزها متفاوت هستند — محدوده روزها نمایش داده می‌شود.

بازهfa_IRen_US
یک روز۲۱ ژوئیه ۲۰۲۴Jul 21, 2024
داخل یک ماه۲۱–۲۵ ژوئیه ۲۰۲۴Jul 21–25, 2024
ماه‌های مختلف۲۱ ژوئیه – ۵ اوت ۲۰۲۴Jul 21 – Aug 5, 2024
سال‌های مختلف۲۵ دسامبر ۲۰۲۴ – ۵ ژانویه ۲۰۲۵Dec 25, 2024 – Jan 5, 2025
با زمان۲۱ ژوئیه ۲۰۲۴، ۱۴:۳۰–۱۶:۴۵Jul 21, 2024, 2:30–4:45 PM

منطق گروه‌بندی بر اساس الگوهای CLDR پیاده‌سازی شده است. قالب‌بند برابری هر جزء تاریخ (Calendar.Component: year, month, day) را به ترتیب از بزرگ به کوچک بررسی می‌کند. به محض اینکه جزئی متفاوت شد، تمام اجزای کوچک‌تر برای هر دو تاریخ نمایش داده می‌شوند. به عنوان مثال، برای ۲۱–۲۵ ژوئیه: سال مطابقت دارد، ماه مطابقت دارد، روز متفاوت است → ماه یک بار، روزها برای هر تاریخ جداگانه نمایش داده می‌شوند.

نکته مهم: DateIntervalFormatter از تنظیم جداکننده از طریق API پشتیبانی نمی‌کند. جداکننده توسط locale تعیین می‌شود و قابل بازنویسی نیست. اگر جداکننده سفارشی مورد نیاز است (مثلاً «الی» به جای «تا»)، باید تاریخ‌ها را به صورت دستی از طریق DateFormatter قالب‌بندی کرده و رشته‌ها را با جداکننده سفارشی بچسبانید.

سبک‌های قالب‌بندی بازه‌ها

DateIntervalFormatter دو مجموعه سبک ارائه می‌دهد: dateStyle و timeStyle — برای هر انتهای بازه. این سبک‌ها مشابه DateFormatter کار می‌کنند: .none جزء را پنهان می‌کند، .short فرمت کوتاه می‌دهد (۲۱.۰۷.۲۰۲۴)، .medium — متوسط (۲۱ ژوئیه ۲۰۲۴)، .long — کامل (۲۱ ژوئیه ۲۰۲۴)، .full — حداکثر جزئیات (یکشنبه، ۲۱ ژوئیه ۲۰۲۴). با ترکیب dateStyle و timeStyle می‌توان سطوح مختلف جزئیات را به دست آورد.

مثال‌هایی از ترکیب سبک‌ها

  • dateStyle = .medium, timeStyle = .none — فقط تاریخ: «۲۱–۲۵ ژوئیه ۲۰۲۴»
  • dateStyle = .short, timeStyle = .short — تاریخ و زمان: «۲۱.۰۷.۲۰۲۴، ۱۴:۳۰ – ۲۵.۰۷.۲۰۲۴، ۱۶:۴۵»
  • dateStyle = .none, timeStyle = .short — فقط زمان: «۱۴:۳۰–۱۶:۴۵» (اگر تاریخ‌ها یکسان باشند)
  • dateStyle = .long, timeStyle = .none — تاریخ طولانی: «۲۱–۲۵ ژوئیه ۲۰۲۴»
  • dateStyle = .full, timeStyle = .short — فرمت کامل: «یکشنبه، ۲۱ ژوئیه ۲۰۲۴ – چهارشنبه، ۲۵ ژوئیه ۲۰۲۴»

مهم: dateStyle و timeStyle به طور یکسان برای هر دو انتهای بازه اعمال می‌شوند. نمی‌توان سبک متفاوتی برای شروع و پایان تنظیم کرد (مثلاً .medium برای شروع و .short برای پایان). اگر سبک متفاوت مورد نیاز است، باید هر تاریخ را با DateFormatter جداگانه قالب‌بندی کرده و نتایج را بچسبانید.

swift
import Foundation

let formatter = DateIntervalFormatter()

// ترکیب‌های مختلف سبک‌ها
let startDate = Date()
let endDate = Date().addingTimeInterval(345600) // +۴ روز
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+) ایجاد کرد. پس از قالب‌بندی، نتیجه بدون پردازش اضافی برای نمایش در UI آماده است.

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 و Calendar Booking: در برنامه‌های رزرو (هتل‌ها، بلیط‌ها) بازه‌های تاریخ یک عنصر کلیدی UI هستند. DateIntervalFormatter بازه‌های بین‌سالی را به درستی پردازش می‌کند (مثلاً از ۲۸ دسامبر تا ۳ ژانویه)، ماه و سال را برای هر تاریخ جداگانه گروه‌بندی می‌کند. برای چنین سناریوهایی توصیه می‌شود از 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)")

// استفاده با locale‌های مختلف
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 دستگاه استفاده می‌شود. برای نمایش بازه‌ها به زبان دیگر (مثلاً محتوای انگلیسی در رابط فارسی)، locale را به صراحت تنظیم کنید. برخلاف DateFormatter، DateIntervalFormatter برای داده‌های سرور نیاز به تنظیم Locale ندارد — همیشه از منطق گروه‌بندی داخلی خود مبتنی بر CLDR استفاده می‌کند.

تفاوت‌های زبانی در قالب‌بندی بازه‌های تاریخ بسیار پیچیده‌تر از تاریخ‌های تکی است. انگلیسی از خط تیره ساده استفاده می‌کند: Jul 21–25. فارسی — از حرف اضافه «تا»: از ۲۱ تا ۲۵ ژوئیه. فرانسوی — از «au»: du 21 au 25 juillet. آلمانی — از نقطه بعد از عدد و خط تیره: 21.–25. Juli. ژاپنی — از خط فاصله بدون حرف اضافه: Jul 21–25. DateIntervalFormatter همه این گزینه‌ها را پوشش می‌دهد.

swift
import Foundation

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

let start = Date()
let end = Date().addingTimeInterval(259200) // +۳ روز
let interval = DateInterval(start: start, end: end)

// نمایش locale‌های مختلف
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 از حروف اضافه «از» و «تا» برای فرمت‌های طولانی تاریخ استفاده می‌کند. برای فرمت کوتاه (short) — فقط خط تیره: ۲۱.۰۷–۲۵.۰۷.۲۰۲۴. برای فرمت کامل (full) — با ذکر روز هفته. انتخاب فرمت به زمینه بستگی دارد: برای لیست رزروها از .medium، برای نمای جزئیات از .long یا .full استفاده کنید.

مقایسه با سایر قالب‌بندهای تاریخ

DateIntervalFormatter جایگاه قالب‌بندی بازه‌های تاریخ را پر می‌کند که کلاس‌های دیگر Foundation پوشش نمی‌دهند. DateFormatter تاریخ‌های تکی، RelativeDateTimeFormatter — تاریخ‌های نسبی (پیش/بعد)، DateComponentsFormatter — مدت زمان (۲ ساعت ۳۰ دقیقه) را قالب‌بندی می‌کند. هر یک از این کلاس‌ها مسئله خود را حل می‌کنند و نمی‌توان آنها را جایگزین یکدیگر کرد.

کلاسهدفنمونه خروجی
DateIntervalFormatterمحدوده تاریخ۲۱–۲۵ ژوئیه ۲۰۲۴
DateFormatterتاریخ تکی۲۱ ژوئیه ۲۰۲۴
RelativeDateTimeFormatterزمان نسبی۳ روز پیش
DateComponentsFormatterمدت زمان۲ ساعت ۳۰ دقیقه
ISO8601DateFormatterفرمت ISO 8601۲۰۲۴-۰۷-۲۱T۱۴:۳۰:۰۰Z

چه زمانی از DateIntervalFormatter استفاده کنیم: برای نمایش بازه‌های تاریخ در UI — رزرو هتل، رویدادها، فیلتر بر اساس تاریخ، تاریخچه عملیات. برای محاسبه مدت زمان بین تاریخ‌ها از DateComponentsFormatter استفاده کنید، نه DateIntervalFormatter — دومی برای نمایش مدت زمان طراحی نشده است. DateFormatter را فقط برای تاریخ‌های تکی استفاده کنید، نه برای چسباندن دو تاریخ قالب‌بندی شده از طریق الحاق رشته — این منجر به از دست رفتن بومی‌سازی جداکننده می‌شود.

لبه: DateIntervalFormatter از نمایش بازه‌های باز (بدون تاریخ پایان) پشتیبانی نمی‌کند. اگر پایان بازه نامشخص است (مثلاً «از ۲۱ ژوئیه»)، برای فارسی از DateFormatter با حرف اضافه «از» استفاده کنید. DateIntervalFormatter همچنین از بازه‌های با ذکر زمان برای روزهای مختلف پشتیبانی نمی‌کند — زمان برای هر تاریخ جداگانه اعمال می‌شود که ممکن است برای بازه‌های کوتاه اضافی به نظر برسد.

سوالات متداول

DateIntervalFormatter چیست؟

DateIntervalFormatter — کلاس Foundation برای قالب‌بندی محدوده‌های تاریخ به رشته‌های بومی‌سازی شده. از iOS 8 در دسترس است، به طور خودکار اجزای تکراری (ماه، سال) را گروه‌بندی می‌کند و جداکننده مناسب زبان را انتخاب می‌کند.

DateIntervalFormatter چگونه تاریخ‌ها را گروه‌بندی می‌کند؟

اجزا را مقایسه می‌کند از سال تا روز. اگر سال مطابقت دارد — یک بار نمایش داده می‌شود. اگر ماه مطابقت دارد — یک بار نمایش داده می‌شود. روزهای متفاوت به عنوان بازه نمایش داده می‌شوند. این باعث می‌شود «۲۱–۲۵ ژوئیه ۲۰۲۴» به جای «۲۱ ژوئیه ۲۰۲۴ – ۲۵ ژوئیه ۲۰۲۴».

آیا می‌توان جداکننده بازه را تغییر داد؟

خیر، جداکننده توسط locale تعیین می‌شود و از طریق API قابل تنظیم نیست. برای جداکننده سفارشی (مثلاً «الی» به جای «تا»)، هر تاریخ را با DateFormatter جداگانه قالب‌بندی کرده و رشته‌ها را به صورت دستی بچسبانید.

تفاوت DateIntervalFormatter با DateFormatter چیست؟

DateIntervalFormatter یک بازه تاریخ (دو تاریخ) را به عنوان یک کل واحد با گروه‌بندی اجزا قالب‌بندی می‌کند. DateFormatter یک تاریخ تکی را قالب‌بندی می‌کند. برای بازه‌ها همیشه از DateIntervalFormatter استفاده کنید — این بومی‌سازی صحیح جداکننده را تضمین می‌کند.

چگونه یک بازه با سال‌های مختلف را قالب‌بندی کنیم؟

به طور خودکار — DateIntervalFormatter تشخیص می‌دهد که سال‌ها متفاوت هستند و تاریخ‌های کامل را برای هر دو انتها نمایش می‌دهد: «۲۵ دسامبر ۲۰۲۴ – ۵ ژانویه ۲۰۲۵». هیچ تنظیم اضافی لازم نیست، فقط کافی است dateStyle تنظیم شود.

خلاصه

  • DateIntervalFormatter — کلاس تخصصی برای قالب‌بندی بازه‌های تاریخ (iOS 8+)
  • گروه‌بندی خودکار — اجزای تکراری (سال، ماه) یک بار برای کل بازه نمایش داده می‌شوند
  • جداکننده‌های بومی‌سازی شده — «تا» (فارسی)، خط تیره (انگلیسی)، «bis» (آلمانی) — به طور خودکار
  • سبک‌های تاریخ و زمان — ترکیب‌های .none، .short، .medium، .long، .full برای هر انتهای بازه
  • مناسب برای مدت زمان نیست — برای محاسبه مدت زمان از DateComponentsFormatter استفاده کنید
  • از جداکننده‌های سفارشی پشتیبانی نمی‌کند — برای موارد غیراستاندارد نیاز به قالب‌بندی دستی است
  • ادغام با DateInterval — ساختار DateInterval بررسی contains و intersection را فراهم می‌کند

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید