DateFormatter: konsep kunci, pemformatan tanggal dan lokalisasi

Penulis: IT Sectr Diterbitkan: 2026-07-12 Waktu membaca: 7 mnt

DateFormatter — kelas Foundation yang dirancang untuk konversi dua arah antara objek Date dan representasi stringnya. Kelas ini mempertimbangkan locale, zona waktu, dan kalender pengguna, memastikan tampilan tanggal yang benar di wilayah mana pun di dunia. Menurut Apple Developer Documentation (2025), DateFormatter mendukung empat gaya tanggal dan waktu yang telah ditentukan sebelumnya, serta format yang sepenuhnya khusus melalui string pola. Tanpa DateFormatter, tidak mungkin menampilkan tanggal dengan benar kepada pengguna dalam aplikasi yang diinternasionalisasi.

Utama

  • DateFormatter — kelas untuk konversi Date ke string dan sebaliknya dengan mempertimbangkan locale dan zona waktu.
  • dateStyle dan timeStyle — gaya yang telah ditentukan sebelumnya (.short, .medium, .long, .full) untuk pemformatan cepat.
  • dateFormat — string pola untuk format kustom, ditentukan melalui simbol spesifikasi Unicode LDML.
  • Locale dan TimeZone — properti formatter yang menentukan tampilan regional dan zona waktu.
  • ISO8601DateFormatter — alternatif yang lebih cepat untuk format ISO 8601 saat serialisasi di API.

Apa itu DateFormatter?

DateFormatter — kelas dari framework Foundation yang mengimplementasikan konversi dua arah antara Date dan string. Ini muncul di OpenStep sebagai NSDateFormatter dan sejak itu tetap menjadi alat utama pemformatan tanggal di semua platform Apple. Kelas ini mewarisi dari Formatter dan menyediakan API yang nyaman untuk tampilan tanggal yang dilokalisasi.

Prinsip kerja DateFormatter didasarkan pada pola Unicode LDML — yang sama digunakan di ICU (International Components for Unicode). Pola ditentukan melalui properti dateFormat, di mana simbol y, M, d, H, m, s masing-masing sesuai dengan tahun, bulan, hari, jam, menit, dan detik. Pengulangan simbol menentukan format: “y” — tahun dua digit, “yyyy” — empat digit.

Membuat DateFormatter adalah operasi yang mahal, karena saat inisialisasi data locale dan kalender dimuat. Apple merekomendasikan untuk membuat formatter sekali untuk setiap jenis pemformatan dan menggunakannya kembali. Di SwiftUI dan UIKit, formatter sering di-cache di properti statis atau dibuat secara malas saat pertama kali diakses.

DateFormatter di iOS SDK

DateFormatter digunakan di banyak komponen sistem iOS. UIDatePicker secara internal menggunakan DateFormatter untuk menampilkan tanggal dalam mode countDownTimer. TextField dengan formatter di input dapat secara otomatis memvalidasi tanggal yang dimasukkan pengguna. Core Data mendukung atribut tipe Date, tetapi tampilan stringnya selalu dilakukan melalui DateFormatter.

Thread Safety — DateFormatter tidak aman untuk thread. Mengubah properti formatter dari thread yang berbeda menyebabkan perilaku yang tidak terdefinisi. Untuk penggunaan multi-thread, buat instance formatter terpisah untuk setiap thread atau gunakan sinkronisasi melalui NSLock atau serial queue.

Gaya pemformatan DateFormatter

dateStyle dan timeStyle — cara paling sederhana untuk mengatur tampilan tanggal. Setiap gaya memiliki empat varian: .short, .medium, .long, .full. Kombinasi dateStyle dan timeStyle memungkinkan konfigurasi format tanggal dan waktu secara independen, dan properti .none menonaktifkan bagian yang sesuai.

Untuk locale Amerika, gaya .short memformat tanggal sebagai “7/21/26”, dan untuk Indonesia — sebagai “21/07/2026”. Gaya .long untuk locale Indonesia menampilkan “21 Juli 2026”, dan .full — “Selasa, 21 Juli 2026” dengan menyebutkan hari dalam seminggu. Keempat gaya secara otomatis menyesuaikan dengan standar regional, termasuk urutan komponen dan pemisah.

