DateIntervalFormatter adalah kelas Foundation di iOS dan macOS yang dirancang untuk memformat rentang tanggal menjadi string yang dilokalkan: “21–25 Juli 2024”, “dari 21 hingga 25 Juli 2024” atau “Jul 21–25, 2024”. Menurut Apple Developer Documentation, 2024, DateIntervalFormatter secara otomatis menentukan komponen tanggal mana yang akan diulang (jika rentang dalam satu bulan — bulan ditampilkan sekali) dan melokalkan pemisah serta urutan kata. Tidak seperti penggabungan manual dua tanggal yang diformat, kelas ini memperhitungkan aturan tata bahasa: untuk Bahasa Indonesia — kata depan “hingga”, untuk bahasa Inggris — tanda hubung tanpa kata depan. Kelas ini tersedia sejak iOS 8 dan macOS 10.10.
Poin utama
DateIntervalFormatter adalah subclass dari Formatter di Foundation yang menerima objek DateInterval (rentang antara dua tanggal) dan mengembalikan string yang dilokalkan dengan deskripsi rentang ini. Misalnya, untuk rentang 21 hingga 25 Juli 2024, hasilnya akan menjadi “21–25 Juli 2024” untuk id_ID dan “Jul 21–25, 2024” untuk en_US. Kelas ini dengan cerdas mengelompokkan elemen berulang: jika kedua tanggal berada di bulan yang sama, nama bulan ditampilkan sekali.
Nilai utama DateIntervalFormatter adalah pemrosesan otomatis tata bahasa rentang. Dalam pemformatan manual, pengembang harus membandingkan bulan/tahun awal dan akhir, memilih pemisah (tanda hubung, “dari–hingga”, “to”, “bis”) dan memantau deklinasi. DateIntervalFormatter melakukan ini secara otomatis berdasarkan data CLDR (Common Locale Data Repository), yang mengurangi jumlah bug dalam aplikasi internasional, terutama untuk bahasa dengan tata bahasa yang kompleks.
Menurut Unicode CLDR v44 (2024), aturan pemformatan rentang tanggal sangat bervariasi antar bahasa. Bahasa Jerman menggunakan kata depan “bis” (21.–25. Juli 2024), Perancis — “au” (du 21 au 25 juillet 2024), Jepang — melalui tanda hubung (2024 Jul 21–25). DateIntervalFormatter mencakup semua variasi ini tanpa kode tambahan dari pengembang.
Prinsip kerja DateIntervalFormatter didasarkan pada analisis dua tanggal yang membentuk rentang dan pemilihan representasi teks optimal dengan mempertimbangkan locale. Kelas membandingkan komponen tanggal (tahun, bulan, hari) dan membuat keputusan tentang pengelompokan: jika tahun sama — ditampilkan sekali; jika bulan sama — ditampilkan sekali; jika hari berbeda — rentang hari ditampilkan.
| Rentang | id_ID | en_US |
|---|---|---|
| Satu hari | 21 Juli 2024 | Jul 21, 2024 |
| Dalam satu bulan | 21–25 Juli 2024 | Jul 21–25, 2024 |
| Bulan berbeda | 21 Juli – 5 Agustus 2024 | Jul 21 – Aug 5, 2024 |
| Tahun berbeda | 25 Desember 2024 – 5 Januari 2025 | Dec 25, 2024 – Jan 5, 2025 |
| Dengan waktu | 21 Juli 2024, 14:30–16:45 | Jul 21, 2024, 2:30–4:45 PM |
Logika pengelompokan diimplementasikan berdasarkan pola CLDR. Pemformat memeriksa kesetaraan setiap komponen tanggal (Calendar.Component: year, month, day) dalam urutan dari terbesar ke terkecil. Segera setelah komponen berbeda, semua komponen yang lebih kecil ditampilkan untuk kedua tanggal. Misalnya, untuk 21–25 Juli: tahun cocok, bulan cocok, hari berbeda → bulan sekali, hari — untuk setiap tanggal secara terpisah.
Nuansa penting: DateIntervalFormatter tidak mendukung konfigurasi pemisah melalui API. Pemisah ditentukan oleh locale dan tidak dapat ditimpa. Jika diperlukan pemisah khusus (misalnya, “sampai dengan” alih-alih “–”), Anda harus memformat tanggal secara manual melalui DateFormatter dan menggabungkan string dengan pemisah khusus.
DateIntervalFormatter menyediakan dua set gaya: dateStyle dan timeStyle — untuk setiap ujung rentang. Gaya-gaya ini bekerja mirip dengan DateFormatter: .none menyembunyikan komponen, .short memberikan format pendek (21.07.2024), .medium — sedang (21 Jul 2024), .long — panjang (21 Juli 2024), .full — sangat detail (Minggu, 21 Juli 2024). Dengan menggabungkan dateStyle dan timeStyle, tingkat detail yang berbeda dapat diperoleh.
Penting: dateStyle dan timeStyle diterapkan secara sama ke kedua ujung rentang. Tidak dapat mengatur gaya berbeda untuk awal dan akhir (misalnya, .medium untuk awal dan .short untuk akhir). Jika diperlukan gaya berbeda, Anda harus memformat setiap tanggal dengan DateFormatter terpisah dan menggabungkan hasilnya.
import Foundation
let formatter = DateIntervalFormatter()
// Kombinasi gaya berbeda
let startDate = Date()
let endDate = Date().addingTimeInterval(345600) // +4 hari
let interval = DateInterval(start: startDate, end: endDate)
// Hanya tanggal, format sedang
formatter.dateStyle = .medium
formatter.timeStyle = .none
print("Hanya tanggal: \(formatter.string(from: interval))")
// Format pendek dengan waktu
formatter.dateStyle = .short
formatter.timeStyle = .short
print("Pendek dengan waktu: \(formatter.string(from: interval))")
// Format lengkap
formatter.dateStyle = .full
formatter.timeStyle = .none
print("Tanggal lengkap: \(formatter.string(from: interval))")
Penggunaan dasar DateIntervalFormatter mencakup pembuatan instance, konfigurasi gaya, dan pemanggilan string(from:). Metode ini menerima DateInterval — struktur dengan properti start dan end. DateInterval dapat dibuat dari dua Date, maupun diinisialisasi dengan Duration (iOS 16+). Setelah pemformatan, hasilnya siap ditampilkan di UI tanpa pemrosesan tambahan.
import Foundation
let calendar = Calendar.current
let now = Date()
// Contoh interval spesifik
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)")
}
// Pemformatan melalui Calendar (iOS 16+)
if let nextWeek = calendar.date(
byAdding: .day, value: 7, to: now
) {
let weekInterval = DateInterval(start: now, end: nextWeek)
print("7 hari berikutnya: \(intervalFormatter.string(from: weekInterval))")
}
DateIntervalFormatter dan Calendar Booking: dalam aplikasi pemesanan (hotel, tiket) rentang tanggal adalah elemen kunci UI. DateIntervalFormatter memproses rentang antar-tahun dengan benar (misalnya, dari 28 Desember hingga 3 Januari), mengelompokkan bulan dan tahun untuk setiap tanggal secara terpisah. Untuk skenario seperti itu, disarankan menggunakan dateStyle = .medium dan timeStyle = .none — format paling mudah dibaca untuk tanggal tanpa waktu.
import Foundation
let formatter = DateIntervalFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .none
// Contoh pemesanan
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("Pemesanan: \(booking.formattedInterval)")
// Penggunaan dengan locale berbeda
let enFormatter = DateIntervalFormatter()
enFormatter.dateStyle = .medium
enFormatter.timeStyle = .none
enFormatter.locale = Locale(identifier: "en_US")
print("Inggris: \(enFormatter.string(from: interval))")
DateInterval vs DateIntervalFormatter: DateInterval — struktur yang mewakili rentang tanggal (awal dan akhir). DateIntervalFormatter — pemformat yang mengubah struktur ini menjadi string. DateInterval juga mendukung pemeriksaan contains(Date) dan intersection(with:), yang berguna untuk logika pemesanan (memeriksa tumpang tindih tanggal).
DateIntervalFormatter melokalkan keluaran melalui properti locale. Secara default, Locale.current digunakan — locale perangkat. Untuk menampilkan interval dalam bahasa lain (misalnya, konten Inggris di antarmuka Indonesia), atur locale secara eksplisit. Tidak seperti DateFormatter, DateIntervalFormatter tidak memerlukan pengaturan Locale untuk data server — selalu menggunakan logika pengelompokan internalnya sendiri yang didasarkan pada CLDR.
Perbedaan bahasa dalam pemformatan rentang tanggal secara signifikan lebih kompleks daripada untuk tanggal tunggal. Bahasa Inggris menggunakan tanda hubung sederhana: Jul 21–25. Bahasa Indonesia — kata depan “dari–hingga”: dari 21 hingga 25 Juli. Bahasa Perancis — kata depan “au”: du 21 au 25 juillet. Bahasa Jerman — titik setelah angka dan tanda hubung: 21.–25. Juli. Bahasa Jepang — melalui tanda hubung tanpa kata depan: Jul 21–25. DateIntervalFormatter mencakup semua varian ini.
import Foundation
let formatter = DateIntervalFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
let start = Date()
let end = Date().addingTimeInterval(259200) // +3 hari
let interval = DateInterval(start: start, end: end)
// Demonstrasi locale berbeda
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))")
}
// Lokalisasi untuk interval waktu
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) waktu: \(formatter.string(from: timeInterval))")
}
Fitur lokalisasi: untuk Bahasa Indonesia, DateIntervalFormatter menggunakan kata depan “dari” dan “hingga” untuk format tanggal panjang. Untuk format pendek (short) — hanya tanda hubung: 21.07–25.07.2024. Untuk format lengkap (full) — dengan menyebutkan hari dalam seminggu. Pemilihan format tergantung pada konteks: untuk daftar pemesanan gunakan .medium, untuk tampilan detail — .long atau .full.
DateIntervalFormatter mengisi ceruk pemformatan rentang tanggal yang tidak dicakup oleh kelas Foundation lainnya. DateFormatter memformat tanggal tunggal, RelativeDateTimeFormatter — tanggal relatif (lalu/depan), DateComponentsFormatter — durasi (2 jam 30 menit). Masing-masing kelas ini menyelesaikan tugasnya sendiri dan tidak dapat saling menggantikan.
| Kelas | Tujuan | Contoh keluaran |
|---|---|---|
| DateIntervalFormatter | Rentang tanggal | 21–25 Juli 2024 |
| DateFormatter | Tanggal tunggal | 21 Juli 2024 |
| RelativeDateTimeFormatter | Waktu relatif | 3 hari lalu |
| DateComponentsFormatter | Durasi | 2 jam 30 menit |
| ISO8601DateFormatter | Format ISO 8601 | 2024-07-21T14:30:00Z |
Kapan menggunakan DateIntervalFormatter: untuk menampilkan rentang tanggal di UI — pemesanan hotel, acara, pemfilteran berdasarkan tanggal, riwayat operasi. Untuk menghitung durasi antara tanggal gunakan DateComponentsFormatter, bukan DateIntervalFormatter — yang terakhir tidak dirancang untuk menampilkan durasi. DateFormatter hanya boleh digunakan untuk tanggal tunggal, bukan untuk menggabungkan dua tanggal yang diformat melalui penggabungan string — ini menyebabkan hilangnya lokalisasi pemisah.
Kasus tepi: DateIntervalFormatter tidak mendukung tampilan rentang terbuka (tanpa tanggal akhir). Jika akhir rentang tidak diketahui (misalnya, “dari 21 Juli”), gunakan DateFormatter dengan kata depan “dari” untuk Bahasa Indonesia atau “from” untuk bahasa Inggris. DateIntervalFormatter juga tidak mendukung rentang dengan penyebutan waktu untuk hari yang berbeda — waktu diterapkan pada setiap tanggal secara terpisah, yang mungkin tampak berlebihan untuk rentang pendek.
Pertanyaan yang sering diajukan
DateIntervalFormatter — kelas Foundation untuk memformat rentang tanggal menjadi string yang dilokalkan. Tersedia sejak iOS 8, secara otomatis mengelompokkan komponen berulang (bulan, tahun) dan memilih pemisah yang tepat untuk bahasa.
Membandingkan komponen dari tahun ke hari. Jika tahun cocok — ditampilkan sekali. Jika bulan cocok — ditampilkan sekali. Hari yang berbeda ditampilkan sebagai rentang. Ini memberikan “21–25 Juli 2024” alih-alih “21 Juli 2024 – 25 Juli 2024”.
Tidak, pemisah ditentukan oleh locale dan tidak dapat dikonfigurasi melalui API. Untuk pemisah khusus (misalnya, “sampai dengan” alih-alih “–”), format setiap tanggal dengan DateFormatter terpisah dan gabungkan string secara manual.
DateIntervalFormatter memformat rentang tanggal (dua tanggal) sebagai satu kesatuan dengan pengelompokan komponen. DateFormatter memformat satu tanggal. Untuk rentang selalu gunakan DateIntervalFormatter — ini memastikan lokalisasi pemisah yang benar.
Secara otomatis — DateIntervalFormatter mendeteksi bahwa tahun berbeda dan menampilkan tanggal lengkap untuk kedua ujung: “25 Desember 2024 – 5 Januari 2025”. Tidak diperlukan pengaturan tambahan, cukup atur dateStyle.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga