DateComponents – apa itu, komponen kalender dan NSCalendar

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

DateComponents adalah struktur Foundation yang menyimpan komponen tanggal kalender sebagai bidang terpisah: tahun, bulan, hari, jam, menit, detik, dan lainnya. Berbeda dengan Date yang mewakili momen absolut dalam waktu, DateComponents berisi nilai yang dapat dibaca manusia, tergantung pada kalender dan zona waktu. Menurut Apple Developer Documentation (2025), DateComponents digunakan sebagai penghubung antara Date dan Calendar – melalui komponen ini, tanggal kalender diekstrak dan dibangun, perhitungan dan pergeseran tanggal dilakukan tanpa aritmetika manual.

Poin utama

  • DateComponents – struktur untuk menyimpan komponen tanggal (tahun, bulan, hari) sebagai bidang integer opsional.
  • Calendar.dateComponents – metode yang mengekstrak komponen yang ditentukan dari Date dengan mempertimbangkan zona waktu.
  • Calendar.date(from:) – konversi terbalik DateComponents ke Date dengan pengisian otomatis bidang yang hilang.
  • Bidang opsional – setiap bidang DateComponents bisa nil, memungkinkan penentuan tanggal yang tidak lengkap.
  • Range dan komponen – DateComponents digunakan dalam Calendar untuk menghitung selisih antara tanggal dan menemukan tanggal dalam rentang.

Apa itu DateComponents?

DateComponents adalah tipe nilai Foundation yang dirancang untuk menyimpan komponen kalender waktu. Setiap komponen direpresentasikan sebagai bidang Int opsional: year, month, day, hour, minute, second, nanosecond, weekday, weekOfMonth, weekOfYear, quarter, yearForWeekOfYear, dan lainnya.

Perbedaan utama dari Date adalah keterkaitan dengan kalender. Date menyimpan waktu absolut (jumlah detik dari tanggal referensi), sedangkan DateComponents adalah representasi yang dapat dibaca manusia yang hanya bermakna dalam konteks Calendar tertentu. Date yang sama dapat direpresentasikan dengan DateComponents yang berbeda dalam kalender dan zona waktu yang berbeda.

DateComponents bukanlah tipe waktu mandiri, melainkan wadah data. Untuk menafsirkan DateComponents sebagai tanggal, diperlukan Calendar yang memahami bagaimana komponen terkait dengan sistem kalender. Calendar.dateComponents(from: Date) melakukan ekstraksi komponen, Calendar.date(from: DateComponents) – perakitan terbalik.

Opsionalitas bidang

Setiap bidang DateComponents bersifat opsional (Int?), yang fundamental untuk bekerja dengan tanggal yang tidak lengkap. Jika Anda hanya menentukan tahun dan bulan, Calendar akan melengkapi bidang yang hilang dengan nilai default: hari = 1, jam = 0, menit = 0. Ini nyaman untuk membuat tanggal awal periode – Anda hanya perlu menentukan komponen yang diminati.

Saat membandingkan DateComponents dengan operator ==, hanya bidang yang ditentukan (tidak nil) yang dibandingkan. Dua struktur DateComponents dengan tahun 2026 tetapi bulan berbeda dianggap berbeda. isEqual dari NSObjectProtocol tidak berlaku untuk DateComponents – DateComponents tidak mewarisi NSObject.

Komponen tanggal: tahun, bulan, hari

Bidang dasar DateComponents mencakup year, month, day, hour, minute, second, nanosecond. Setiap bidang menyimpan nilai numerik dalam unit yang sesuai: tahun – 2026, bulan – 1..12, hari – 1..31, jam – 0..23, menit – 0..59, detik – 0..59. Nanodetik dapat mengambil nilai 0..999999999.

Bidang minggu – weekday (1..7, di mana 1 = Minggu dalam kalender Gregorian), weekOfMonth, weekOfYear. Bidang-bidang ini tergantung pada Calendar dan tidak bermakna di luar konteksnya. weekday tergantung pada pengaturan firstWeekday kalender: dalam lokal Indonesia, minggu dimulai pada hari Senin (weekday = 2 dalam sistem Gregorian), sedangkan dalam lokal Amerika – pada hari Minggu (weekday = 1).

Bidang khusus – quarter (1..4), yearForWeekOfYear (tahun di mana minggu tersebut berada), isLeapMonth (bendera logis untuk bulan kabisat dalam kalender Ibrani atau Cina). Bidang calendar dan timeZone menyimpan referensi ke objek terkait dengan mana struktur dibuat.