RelativeDateFormatter di iOS 15+ menawarkan pendekatan alternatif melalui RelativeDateFormatter dan DateIntervalFormatter. RelativeDateFormatter menampilkan “hari ini”, “kemarin”, “3 hari lagi” untuk konteks saat ini. DateIntervalFormatter menampilkan rentang tanggal: “21–25 Juli 2026” — untuk pemesanan dan perencanaan.

GayaContoh (id_ID)Contoh (en_US)
.short21/07/20267/21/26
.medium21 Jul 2026Jul 21, 2026
.long21 Juli 2026July 21, 2026
.fullSelasa, 21 Juli 2026Tuesday, July 21, 2026

Saat menggabungkan gaya, DateFormatter secara otomatis memilih pemisah: untuk .short.date + .short.time hasilnya mungkin “21/07/2026, 14:30”. Untuk .full.date + .full.time — “Selasa, 21 Juli 2026, 14:30:00 MSK”. Pemisah dikendalikan oleh locale, bukan pengembang — ini menjamin kesesuaian dengan harapan regional pengguna.

Format kustom melalui dateFormat

dateFormat memungkinkan Anda menentukan pola pemformatan arbitrer menggunakan simbol spesifikasi Unicode LDML. Ini memberikan kontrol penuh atas tampilan: Anda dapat menampilkan hanya tahun dan bulan, hari dalam seminggu tanpa angka, atau waktu tanpa detik. Format kustom sangat diperlukan untuk kebutuhan desain tertentu.

Simbol dasar — yyyy (tahun: 2026), MM (bulan: 07), dd (hari: 21), HH (jam: 14), mm (menit: 30), ss (detik: 00). Untuk nama bulan lengkap gunakan MMMM (Juli), untuk singkatan — MMM (Jul). Hari dalam seminggu — EEEE (Selasa), singkatan — E (Sel).

Saat menggunakan dateFormat, penting untuk mengatur locale formatter. Jika locale tidak diatur, formatter menggunakan locale sistem, yang mungkin tidak diinginkan untuk format tetap di API. Apple merekomendasikan pengaturan locale = Locale(identifier: “en_US_POSIX”) untuk format antar-regional yang tetap, terutama saat menguraikan tanggal dari respons server.

swift
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU")
formatter.dateFormat = "d MMMM yyyy"
let customString = formatter.string(from: Date())
// "21 July 2026"

// Parsing string khusus
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = formatter.date(from: "2026-07-21 14:30:00")!

Kesalahan di dateFormat — salah satu penyebab umum crash aplikasi. Jika format tidak cocok dengan string, metode date(from:) mengembalikan nil. Gunakan guard let atau ?? untuk mengekstrak nilai opsional dengan aman. Untuk validasi format, uji pada semua bahasa yang didukung — beberapa simbol LDML bekerja berbeda di locale yang berbeda.

Lokalisasi dan TimeZone

Locale menentukan bagaimana nama bulan, hari dalam seminggu, dan pemisah ditampilkan. DateFormatter secara default menggunakan Locale.current, tetapi dalam beberapa skenario diperlukan penentuan locale tertentu: untuk format tetap di log gunakan en_US_POSIX, untuk tanggal server — locale yang identik dengan server.

Properti TimeZone menentukan zona waktu untuk tampilan. Secara default, zona waktu sistem digunakan, tetapi untuk aplikasi dengan audiens internasional sering diperlukan menampilkan tanggal di zona waktu pengguna atau di UTC. Mengubah timeZone hanya memengaruhi tampilan — nilai Date tetap tidak berubah.

Fitur penting: jika DateFormatter digunakan untuk mengurai string, dan string berisi indikasi zona waktu (misalnya, “2026-07-21T14:30:00Z” dengan Z untuk UTC), properti timeZone diabaikan — formatter menggunakan zona waktu dari string. Jika zona waktu tidak ada dalam string, timeZone formatter yang diterapkan.

