টেম্পোরাল সহ গ্লোবাল ক্যালেন্ডার সিস্টেমকে সাপোর্ট করা

ওয়েব ফিচার: Temporal

প্রথাগত JavaScript Date অবজেক্ট প্রোলেপ্টিক গ্রেগরিয়ান ক্যালেন্ডারের উপর ভিত্তি করে তৈরি, তাই ইসলামিক (চন্দ্র), হিব্রু (চন্দ্র-সৌর) বা চাইনিজ (চন্দ্র-সৌর) ক্যালেন্ডারের মতো অন্যান্য ক্যালেন্ডার সিস্টেমের উপর নির্ভর করেন এমন ব্যবহারকারীদের জন্য অ্যাপ্লিকেশন তৈরি করা চ্যালেঞ্জিং হয়ে ওঠে। ডেভেলপারদের আগে এইসব সিস্টেমের জন্য জটিল থার্ড-পার্টি লাইব্রেরি বা ম্যানুয়াল গণনার উপর নির্ভর করতে হত।

Temporal API একাধিক ক্যালেন্ডার সিস্টেমের জন্য ফার্স্ট-ক্লাস সহায়তা প্রদান করে। তারিখ অবজেক্টের সাথে ক্যালেন্ডার শনাক্তকারী যুক্ত করার মাধ্যমে, Temporal বিভিন্ন সাংস্কৃতিক প্রেক্ষাপটের জন্য প্রয়োজনীয় জটিল পাটিগণিত এবং ফর্ম্যাটিং নেটিভভাবে পরিচালনা করে।

কীভাবে প্রয়োগ করতে হয়

Temporal ব্যবহার করে গ্লোবাল ক্যালেন্ডার সিস্টেমকে সহায়তা করতে:

  1. ক্যালেন্ডার অ্যাসোসিয়েট করা (বাধ্যতামূলক): টেম্পোরাল অবজেক্ট (যেমন Temporal.PlainDate) তৈরি বা কনভার্ট করার সময়, ক্যালেন্ডার-সংবেদনশীল অপারেশন পারফর্ম করার জন্য আপনাকে অবশ্যই withCalendar() ব্যবহার করে কাঙ্ক্ষিত ক্যালেন্ডার সিস্টেম নির্দিষ্ট করতে হবে।
  2. স্টেবল আইডেন্টিফায়ার ব্যবহার করুন (লুনিসোলার ক্যালেন্ডারের জন্য বাধ্যতামূলক): লুনিসোলার ক্যালেন্ডারে বিভিন্ন বছরের নির্দিষ্ট মাস শনাক্ত করতে আপনাকে অবশ্যই সংখ্যাসূচক month ইনডেক্সের পরিবর্তে monthCode ব্যবহার করতে হবে। শুধুমাত্র সেইসব ক্যালেন্ডারের জন্য এটি ব্যবহার করুন যেগুলিতে লিপ মাস আছে, যেমন হিব্রু ও চাইনিজ ক্যালেন্ডার।
  3. ক্যালেন্ডার ইনভেরিয়েন্ট মেনে চলুন (বাধ্যতামূলক): মাস বা দিনের মধ্যে দিয়ে ইটারেট করার সময়, আপনাকে অবশ্যই নির্দিষ্ট ভ্যালু (যেমন, এক বছরে ১২ মাস বা এক মাসে ৩১ দিন) ধরে নিলে চলবে না। আপনার কোড যাতে সব ক্যালেন্ডারে কাজ করে তা নিশ্চিত করতে monthsInYear এবং daysInMonth-এর মতো প্রপার্টি ব্যবহার করুন।
  4. ক্যালেন্ডার-অ্যাওয়ার তুলনা ব্যবহার করুন (বাধ্যতামূলক): কোনও নির্দিষ্ট ক্যালেন্ডার সিস্টেমের মধ্যে তারিখ তুলনা করার সময়, আপনাকে ম্যানুয়ালি বছর/মাস/দিনের প্রপার্টি তুলনা করার পরিবর্তে অবশ্যই Temporal.PlainDate.compare() ব্যবহার করতে হবে। এটি ক্যালেন্ডারের নিয়মের মধ্যে সময়ানুক্রমিক ক্রম সঠিকভাবে ম্যানেজ করে।

উদাহরণ কোড: ক্যালেন্ডার কনভার্ট ও ইটারেট করা

// 1. Helper to check calendar support
function isCalendarSupported(calendarId) {
  try {
    return Intl.supportedValuesOf('calendar').includes(calendarId);
  } catch {
    // Fallback for environments where supportedValuesOf is not available
    return false;
  }
}

// 2. Get current date in default ISO 8601 calendar
const isoDate = Temporal.Now.plainDateISO();

// 3. Convert to Hebrew calendar if supported
const calendarId = 'hebrew';
const targetDate = isCalendarSupported(calendarId) 
  ? isoDate.withCalendar(calendarId)
  : isoDate; // Fallback to ISO if not supported

if (targetDate.calendar.id !== calendarId) {
  console.warn(`Calendar ${calendarId} not supported; falling back to ISO 8601`);
}