KategoriBidangRentang
Kalenderyear, month, day1..∞, 1..12, 1..31
Waktuhour, minute, second, nanosecond0..23, 0..59, 0..59, 0..999999999
Mingguanweekday, weekOfMonth, weekOfYear1..7, 1..5, 1..53
Khususquarter, yearForWeekOfYear1..4, tergantung

Saat mengekstrak komponen melalui Calendar.dateComponents, penting untuk hanya meminta bidang yang diperlukan demi performa. Calendar mengekstrak semua bidang yang diminta dalam satu lintasan – ini jauh lebih cepat daripada memanggil Calendar.component untuk setiap bidang secara terpisah.

Membuat DateComponents

Inisialisasi DateComponents – cara termudah: Anda membuat struktur kosong dan mengisi bidang yang diperlukan. Semua bidang yang tidak ditentukan secara otomatis menerima nil. Tanggal yang dibuat dari komponen parsial tidak divalidasi pada tahap inisialisasi – kesalahan hanya dapat terjadi saat konversi ke Date melalui Calendar.

Inisialisator DateComponents(calendar:timeZone:era:year:month:day:hour:minute:second:nanosecond:weekday:…) memungkinkan pengaturan semua bidang dalam satu panggilan. Inisialisator ini nyaman untuk membuat tanggal lengkap dari nilai yang sudah siap, tetapi jarang digunakan dengan lebih dari 5-6 argumen karena keterbacaan.

Calendar.dateComponents(_:from:) – cara utama untuk mendapatkan DateComponents dari Date yang ada. Argumen kedua adalah kumpulan komponen yang akan diekstrak. Calendar melakukan perhitungan kalender dengan mempertimbangkan zona waktu dan mengembalikan struktur hanya dengan bidang yang diminta, bidang lainnya tetap nil.

swift
import Foundation

// Membuat melalui inisialisator bidang
var components = DateComponents()
components.year = 2026
components.month = 7
components.day = 21

// Mengekstrak dari Date
let now = Date()
let extracted = Calendar.current.dateComponents(
    [.year, .month, .day],
    from: now
)
print("Today: \(extracted.day!).\(extracted.month!).\(extracted.year!)")

// Membuat melalui inisialisator diperluas
let birthday = DateComponents(
    calendar: Calendar.current,
    year: 1990, month: 5, day: 15
)

Saat membuat DateComponents melalui bidang secara manual, selalu periksa Calendar sebelum konversi ke Date. Calendar saat konversi date(from:) dapat mengembalikan nil jika komponen membentuk tanggal yang tidak ada – misalnya, 31 Februari atau 30 Februari di tahun non-kabisat. Validasi tanggal adalah tanggung jawab Calendar, bukan DateComponents.

Mengonversi DateComponents ke Date

Calendar.date(from:) – metode utama konversi DateComponents ke Date. Calendar menafsirkan komponen sesuai dengan kalender dan zona waktunya. Jika beberapa bidang tidak diatur (nil), Calendar menggunakan nilai default: hari = 1, jam = 0, menit = 0, detik = 0.

Metode mengembalikan Date opsional – nil terjadi ketika komponen saling bertentangan atau membentuk tanggal yang tidak valid. Penyebab umum nil: tanggal yang tidak ada (32 Januari, 29 Februari 2023), bidang yang bertentangan (weekday=1, day=5 dalam satu set), tahun yang tidak mungkin untuk kalender tertentu (tahun 0 dalam kalender Gregorian).

DateComponents dengan timeZone – jika DateComponents berisi timeZone, Calendar menggunakannya saat konversi. Jika timeZone tidak ditentukan, Calendar menggunakan timeZone saat ini. Jika Calendar.timeZone tidak sesuai dengan zona waktu yang diharapkan dari tanggal, hasilnya mungkin berbeda beberapa jam – pastikan timeZone secara eksplisit ditetapkan di salah satu objek.

swift
let calendar = Calendar(identifier: .gregorian)

// Membuat Date dari DateComponents
var comps = DateComponents()
comps.year = 2026
comps.month = 12
comps.day = 25
comps.hour = 10

if let date = calendar.date(from: comps) {
    print("Christmas: \(date)")
}