swift
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU")
formatter.timeZone = TimeZone(identifier: "Europe/Moscow")
formatter.dateStyle = .long
formatter.timeStyle = .short

let moscowTime = formatter.string(from: Date())
// "21 July 2026, 14:30"

// Parsing tanpa zona waktu dalam string
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd HH:mm"
let utcDate = formatter.date(from: "2026-07-21 10:30")!

AutoupdatingCurrentLocale — tipe locale khusus yang secara otomatis diperbarui saat pengaturan sistem pengguna berubah. DateFormatter mendukungnya secara default. Jika aplikasi berjalan di latar belakang dan pengguna mengubah bahasa sistem, formatter yang dibuat sebelum perubahan akan terus menggunakan locale lama — untuk pembaruan perlu membuat instance baru.

ISO8601DateFormatter dan alternatif

ISO8601DateFormatter — formatter khusus untuk bekerja dengan tanggal dalam format ISO 8601. Format ini adalah standar de facto untuk REST API, JSON, dan pertukaran data. ISO8601DateFormatter bekerja jauh lebih cepat daripada DateFormatter karena tidak bergantung pada locale dan menggunakan tata bahasa parsing yang tetap.

Opsi utama formatter — .withInternetDateTime (2026-07-21T14:30:00Z), .withFractionalSeconds (menambahkan milidetik), .withTimeZone (menyertakan offset zona waktu). Dengan menggabungkan opsi, Anda bisa mendapatkan varian ISO 8601 apa pun: dengan milidetik, dengan zona waktu, dengan tanggal tanpa waktu.

JSONEncoder.DateEncodingStrategy memungkinkan Anda mengonfigurasi pengkodean tanggal secara global untuk semua model Codable. Varian — .iso8601 (menggunakan ISO8601DateFormatter), .formatted(DateFormatter), .millisecondsSince1970, .secondsSince1970. Pemilihan strategi memengaruhi seluruh siklus hidup serialisasi dan harus seragam untuk semua endpoint API.

swift
// ISO8601DateFormatter
let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let isoString = isoFormatter.string(from: Date())
// "2026-07-21T14:30:00.000Z"

// JSONEncoder dengan ISO8601
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601

// Alternatif: JSONEncoder dengan formatter khusus
let customEncoder = JSONEncoder()
customEncoder.dateEncodingStrategy = .formatted(myFormatter)

DateFormatter vs ISO8601DateFormatter — pilih ISO8601DateFormatter untuk serialisasi dan parsing tanggal di API, karena bekerja 5-10 kali lebih cepat daripada DateFormatter dan tidak rentan terhadap kesalahan lokalisasi. Biarkan DateFormatter untuk antarmuka pengguna, di mana tampilan yang dilokalisasi dengan nama bulan dan hari dalam seminggu dalam bahasa ibu pengguna diperlukan.

Contoh pemformatan tanggal

Mari kita pertimbangkan skenario nyata penggunaan DateFormatter di aplikasi iOS: menampilkan di daftar berita, memasukkan tanggal lahir, dan mengekspor laporan dengan tanggal di zona waktu berbeda.

Menampilkan tanggal berita di daftar

RelativeDateFormatter optimal untuk feed berita. Ini menampilkan “baru saja”, “5 menit yang lalu”, “kemarin” untuk berita terbaru dan beralih ke tanggal lengkap untuk yang lama. Ambang peralihan dikonfigurasi melalui calendar: untuk berita gunakan ambang 24 jam, untuk messenger — seminggu.

swift
func formatRelativeDate(_ date: Date) -> String {
    let relative = RelativeDateFormatter()
    relative.unitsStyle = .full

    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    formatter.timeStyle = .short

    let daysDiff = Calendar.current.dateComponents(
        [.day], from: date, to: Date()
    ).day ?? 0

    return daysDiff < 1
        ? relative.localizedString(for: date, relativeTo: Date())
        : formatter.string(from: date)
}

