Calendar — এটি একটি Foundation ক্লাস যা ক্যালেন্ডার সিস্টেম সংজ্ঞায়িত করে এবং ক্যালেন্ডার গণনার জন্য পদ্ধতি প্রদান করে: তারিখের উপাদান বের করা, তারিখের মধ্যে পার্থক্য গণনা করা, সময়সীমার সীমা খোঁজা এবং তারিখ স্থানান্তর করা। ক্যালেন্ডার পরম সময় (Date) কে মানব-পাঠযোগ্য উপাদানের সাথে সংযুক্ত করে এবং আঞ্চলিক বৈশিষ্ট্যগুলি বিবেচনা করে: সপ্তাহের শুরু, সময় অঞ্চল এবং গ্রীষ্মকালীন সময়। Apple Developer Documentation (2025) অনুসারে, Foundation 17টি ক্যালেন্ডার সিস্টেম সমর্থন করে — গ্রেগরিয়ান থেকে বৌদ্ধ এবং জাপানি পর্যন্ত, যা Calendar-কে আন্তর্জাতিক অ্যাপ্লিকেশনের জন্য একটি সর্বজনীন টুল করে তোলে।
মূল বিষয়
Calendar — একটি Foundation ক্লাস যা ICU (International Components for Unicode) এর ভিত্তিতে ক্যালেন্ডার গণনা বাস্তবায়ন করে। ক্যালেন্ডার নির্ধারণ করে কিভাবে পরম সময় (Date) ক্যালেন্ডার উপাদানে ম্যাপ করা হয়: বছর, মাস, দিন, ঘন্টা, মিনিট, সেকেন্ড। Calendar ছাড়া বোঝা অসম্ভব যে আজ কোন বছর, মাস এবং দিন — Date নিজে থেকে এই তথ্য ধারণ করে না।
ক্যালেন্ডার তিনটি প্যারামিটার গ্রুপ বিবেচনা করে: ক্যালেন্ডার সিস্টেম (গ্রেগরিয়ান, বৌদ্ধ, জাপানি), সময় অঞ্চল এবং লোকেল। Calendar.current ব্যবহারকারীর সিস্টেম সেটিংস থেকে তিনটি একত্রিত করে। Calendar.autoupdatingCurrent — একটি বিশেষ সংস্করণ যা সেটিংস পরিবর্তনের সময় NotificationCenter-এর মাধ্যমে অ্যাপ্লিকেশন পুনরায় চালু না করেই স্বয়ংক্রিয়ভাবে আপডেট হয়।
ক্যালেন্ডার — Foundation-এ একটি ভ্যালু টাইপ (value type)। Calendar(identifier:) নির্দিষ্ট প্যারামিটার সহ একটি নতুন ইনস্ট্যান্স তৈরি করে। Calendar কপি করা যায়, == এর মাধ্যমে তুলনা করা যায় এবং ডিকশনারিতে কী হিসাবে ব্যবহার করা যায়। এটি পরীক্ষার জন্য নির্দিষ্ট timeZone এবং locale সেটিংস সহ ক্যালেন্ডার তৈরি করতে দেয়।
Calendar — এটি Objective-C NSCalendar-এর Swift সংস্করণ, যার ব্রিজ হল as Calendar / as NSCalendar। আধুনিক Swift-এ সর্বত্র Calendar ব্যবহার করা হয়। NSCalendar Objective-C API-এর সাথে পশ্চাৎগামী সামঞ্জস্যের জন্য রয়ে গেছে। Calendar-এ NS উপসর্গ ছাড়া পদ্ধতির সম্পূর্ণ সেট রয়েছে, type-safe আর্গুমেন্ট এবং Swift-অপশনালিটি সহ।
Thread Safety — Calendar পড়ার জন্য থ্রেড-নিরাপদ। তৈরি করা ইনস্ট্যান্স একাধিক থ্রেড থেকে নিরাপদে পড়া যায়। প্রপার্টি (timeZone, locale) পরিবর্তন করা থ্রেড-নিরাপদ নয় — বিভিন্ন কনফিগারেশনের জন্য আলাদা Calendar ইনস্ট্যান্স তৈরি করুন।
Foundation 17টি ক্যালেন্ডার সিস্টেম সমর্থন করে Calendar.Identifier এনামের মাধ্যমে। প্রতিটি সিস্টেমের নিজস্ব লিপ ইয়ারের নিয়ম, মাসের সংখ্যা এবং যুগের শুরু রয়েছে। ক্যালেন্ডারের পছন্দ সমস্ত গণনাকে প্রভাবিত করে: dateComponents, dateInterval, nextDate।
প্রধান ক্যালেন্ডার সিস্টেম:
Calendar(identifier: .gregorian) — সবচেয়ে বেশি ব্যবহৃত। এটি আন্তর্জাতিক মান ISO 8601 অনুসরণ করে এবং বেশিরভাগ দেশে ডিফল্ট ক্যালেন্ডার। আন্তর্জাতিক দর্শকদের জন্য অ্যাপ্লিকেশনের ক্ষেত্রে Calendar.current ব্যবহার করুন — এটি স্বয়ংক্রিয়ভাবে ব্যবহারকারীর সিস্টেম ক্যালেন্ডারের সাথে মেলে।
| আইডেন্টিফায়ার | ধরন | ব্যবহারের অঞ্চল |
|---|---|---|
| .gregorian | সৌর | আন্তর্জাতিক |
| .buddhist | সৌর | থাইল্যান্ড, কম্বোডিয়া |
| .japanese | সৌর | জাপান |
| .hebrew | চন্দ্র-সৌর | ইসরায়েল |
| .islamic | চন্দ্র | ইসলামিক দেশ |
| .chinese | চন্দ্র-সৌর | চীন |
DateComponents এবং Calendar — একটি অবিচ্ছেদ্য জুটি। Calendar.dateComponents(_:from:) ক্যালেন্ডারের সময় অঞ্চল অনুসারে Date থেকে উপাদান বের করে। Calendar.date(from:) DateComponents থেকে Date তৈরি করে, অনুপস্থিত ফিল্ডগুলি ডিফল্ট মান দিয়ে পূরণ করে: দিন = 1, ঘন্টা = 0, মিনিট = 0, সেকেন্ড = 0।
Calendar.component মেথড একটি একক উপাদান বের করে, যা দ্রুত পরীক্ষার জন্য সুবিধাজনক। Calendar.dateComponents এক কলেই উপাদানের সেট বের করে — এটি বেশি কার্যকর, কারণ Calendar ক্যালেন্ডার গণনা একবার করে, প্রতিটি উপাদানের জন্য আলাদাভাবে নয়। 3+ উপাদানের তালিকার জন্য সর্বদা dateComponents ব্যবহার করুন।
Calendar.compare নির্দিষ্ট নির্ভুলতার সাথে দুটি Date তুলনা করে। toGranularity প্যারামিটার নির্ধারণ করে কোন উপাদান পর্যন্ত তুলনা করতে হবে: .year শুধু বছর তুলনা করে, .month — বছর এবং মাস, .day — বছর, মাস, দিন। এটি সময় উপেক্ষা করে দুটি তারিখ একই দিন কিনা তা পরীক্ষা করার জন্য সুবিধাজনক।
let calendar = Calendar.current
let now = Date()
// একটি উপাদান বের করা
let year = calendar.component(.year, from: now)
// উপাদানের সেট বের করা
let comps = calendar.dateComponents(
[.year, .month, .day], from: now
)
// দিনের গ্র্যানুলারিটির সাথে তুলনা করুন
let isSameDay = calendar.compare(date1, to: date2,
toGranularity: .day) == .orderedSame
// তারিখ আজ কিনা পরীক্ষা করুন
let isToday = calendar.isDateInToday(someDate)
Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday — আপেক্ষিক পরীক্ষার জন্য পদ্ধতি। Calendar.isDate(_:inSameDayAs:) পরীক্ষা করে যে দুটি তারিখ ক্যালেন্ডারের সময় অঞ্চল অনুসারে একই ক্যালেন্ডার দিনে পড়ে কিনা। এই পদ্ধতিগুলি অভ্যন্তরীণভাবে Calendar.compare ব্যবহার করে এবং ঘন ঘন কলের জন্য অপ্টিমাইজ করা।
Calendar.dateInterval — বিশ্লেষণ এবং UI-এর জন্য সবচেয়ে দরকারী পদ্ধতিগুলির একটি। এটি নির্দিষ্ট উপাদানের জন্য DateInterval ফেরত দেয়: দিন, সপ্তাহ, মাস, বছরের শুরু এবং শেষ। DateInterval-এ start (Date) এবং end (Date) থাকে — সময়সীমার সীমানা। উদাহরণস্বরূপ, dateInterval(of: .weekOfYear, for: Date()) বর্তমান সপ্তাহের সোমবারের শুরু এবং রবিবারের শেষ ফেরত দেয়।
Calendar.date byAdding সহ — তারিখ স্থানান্তরের জন্য পদ্ধতি। Calendar.date(byAdding: .day, value: 7, to: Date()) এক সপ্তাহ পরে তারিখ ফেরত দেয়। Calendar.date(byAdding: DateComponents) — আরও নমনীয় সংস্করণ, যা একসাথে একাধিক উপাদান স্থানান্তর করতে দেয়: +1 মাস +3 দিন। Calendar স্বয়ংক্রিয়ভাবে মাসের বিভিন্ন দৈর্ঘ্য এবং লিপ ইয়ার বিবেচনা করে।
Calendar.nextDate নির্দিষ্ট DateComponents-এর সাথে মেলে এমন পরবর্তী তারিখ খোঁজে। matchingPolicy প্যারামিটার অমিলের ক্ষেত্রে আচরণ নির্ধারণ করে: .nextTime — সময় অনুসারে পরবর্তী মিল, .nextTimePreservingSmallerComponents — মূল তারিখ থেকে মিনিট এবং সেকেন্ড সংরক্ষণ করে, .strict — সঠিক মিল প্রয়োজন।
let calendar = Calendar.current
let today = Date()
// সপ্তাহের শুরু এবং শেষ
let weekInterval = calendar.dateInterval(
of: .weekOfYear, for: today
)!
// 1 মাস স্থানান্তর
let nextMonth = calendar.date(
byAdding: .month, value: 1, to: today
)!
// DateComponents-এর মাধ্যমে স্থানান্তর
var delta = DateComponents()
delta.month = 1
delta.day = 3
let shifted = calendar.date(byAdding: delta, to: today)!
// পরবর্তী শুক্রবার 13 তারিখ
let friday13Components = DateComponents(
weekday: 6, day: 13
)
let nextFriday13 = calendar.nextDate(
after: today, matching: friday13Components,
matchingPolicy: .nextTime
)
EnumerateDates — প্যাটার্ন অনুসারে তারিখ পুনরাবৃত্তির জন্য শক্তিশালী পদ্ধতি। Calendar.enumerateDates(startingAfter:matching:matchingPolicy:using:) প্রতিটি মিলের জন্য ব্লক কল করে, যতক্ষণ না ব্লক stop = true ফেরত দেয়। ক্যালেন্ডার এবং সময়সূচীতে পুনরাবৃত্ত ইভেন্ট জেনারেট করার জন্য ব্যবহৃত হয়। পদ্ধতিটি nextDate সহ ম্যানুয়াল লুপের চেয়ে বেশি কার্যকর, কারণ এটি ICU-তে অপ্টিমাইজ করা।
TimeZone — Calendar-এর একটি অবিচ্ছেদ্য অংশ। সময় অঞ্চল নির্ধারণ করে যে পরম Date কোন ক্যালেন্ডার সময়ের সাথে মিলে যায়। একই Date UTC-তে এবং মস্কোতে ভিন্ন উপাদান দেয়: Date() UTC-তে 10:00 দেখাতে পারে, কিন্তু MSK-তে 13:00। Calendar.timeZone ডিফল্টরূপে TimeZone.current-এর সমান।
Locale সপ্তাহের প্রথম দিন, বছরের প্রথম সপ্তাহে ন্যূনতম দিনের সংখ্যা (minDaysInFirstWeek) এবং মাস/সপ্তাহের দিনের নাম (DateFormatter-এর মাধ্যমে রূপান্তরের সময়) প্রভাবিত করে। Calendar.locale ডিফল্টরূপে Locale.current-এর সমান। রুশ লোকে সপ্তাহ সোমবার থেকে শুরু হয়, আমেরিকান লোকে — রবিবার থেকে।
Calendar.availableIdentifiers সমস্ত সমর্থিত ক্যালেন্ডার আইডেন্টিফায়ারের তালিকা ফেরত দেয়। static property Calendar.availableCalendarIdentifiers — একই আইডেন্টিফায়ার সহ স্ট্রিংয়ের অ্যারে। ক্যালেন্ডার নির্বাচনের UI তৈরি করতে এবং ডিভাইসে নির্দিষ্ট ক্যালেন্ডার সিস্টেমের উপলব্ধতা পরীক্ষা করতে ব্যবহৃত হয়।
// নির্দিষ্ট সময় অঞ্চল সহ Calendar
var utcCalendar = Calendar(identifier: .gregorian)
utcCalendar.timeZone = TimeZone(identifier: "UTC")!
// রুশ লোকেল সহ Calendar
var russianCalendar = Calendar(identifier: .gregorian)
russianCalendar.locale = Locale(identifier: "ru_RU")
// প্রথম কার্যদিবস লোকেলের উপর নির্ভর করে
let firstWeekday = russianCalendar.firstWeekday
// 2 = সোমবার (ru_RU তে)
// উপলব্ধ ক্যালেন্ডারের তালিকা
for identifier in Calendar.availableIdentifiers {
print(identifier)
}
firstWeekday — Calendar-এর একটি প্রপার্টি যা নির্ধারণ করে সপ্তাহের কোন দিনটি প্রথম হিসাবে গণ্য হয়। রুশ লোকে Sunday = 2 (সোমবার প্রথম)। আমেরিকান লোকে Sunday = 1। এটি weekOfMonth এবং weekOfYear-এর কাজকে প্রভাবিত করে: একই তারিখ বিভিন্ন লোকে ভিন্ন সপ্তাহ নম্বরে পড়তে পারে। তারিখ সহ অ্যাপ্লিকেশনের জন্য Calendar.current ব্যবহার করুন অথবা স্পষ্টভাবে firstWeekday সেট করুন।
আসুন ব্যবহারিক পরিস্থিতি বিবেচনা করি যা Calendar-এর ক্ষমতা প্রদর্শন করে। প্রতিটি উদাহরণ iOS ডেভেলপমেন্টের একটি নির্দিষ্ট সমস্যা সমাধান করে এবং ক্যালেন্ডার গণনা ব্যবহারের সঠিক উপায় দেখায়।
Calendar.dateInterval(of: .month, for:) বর্তমান মাসের সীমানা ফেরত দেয়। এই ব্যবধানে Date-এর অন্তর্ভুক্তি পরীক্ষা করা — তারিখটি বর্তমান মাসের কিনা তা নির্ধারণের দ্রুততম উপায়। বিকল্প উপায় — granularity .month সহ Calendar.compare: যদি ফলাফল .orderedSame হয়, তাহলে মাস মিলে যায়।
func isInCurrentMonth(_ date: Date) -> Bool {
let calendar = Calendar.current
let monthInterval = calendar.dateInterval(
of: .month, for: Date()
)!
return monthInterval.contains(date)
}
// মাসে দিনের সংখ্যা
func daysInMonth(for date: Date) -> Int {
let calendar = Calendar.current
return calendar.range(
of: .day, in: .month, for: date
)?.count ?? 0
}
// সঠিক সমাপ্তির সাথে মাস যোগ করা
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:) অন্য উপাদানের প্রসঙ্গে নির্দিষ্ট উপাদানের জন্য অনুমোদিত মানের পরিসর ফেরত দেয়। উদাহরণস্বরূপ, range(of: .day, in: .month, for: date) 31 দিনের মাসের জন্য 1..<32 বা অ-লিপ ইয়ার ফেব্রুয়ারির জন্য 1..<29 ফেরত দেয়। এটি মাসের দিনের সংখ্যা জানার সঠিক উপায়, হার্ডকোড ব্যবহার না করে।
মাস যোগ করা Calendar.date(byAdding:value:to:) এর মাধ্যমে সীমার শেষের তারিখগুলি সঠিকভাবে প্রক্রিয়া করে। যদি 31 জানুয়ারিতে 1 মাস যোগ করা হয়, Calendar 28 ফেব্রুয়ারি ফেরত দেবে (বা লিপ ইয়ারে 29), 3 মার্চ নয়, যা TimeInterval-এর মাধ্যমে সহজে 30 দিন যোগ করলে হত। এটি ক্যালেন্ডার গণনার জন্য TimeInterval না ব্যবহার করার আরেকটি কারণ।
| Calendar পদ্ধতি | উদ্দেশ্য | উদাহরণ |
|---|---|---|
| dateInterval | সময়সীমার সীমানা | মাসের শুরু এবং শেষ |
| range(of:in:for:) | উপাদানের পরিসর | বর্তমান মাসের দিনগুলি |
| date(byAdding:) | তারিখ স্থানান্তর | আজ থেকে +1 মাস |
| isDateInToday | আজ কিনা পরীক্ষা | তারিখ কি আজকের? |
| compare(toGranularity:) | নির্ভুলতার সাথে তুলনা | সময় উপেক্ষা করে একই দিন কিনা |
প্রায়শই জিজ্ঞাসিত প্রশ্ন
Calendar.current ব্যবহারকারীর সিস্টেম সেটিংস থেকে ক্যালেন্ডার ফেরত দেয় — এটি গ্রেগরিয়ান নাও হতে পারে (উদাহরণস্বরূপ, থাইল্যান্ডে বৌদ্ধ)। Calendar(identifier: .gregorian) সর্বদা সেটিংস নির্বিশেষে গ্রেগরিয়ান ক্যালেন্ডার তৈরি করে। তারিখ প্রদর্শনের জন্য Calendar.current ব্যবহার করুন, ব্যবসায়িক লজিকের জন্য — স্পষ্টভাবে নির্বাচিত আইডেন্টিফায়ার।
এটি মাসের ভিন্ন দৈর্ঘ্যের সাথে সম্পর্কিত। যদি বর্তমান তারিখ 31 জানুয়ারি হয়, 1 মাস যোগ করলে 28 ফেব্রুয়ারি পাওয়া যায়, কারণ ফেব্রুয়ারিতে 31 দিন নেই। Calendar স্বয়ংক্রিয়ভাবে মাসের শেষ বৈধ দিন পর্যন্ত তারিখ সম্পূর্ণ করে। সঠিক নিয়ন্ত্রণের জন্য DateComponents ব্যবহার করুন day: 1 সহ মাসের প্রথম দিনে যাওয়ার জন্য।
DateFormatter Calendar.current ব্যবহার করে — ব্যবহারকারীর সিস্টেম ক্যালেন্ডার। যদি অ্যাপ্লিকেশন সবসময় সেটিংস নির্বিশেষে গ্রেগরিয়ান ক্যালেন্ডারে তারিখ দেখাতে চায়, তাহলে formatter.calendar = Calendar(identifier: .gregorian) সেট করুন। এটি সমস্ত ব্যবহারকারীর জন্য অভিন্ন প্রদর্শন নিশ্চিত করে।
Calendar.range(of: .day, in: .year, for: date) 365 বা 366 দিন ফেরত দেয়। সহজ উপায়: Calendar.date(from: DateComponents(year: year, month: 2, day: 29)) != nil — যদি 29 ফেব্রুয়ারি থাকে, বছরটি লিপ ইয়ার। Calendar নিজেই নির্দিষ্ট ক্যালেন্ডার সিস্টেমের নিয়ম বিবেচনা করে।
হ্যাঁ, firstWeekday প্রপার্টি লেখার জন্য উপলব্ধ। পরিবর্তন weekOfMonth, weekOfYear এবং সপ্তাহের নম্বর সম্পর্কিত সমস্ত গণনাকে প্রভাবিত করে। locale = Locale(identifier: “en_US”) সেট করলে firstWeekday স্বয়ংক্রিয়ভাবে 1 (রবিবার) হয়। locale = Locale(identifier: “ru_RU”) সেট করলে firstWeekday স্বয়ংক্রিয়ভাবে 2 (সোমবার) হয়। ম্যানুয়াল সেটিং locale থেকে মান ওভাররাইড করে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন