Calendar — ay isang klase ng Foundation na tumutukoy sa sistema ng kalendaryo at nagbibigay ng mga pamamaraan para sa mga kalkulasyon ng kalendaryo: pagkuha ng mga bahagi ng petsa, pagkalkula ng pagkakaiba sa pagitan ng mga petsa, paghahanap ng mga hangganan ng panahon, at paglipat ng mga petsa. Ang kalendaryo ay nag-uugnay ng absolute na oras (Date) sa mga bahaging nababasa ng tao at isinasaalang-alang ang mga rehiyonal na katangian: simula ng linggo, time zone, at daylight saving time. Ayon sa Apple Developer Documentation (2025), sinusuportahan ng Foundation ang 17 sistema ng kalendaryo — mula Gregorian hanggang Buddhist at Japanese, na ginagawang unibersal na kasangkapan ang Calendar para sa mga internasyonalisadong aplikasyon.
Mga Pangunahing Punto
Calendar — ay isang klase ng Foundation na nagpapatupad ng mga kalkulasyon ng kalendaryo batay sa ICU (International Components for Unicode). Tinutukoy ng kalendaryo kung paano imamapa ang absolute na oras (Date) sa mga bahagi ng kalendaryo: taon, buwan, araw, oras, minuto, segundo. Kung walang Calendar, hindi malalaman kung anong taon, buwan, at araw ngayon — ang Date mismo ay hindi naglalaman ng impormasyong ito.
Isinasaalang-alang ng kalendaryo ang tatlong grupo ng mga parameter: sistema ng kalendaryo (Gregorian, Buddhist, Japanese), time zone, at lokal. Pinagsasama ng Calendar.current ang lahat ng tatlo mula sa mga setting ng system ng gumagamit. Ang Calendar.autoupdatingCurrent — espesyal na bersyon na awtomatikong ina-update kapag nagbago ang mga setting nang hindi nire-restart ang application sa pamamagitan ng NotificationCenter.
Ang kalendaryo ay isang value type sa Foundation. Lumilikha ang Calendar(identifier:) ng bagong instance na may nakapirming mga parameter. Ang kalendaryo ay maaaring kopyahin, ihambing sa pamamagitan ng ==, at gamitin bilang susi sa diksyunaryo. Pinapayagan nito ang paglikha ng mga kalendaryo na may tiyak na mga setting ng timeZone at locale para sa pagsubok.
Calendar — bersyon ng Swift ng NSCalendar ng Objective-C, na may tulay na as Calendar / as NSCalendar. Sa modernong Swift, ginagamit ang Calendar sa lahat ng dako. Nananatili ang NSCalendar para sa backward compatibility sa Objective-C API. Ang Calendar ay may kumpletong hanay ng mga pamamaraan nang walang NS prefix, na may type-safe na argumento at Swift optionality.
Thread Safety — ang Calendar ay thread-safe para sa pagbabasa. Ang nilikhang instance ay maaaring ligtas na basahin mula sa maraming thread. Ang pagbabago ng mga property (timeZone, locale) ay hindi thread-safe — para sa iba't ibang configuration, lumikha ng hiwalay na mga instance ng Calendar.
Sinusuportahan ng Foundation ang 17 sistema ng kalendaryo sa pamamagitan ng enumeration na Calendar.Identifier. Bawat sistema ay may sariling mga patakaran para sa leap year, bilang ng mga buwan, at simula ng panahon. Ang pagpili ng kalendaryo ay nakakaapekto sa lahat ng kalkulasyon: dateComponents, dateInterval, nextDate.
Mga pangunahing sistema ng kalendaryo:
Calendar(identifier: .gregorian) — pinakamadalas gamitin. Ito ay tumutugma sa internasyonal na pamantayang ISO 8601 at ang default na kalendaryo sa karamihan ng mga bansa. Para sa mga application na may internasyonal na madla, gamitin ang Calendar.current — awtomatiko itong tumutugma sa kalendaryo ng system ng gumagamit.
| Tagatukoy | Uri | Rehiyon ng Paggamit |
|---|---|---|
| .gregorian | Araw | Internasyonal |
| .buddhist | Araw | Thailand, Cambodia |
| .japanese | Araw | Hapon |
| .hebrew | Lunar-Araw | Israel |
| .islamic | Lunar | Mga bansang Islamiko |
| .chinese | Lunar-Araw | Tsina |
DateComponents at Calendar — hindi mapaghihiwalay na pares. Kinukuha ng Calendar.dateComponents(_:from:) ang mga bahagi mula sa Date na isinasaalang-alang ang time zone ng kalendaryo. Binubuo ng Calendar.date(from:) ang Date mula sa DateComponents, pinupuno ang mga nawawalang field ng mga default na halaga: araw = 1, oras = 0, minuto = 0, segundo = 0.
Ang pamamaraang Calendar.component ay kumukuha ng isang bahagi, na maginhawa para sa mabilisang pagsusuri. Ang Calendar.dateComponents ay kumukuha ng isang set ng mga bahagi sa isang tawag — ito ay mas episyente dahil ang Calendar ay nagsasagawa ng mga kalkulasyon ng kalendaryo nang isang beses, hindi para sa bawat bahagi nang hiwalay. Para sa listahan ng 3+ bahagi, laging gamitin ang dateComponents.
Calendar.compare ay naghahambing ng dalawang Date na may tinukoy na presisyon. Tinutukoy ng parameter na toGranularity kung hanggang saang bahagi isasagawa ang paghahambing: .year ay naghahambing lamang ng taon, .month — taon at buwan, .day — taon, buwan, araw. Ito ay maginhawa para sa pagsuri kung ang dalawang petsa ay kabilang sa parehong araw, nang hindi isinasaalang-alang ang oras.
let calendar = Calendar.current
let now = Date()
// Pagkuha ng isang bahagi
let year = calendar.component(.year, from: now)
// Pagkuha ng isang set ng mga bahagi
let comps = calendar.dateComponents(
[.year, .month, .day], from: now
)
// Paghahambing na may presisyon ng araw
let isSameDay = calendar.compare(date1, to: date2,
toGranularity: .day) == .orderedSame
// Suriin kung ang petsa ay ngayon
let isToday = calendar.isDateInToday(someDate)
Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday — mga pamamaraan para sa relatibong pagsusuri. Ang Calendar.isDate(_:inSameDayAs:) ay sumusuri kung ang dalawang petsa ay nasa parehong araw ng kalendaryo na isinasaalang-alang ang time zone ng kalendaryo. Ang mga pamamaraang ito ay gumagamit ng Calendar.compare sa loob at optimisado para sa madalas na tawag.
Calendar.dateInterval — isa sa mga pinakakapaki-pakinabang na pamamaraan para sa analytics at UI. Nagbabalik ito ng DateInterval para sa tinukoy na bahagi: simula at wakas ng araw, linggo, buwan, taon. Naglalaman ang DateInterval ng start (Date) at end (Date) — mga hangganan ng panahon. Halimbawa, ang dateInterval(of: .weekOfYear, for: Date()) ay nagbabalik ng simula ng Lunes at wakas ng Linggo ng kasalukuyang linggo.
Calendar.date na may byAdding — pamamaraan para sa paglipat ng petsa. Ang Calendar.date(byAdding: .day, value: 7, to: Date()) ay nagbabalik ng petsa makalipas ang isang linggo. Ang Calendar.date(byAdding: DateComponents) — mas nababaluktot na bersyon, na nagpapahintulot ng paglipat ng maraming bahagi nang sabay: +1 buwan +3 araw. Awtomatikong isinasaalang-alang ng Calendar ang iba't ibang haba ng mga buwan at leap year.
Calendar.nextDate ay naghahanap ng susunod na petsa na tumutugma sa tinukoy na DateComponents. Tinutukoy ng parameter na matchingPolicy ang pag-uugali kapag hindi tugma: .nextTime — susunod na tugma sa oras, .nextTimePreservingSmallerComponents — pinapanatili ang mga minuto at segundo mula sa orihinal na petsa, .strict — nangangailangan ng eksaktong tugma.
let calendar = Calendar.current
let today = Date()
// Simula at wakas ng linggo
let weekInterval = calendar.dateInterval(
of: .weekOfYear, for: today
)!
// Paglipat ng 1 buwan
let nextMonth = calendar.date(
byAdding: .month, value: 1, to: today
)!
// Paglipat sa pamamagitan ng DateComponents
var delta = DateComponents()
delta.month = 1
delta.day = 3
let shifted = calendar.date(byAdding: delta, to: today)!
// Susunod na Biyernes ika-13
let friday13Components = DateComponents(
weekday: 6, day: 13
)
let nextFriday13 = calendar.nextDate(
after: today, matching: friday13Components,
matchingPolicy: .nextTime
)
EnumerateDates — isang makapangyarihang pamamaraan para sa pag-ulit ng mga petsa ayon sa pattern. Ang Calendar.enumerateDates(startingAfter:matching:matchingPolicy:using:) ay tumatawag ng block para sa bawat tugma hanggang ang block ay magbalik ng stop = true. Ginagamit para sa pagbuo ng mga umuulit na kaganapan sa mga kalendaryo at iskedyul. Ang pamamaraan ay mas episyente kaysa sa manu-manong loop na may nextDate dahil ito ay optimisado ng ICU.
TimeZone — hindi mapaghihiwalay na bahagi ng Calendar. Tinutukoy ng time zone kung anong oras ng kalendaryo ang katumbas ng absolute na Date. Ang parehong Date sa UTC at sa Moscow ay nagbibigay ng magkaibang mga bahagi: ang Date() sa UTC ay maaaring magpakita ng 10:00, at sa MSK — 13:00. Ang Calendar.timeZone ay default na katumbas ng TimeZone.current.
Locale ay nakakaapekto sa unang araw ng linggo, pinakamababang bilang ng mga araw sa unang linggo ng taon (minDaysInFirstWeek), at mga pangalan ng buwan/araw ng linggo (sa conversion sa pamamagitan ng DateFormatter). Ang Calendar.locale ay default na katumbas ng Locale.current. Sa lokal na Pilipino, ang linggo ay nagsisimula sa Lunes, sa Amerikanong lokal — sa Linggo.
Calendar.availableIdentifiers ay nagbabalik ng listahan ng lahat ng sinusuportahang tagatukoy ng kalendaryo. static property Calendar.availableCalendarIdentifiers — array ng mga string na may parehong mga tagatukoy. Ginagamit para sa pagbuo ng UI ng pagpili ng kalendaryo at para sa pagsuri ng pagkakaroon ng isang partikular na sistema ng kalendaryo sa device.
// Kalendaryo na may tiyak na time zone
var utcCalendar = Calendar(identifier: .gregorian)
utcCalendar.timeZone = TimeZone(identifier: "UTC")!
// Kalendaryo na may lokal na Ruso
var russianCalendar = Calendar(identifier: .gregorian)
russianCalendar.locale = Locale(identifier: "ru_RU")
// Unang araw ng linggo ay depende sa lokal
let firstWeekday = russianCalendar.firstWeekday
// 2 = Lunes (sa fil_PH)
// Listahan ng mga magagamit na kalendaryo
for identifier in Calendar.availableIdentifiers {
print(identifier)
}
firstWeekday — property ng Calendar na tumutukoy kung aling araw ng linggo ang itinuturing na una. Sa lokal na Pilipino, Sunday = 2 (Lunes ang una). Sa Amerikanong lokal, Sunday = 1. Ito ay nakakaapekto sa paggana ng weekOfMonth at weekOfYear: ang parehong petsa ay maaaring italaga sa magkaibang numero ng linggo sa magkaibang lokal. Para sa mga application na may mga petsa, gamitin ang Calendar.current o tahasang itakda ang firstWeekday.
Tingnan natin ang mga praktikal na senaryo na nagpapakita ng mga kakayahan ng Calendar. Bawat halimbawa ay lumulutas ng isang tiyak na gawain sa pag-develop ng iOS at nagpapakita ng tamang paraan ng paggamit ng mga kalkulasyon ng kalendaryo.
Calendar.dateInterval(of: .month, for:) ay nagbabalik ng mga hangganan ng kasalukuyang buwan. Ang pagsusuri kung ang Date ay nasa loob ng interval na ito — ang pinakamabilis na paraan upang matukoy kung ang petsa ay kabilang sa kasalukuyang buwan. Alternatibong paraan — Calendar.compare na may granularity .month: kung ang resulta ay .orderedSame, ang buwan ay tugma.
func isInCurrentMonth(_ date: Date) -> Bool {
let calendar = Calendar.current
let monthInterval = calendar.dateInterval(
of: .month, for: Date()
)!
return monthInterval.contains(date)
}
// Bilang ng mga araw sa isang buwan
func daysInMonth(for date: Date) -> Int {
let calendar = Calendar.current
return calendar.range(
of: .day, in: .month, for: date
)?.count ?? 0
}
// Pagdaragdag ng mga buwan na may tamang pagkumpleto
func addMonths(_ months: Int, to date: Date) -> Date {
let calendar = Calendar.current
return calendar.date(
byAdding: .month, value: months, to: date
)!
}
Calendar.range(of:in:for:) ay nagbabalik ng saklaw ng mga pinapayagang halaga para sa tinukoy na bahagi sa konteksto ng isa pang bahagi. Halimbawa, ang range(of: .day, in: .month, for: date) ay nagbabalik ng 1..<32 para sa mga buwan na may 31 araw o 1..<29 para sa Pebrero ng hindi leap year. Ito ang tamang paraan upang malaman ang bilang ng mga araw sa isang buwan, hindi ang paggamit ng hardcode na mga halaga.
Pagdaragdag ng mga buwan sa pamamagitan ng Calendar.date(byAdding:value:to:) ay wastong humahawak ng mga petsang nasa hangganan. Kung ang ika-31 ng Enero ay dagdagan ng 1 buwan, ang Calendar ay nagbabalik ng ika-28 ng Pebrero (o 29 sa leap year), hindi ika-3 ng Marso, tulad ng mangyayari sa simpleng pagdaragdag ng 30 araw sa pamamagitan ng TimeInterval. Ito ay isa pang dahilan upang hindi gumamit ng TimeInterval para sa mga kalkulasyon ng kalendaryo.
| Pamamaraan ng Calendar | Layunin | Halimbawa |
|---|---|---|
| dateInterval | Mga hangganan ng panahon | Simula at wakas ng buwan |
| range(of:in:for:) | Saklaw ng bahagi | Mga araw sa kasalukuyang buwan |
| date(byAdding:) | Paglipat ng petsa | +1 buwan mula ngayon |
| isDateInToday | Pagsusuri kung ngayon | Ang petsa ba ay ngayon |
| compare(toGranularity:) | Paghahambing na may presisyon | Parehong araw walang oras |
Mga Madalas Itanong
Calendar.current ay nagbabalik ng kalendaryo mula sa mga setting ng system ng gumagamit — maaaring hindi ito Gregorian (halimbawa, Buddhist sa Thailand). Calendar(identifier: .gregorian) ay laging lumilikha ng Gregorian na kalendaryo anuman ang mga setting. Para sa pagpapakita ng mga petsa, gamitin ang Calendar.current, para sa lohika ng negosyo — ang tahasang piniling tagatukoy.
Ito ay may kaugnayan sa iba't ibang haba ng mga buwan. Kung ang kasalukuyang petsa ay ika-31 ng Enero, ang pagdaragdag ng 1 buwan ay nagbibigay ng ika-28 ng Pebrero, dahil ang Pebrero ay walang 31 araw. Awtomatikong kinukumpleto ng Calendar ang petsa hanggang sa huling pinapayagang araw ng buwan. Para sa tumpak na kontrol, gamitin ang DateComponents na may day: 1 upang pumunta sa unang araw ng buwan.
DateFormatter ay gumagamit ng Calendar.current — kalendaryo ng system ng gumagamit. Kung ang application ay dapat palaging magpakita ng mga petsa sa Gregorian na kalendaryo anuman ang mga setting, itakda ang formatter.calendar = Calendar(identifier: .gregorian). Ito ay ginagarantiyahan ang pare-parehong pagpapakita para sa lahat ng gumagamit.
Calendar.range(of: .day, in: .year, for: date) ay nagbabalik ng 365 o 366 araw. Mas simple: Calendar.date(from: DateComponents(year: taon, month: 2, day: 29)) != nil — kung ang ika-29 ng Pebrero ay umiiral, ang taon ay leap year. Ang Calendar mismo ay isinasaalang-alang ang mga patakaran para sa partikular na sistema ng kalendaryo.
Oo, ang property na firstWeekday ay maaaring isulat. Ang pagbabago ay nakakaapekto sa weekOfMonth, weekOfYear, at lahat ng kalkulasyon na may kaugnayan sa mga numero ng linggo. Kapag itinakda ang locale = Locale(identifier: "fil_PH"), ang firstWeekday ay awtomatikong nagiging 2 (Lunes). Ang manu-manong setting ay nag-o-override sa halaga mula sa locale.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din