// Membuat dengan menentukan timeZone
calendar.timeZone = TimeZone(identifier: "UTC")!
let utcComps = DateComponents(
    calendar: calendar, year: 2026, month: 7, day: 21,
    hour: 12
)
let utcDate = calendar.date(from: utcComps)!

Calendar.dateComponents untuk selisih tanggal – skenario lain penggunaan DateComponents. Calendar.dateComponents([.year, .month, .day], from: Date(), to: futureDate) mengembalikan selisih dalam tahun, bulan, dan hari antara dua tanggal. Ini adalah cara yang benar untuk menghitung usia daripada membagi TimeInterval dengan jumlah detik dalam setahun, karena Calendar memperhitungkan tahun kabisat.

Calendar dan DateComponents

Calendar – kelas sentral yang bekerja dengan DateComponents. Semua operasi ekstraksi, perakitan, dan perbandingan tanggal melewati Calendar. Tanpa Calendar, DateComponents hanyalah kumpulan angka tanpa makna temporal. Calendar memberikan interpretasi pada komponen: menentukan bahwa bulan 2 adalah Februari, dan weekday 2 adalah Senin.

Calendar.nextDate dan Calendar.enumerateDates – dua metode yang didasarkan pada DateComponents. nextDate(after: Date(), matching: DateComponents) menemukan tanggal berikutnya yang sesuai dengan komponen yang ditentukan – misalnya, Senin berikutnya setelah hari ini. enumerateDates(startingAfter:matching:matchingPolicy:using:) mengulangi semua tanggal yang sesuai dengan pola hingga batas yang ditentukan.

Calendar.dateInterval – metode yang mengembalikan DateInterval untuk komponen yang ditentukan. dateInterval(of: .month, for: Date()) mengembalikan awal dan akhir bulan saat ini. Secara internal, metode ini menggunakan DateComponents untuk menemukan batas periode: membuat DateComponents dengan hari pertama dan terakhir bulan, mengonversinya ke Date melalui Calendar.

swift
let calendar = Calendar.current

// Senin depan
let nextMonday = calendar.nextDate(
    after: Date(),
    matching: DateComponents(weekday: 2),
    matchingPolicy: .nextTime
)!

// Selisih antara tanggal dalam hari
let diff = calendar.dateComponents(
    [.day], from: Date(), to: nextMonday
)

// Rentang bulan
let monthInterval = calendar.dateInterval(
    of: .month, for: Date()
)!
let startOfMonth = monthInterval.start
let endOfMonth = monthInterval.end

MatchingPolicy – parameter penting dari metode Calendar saat bekerja dengan DateComponents. strictPolicy memerlukan pencocokan tepat semua komponen, nextTimePolicy memilih pencocokan berikutnya dalam waktu, nextTimePreservingSmallerComponents mempertahankan komponen yang lebih kecil (menit, detik) dari tanggal asli. Pilihan kebijakan memengaruhi hasil pencarian tanggal, terutama saat pergeseran melalui perubahan waktu musim panas/musim dingin.

Contoh DateComponents

Kami akan meninjau skenario praktis penggunaan DateComponents dalam aplikasi. Setiap contoh mendemonstrasikan tugas tipikal yang dihadapi pengembang iOS saat bekerja dengan tanggal kalender.

Pengingat untuk hari pertama setiap bulan

Calendar.nextDate dengan DateComponents(day: 1) menemukan hari pertama bulan berikutnya. Calendar secara otomatis menentukan jumlah hari dalam bulan saat ini dan beralih ke bulan berikutnya. Untuk notifikasi berulang, gunakan enumerateDates atau Combine.Timer dengan kunci Calendar.

swift
func firstDayOfNextMonth(from date: Date) -> Date {
    let calendar = Calendar.current
    let comps = DateComponents(day: 1)
    return calendar.nextDate(
        after: date,
        matching: comps,
        matchingPolicy: .nextTime
    )!
}

// Menghitung usia dalam tahun
func ageInYears(from birthDate: Date) -> Int {
    let calendar = Calendar.current
    let ageComponents = calendar.dateComponents(
        [.year], from: birthDate, to: Date()
    )
    return ageComponents.year ?? 0
}

// Mengelompokkan peristiwa berdasarkan tahun dan bulan
func groupEventsByMonth(_ events: [Event]) -> [String: [Event]] {
    let calendar = Calendar.current
    return Dictionary(grouping: events) { event in
        let comps = calendar.dateComponents(
            [.year, .month], from: event.date
        )
        return "\(comps.year!)-\(comps.month!)"
    }
}