Memasukkan tanggal lahir — skenario umum lainnya. DateFormatter dikonfigurasi dengan dateFormat tertentu “dd/MM/yyyy” dan locale “id_ID”. Saat mengurai string yang dimasukkan, penting untuk menangani kemungkinan kesalahan: formatter mengembalikan nil untuk string yang salah. Setelah parsing berhasil, tanggal diperiksa apakah berada dalam rentang yang diizinkan — tidak lebih awal dari 1900, tidak lebih lambat dari hari ini.

Mengekspor laporan dengan tanggal membutuhkan format tetap yang tidak tergantung pada locale pengguna. Gunakan dateFormat “yyyy-MM-dd HH:mm:ss” dengan locale en_US_POSIX dan zona waktu UTC. Pendekatan ini menjamin bahwa file akan terbuka dengan benar di negara mana pun terlepas dari pengaturan regional sistem.

SkenarioFormatterPengaturan Kunci
Feed beritaRelativeDateFormatterunitsStyle = .full
Input tanggalDateFormatterdateFormat + fallback
Serialisasi APIISO8601DateFormatterwithInternetDateTime
Ekspor laporanDateFormatteren_US_POSIX + UTC

Pertanyaan yang Sering Diajukan

Mengapa DateFormatter mengembalikan nil untuk string yang benar?

Penyebab paling umum — ketidakcocokan dateFormat dengan format string. Misalnya, format “dd/MM/yyyy” tidak akan mengurai string “2026-07-21”. Penyebab kedua — ketidakcocokan locale: string “July 21, 2026” tidak akan diurai dengan locale id_ID. Ketiga — kesalahan ketik di simbol LDML: gunakan yyyy, bukan YYYY (berbeda arti).

Apakah perlu membuat DateFormatter baru untuk setiap panggilan?

Tidak. DateFormatter adalah objek berat, inisialisasinya mencakup memuat data locale. Buat satu instance per jenis pemformatan dan gunakan kembali. Di lingkungan multi-thread, gunakan Thread-local storage atau kumpulan formatter dengan serial queue untuk sinkronisasi.

Apa perbedaan DateFormatter dengan RelativeDateFormatter?

DateFormatter menampilkan tanggal absolut (21 Juli 2026), sedangkan RelativeDateFormatter — tanggal relatif (hari ini, kemarin, 3 hari lagi). RelativeDateFormatter muncul di iOS 15+ dan menggunakan pola LDML yang sama, tetapi secara otomatis memilih tampilan relatif.

Bagaimana menangani tanggal tanpa zona waktu dari API?

Atur timeZone formatter ke UTC sebelum parsing. Jika server mengembalikan tanggal dalam waktu lokal tanpa indikasi zona, periksa spesifikasi API — kemungkinan besar yang dimaksud adalah UTC. Untuk ISO 8601 dengan Z di akhir, timeZone tidak diperlukan — formatter mengurai offset dari string.

Bagaimana membuat DateFormatter thread-safe?

Jangan gunakan satu instance dari thread yang berbeda tanpa sinkronisasi. Buat instance baru di setiap thread atau gunakan Thread.current.threadDictionary untuk penyimpanan. Alternatif — NSLock dengan penguncian selama string(from:) dan date(from:).

Kesimpulan

  • DateFormatter — kelas Foundation untuk konversi Date ke string dan sebaliknya dengan mempertimbangkan locale, zona waktu, dan kalender pengguna.
  • Gaya yang telah ditentukan dateStyle dan timeStyle dengan varian .short, .medium, .long, .full mencakup sebagian besar skenario UI.
  • dateFormat kustom melalui simbol LDML memberikan kontrol penuh atas format, tetapi memerlukan kehati-hatian dengan lokalisasi.
  • Locale dan TimeZone — properti wajib untuk tampilan yang benar: untuk UI — locale sistem, untuk API — en_US_POSIX dan UTC.
  • ISO8601DateFormatter — pilihan yang lebih disukai untuk serialisasi tanggal di API karena kecepatan dan stabilitas.
  • DateFormatter tidak aman untuk thread — gunakan instance terpisah untuk setiap thread atau sinkronkan akses.
  • RelativeDateFormatter (iOS 15+) — solusi optimal untuk menampilkan tanggal relatif di feed berita dan messenger.

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.

Diskusikan proyek

Baca juga