// 4. Log properties specific to the calendar
console.log(`Calendar: ${targetDate.calendar.id}`);
console.log(`Year: ${targetDate.year}`);
console.log(`Month Code: ${targetDate.monthCode}`); // Stable across leap years

// 5. Safely iterate through months in the current year
for (let m = 1; m <= targetDate.monthsInYear; m++) {
  console.log(`Month ${m} has ${targetDate.with({ month: m }).daysInMonth} days.`);
}

// 6. Compare dates within the same calendar
const today = Temporal.Now.plainDateISO().withCalendar(calendarId);
const comparison = Temporal.PlainDate.compare(targetDate, today);
const relative = comparison < 0 ? 'Past' : comparison > 0 ? 'Future' : 'Today';
console.log(`Timeline: ${relative}`);

// 7. Format for display using toLocaleString (including era for era-based calendars like 'japanese')
const localizedDisplay = targetDate.toLocaleString('en-u-ca-hebrew', {
  day: 'numeric',
  month: 'long',
  year: 'numeric',
  era: 'long'
});

স্ট্র্যাটেজিক প্রয়োগ ও পেশাদার পদ্ধতি

  • মাস লুপ করার সময় monthsInYear-কে সর্বোচ্চ সীমা হিসেবে ব্যবহার করুন, ১২ ধরে নেবেন না।
  • অবশ্যই monthCode ব্যবহার করুন, যাতে বছর যাই হোক না কেন, লিপ মাস (যেমন, হিব্রু বা চাইনিজ) ব্যবহার করা ক্যালেন্ডারে নির্দিষ্ট মাস শনাক্ত করা যায়।
  • date.month === 12 বছরের শেষ মাস বলে ধরে নেবেন না। date.month === date.monthsInYear ব্যবহার করুন।
  • মনে করবেন না যে inLeapYear === true-এর অর্থ হল বছরটি মাত্র একদিন দীর্ঘ। লুনিসোলার ক্যালেন্ডারে, এটি একটি সম্পূর্ণ লিপ মাস যোগ করতে পারে।
  • ম্যানুয়ালি বছর/মাস/দিন প্রপার্টি তুলনা করার পরিবর্তে নির্দিষ্ট ক্যালেন্ডার সিস্টেমে দুটি তারিখ তুলনা করার সময় Temporal.PlainDate.compare() ব্যবহার করুন।
  • ম্যানুয়াল স্ট্রিং কনক্যাটেনেশনের পরিবর্তে ব্যবহারকারীদের জন্য তারিখ ফর্ম্যাট করতে toLocaleString() ব্যবহার করুন।
  • ক্যালেন্ডার-নির্দিষ্ট টেম্পোরাল অবজেক্ট তৈরি করার আগে, Intl.supportedValuesOf('calendar') ব্যবহার করে টার্গেট ক্যালেন্ডার সিস্টেমটি এনভায়রনমেন্টের সাথে মানানসই কিনা তা যাচাই করুন।
  • মনে রাখবেন যে কিছু ক্যালেন্ডার (যেমন ইসলামিক ক্যালেন্ডারের বিভিন্ন রূপ) নির্দিষ্ট গণনার পরিবর্তে চাক্ষুষ পর্যবেক্ষণের উপর নির্ভর করতে পারে। Temporal API এনভায়রনমেন্টের Intl প্রয়োগ অনুসরণ করে, যা সাধারণত আনুমানিক হিসেব ব্যবহার করে। গুরুত্বপূর্ণ সাংস্কৃতিক বা ধর্মীয় তারিখ গণনা করার জন্য, ডোমেন বিশেষজ্ঞদের সাথে যাচাই করুন বা বিশেষ লাইব্রেরি ব্যবহার করুন।
  • toLocaleString() ব্যবহার করে, যুগ ব্যবহার করে এমন ক্যালেন্ডার (যেমন, জাপানি, বৌদ্ধ) ব্যবহার করার সময় যুগের নামের জন্য অ্যাকাউন্ট করুন।

ফলব্যাক স্ট্র্যাটেজি

টেম্পোরালের জন্য ফলব্যাক ও ব্রাউজার সহায়তা

যেসব ব্রাউজার এখনও নেটিভ Temporal API সাপোর্ট করে না, সেগুলির জন্য ফিচার শনাক্তকরণ ব্যবহার করুন এবং ডায়নামিকভাবে temporal-polyfill (~15 KB min+gz) লোড করুন।

মনে রাখবেন, temporal-polyfill ইমপোর্ট করলে, Temporal অবজেক্ট গ্লোবাল স্কোপে অটোমেটিক অ্যাসাইন হয় না। আপনার কোড globalThis.Temporal-এর উপর নির্ভর করলে, এটি স্পষ্টভাবে অ্যাসাইন করুন।

// Check if Temporal is supported natively
(async () => {
  if (typeof Temporal === 'undefined') {
    // Load the polyfill conditionally
    const module = await import('https://esm.sh/temporal-polyfill');
    globalThis.Temporal = module.Temporal;
    // Extend Date.prototype if needed
    Date.prototype.toTemporalInstant = module.toTemporalInstant;
  }
  initializeApp();
})();