Menghitung usia melalui Calendar.dateComponents([.year], from:to:) – satu-satunya cara yang benar yang memperhitungkan tahun kabisat. Perhitungan berbasis TimeInterval (detik / 31536000) memberikan kesalahan untuk orang yang lahir pada 29 Februari. Calendar dengan benar menentukan apakah ulang tahun telah terjadi di tahun berjalan dan mengembalikan usia yang tepat.

Pengelompokan berdasarkan tahun dan bulan – tugas umum untuk layar dengan riwayat atau kalender. DateComponents berfungsi sebagai kunci pengelompokan: Anda mengekstrak tahun dan bulan dari tanggal peristiwa, membentuk kunci string, dan mengelompokkan melalui Dictionary(grouping:). Untuk tampilan, gunakan DateFormatter dengan templat “LLLL yyyy” untuk nama bulan yang dilokalkan.

TugasMetode CalendarPeran DateComponents
Hari pertama bulannextDate(after:matching:)day: 1
Menghitung usiadateComponents(from:to:)[.year] dari selisih
Mengelompokkan tanggaldateComponents(_:from:)year + month kunci
Mencari hari dalam minggunextDate(after:matching:)weekday: N

Pertanyaan yang sering diajukan

Mengapa Calendar.date(from:) mengembalikan nil untuk DateComponents?

Penyebab: tanggal yang tidak ada (31 April), bidang yang bertentangan (weekday=1 dengan day=5), kombinasi bidang yang tidak valid untuk kalender yang dipilih. Calendar mencoba menafsirkan komponen dalam sistemnya – jika kombinasi tidak mungkin, hasilnya nil. Selalu gunakan guard let atau if let saat konversi.

Bisakah DateComponents dibandingkan satu sama lain?

Ya, melalui operator ==. DateComponents mengimplementasikan Equatable, membandingkan semua bidang. Dua struktur sama jika semua bidangnya sama (nil == nil dianggap benar). Untuk membandingkan hanya sebagian bidang – ekstrak set yang sama melalui Calendar.dateComponents.

Apa perbedaan DateComponents dengan Date?

Date – momen absolut dalam waktu tanpa keterkaitan dengan kalender. DateComponents – kumpulan angka yang dapat dibaca manusia (tahun, bulan, hari) yang hanya bermakna dalam konteks Calendar. Date dapat dibandingkan, dikurangkan, diserialisasi ke ISO 8601. DateComponents – representasi perantara untuk interaksi dengan kalender.

Bagaimana cara menentukan hanya tahun dan bulan di DateComponents?

Atur hanya bidang year dan month, biarkan sisanya nil. Saat konversi ke Date melalui Calendar.date(from:), Calendar akan secara otomatis mengatur hari = 1, jam = 0, menit = 0. Hasilnya – Date yang sesuai dengan hari pertama bulan yang ditentukan pada tengah malam.

Bagaimana DateComponents menangani zona waktu?

DateComponents tidak menyimpan informasi tentang zona waktu di bidang – nilai bidang (tahun, bulan, hari) sendiri tergantung pada timeZone di mana mereka diekstrak. Komponen “21 Juli 2026 14:00 MSK” dan “21 Juli 2026 10:00 UTC” mewakili Date yang sama, tetapi bidang DateComponents berbeda.

Ringkasan

  • DateComponents – struktur Foundation untuk menyimpan komponen kalender (tahun, bulan, hari, jam) sebagai bidang opsional Int?.
  • Calendar.dateComponents mengekstrak komponen dari Date dengan mempertimbangkan zona waktu dan sistem kalender.
  • Calendar.date(from:) merakit Date dari DateComponents menggunakan nilai default untuk bidang yang hilang.
  • Opsionalitas bidang memungkinkan penentuan tanggal yang tidak lengkap – Calendar melengkapi nilai yang hilang.
  • Calendar.nextDate mencari tanggal berikutnya yang sesuai dengan DateComponents – untuk pengingat dan acara berulang.
  • Menghitung usia melalui Calendar.dateComponents([.year], from:to:) – satu-satunya cara yang benar yang memperhitungkan tahun kabisat.
  • MatchingPolicy mengontrol perilaku Calendar saat ketidakcocokan semua komponen – parameter penting untuk pencarian tanggal.

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