الحصول على قائمة أنظمة التقويم المتاحة

اكتشف أنظمة التقويم التي تدعمها بيئة جافا سكريبت الخاصة بك

مقدمة

عند بناء تطبيقات لجمهور عالمي، غالبًا ما يحتاج المستخدمون إلى عرض التواريخ بنظام التقويم المفضل لديهم. بينما قد تكون على دراية بالتقويم الميلادي المستخدم في معظم الدول الغربية، تستخدم العديد من الثقافات أنظمة تقويم مختلفة تمامًا مثل التقويم الهجري الإسلامي، التقويم العبري، أو التقويم البوذي.

للسماح للمستخدمين باختيار التقويم المفضل لديهم، تحتاج إلى معرفة أنظمة التقويم التي تدعمها بيئة جافا سكريبت. بدلاً من الاحتفاظ بقائمة مشفرة تصبح قديمة أو تتضمن قيمًا غير مدعومة، توفر جافا سكريبت طريقة لاكتشاف أنظمة التقويم المتاحة في وقت التشغيل.

تقوم طريقة Intl.supportedValuesOf() مع معامل "calendar" بإرجاع مصفوفة تحتوي على جميع معرفات أنظمة التقويم المدعومة في البيئة الحالية. هذا يضمن أن تطبيقك يقدم فقط خيارات التقويم التي تعمل بشكل صحيح.

ما هي أنظمة التقويم

أنظمة التقويم هي طرق مختلفة لتنظيم وحساب الوقت. بينما تتتبع جميع التقويمات الأيام والشهور والسنوات، إلا أنها تستخدم قواعد مختلفة لحساب متى تبدأ السنة، وكم تستمر الشهور، وكيفية حساب الدورات الفلكية.

التقويم الميلادي، الذي تم تقديمه في عام 1582، هو التقويم المدني الأكثر استخدامًا. يستخدم سنة شمسية تبلغ حوالي 365.25 يومًا، مقسمة إلى 12 شهرًا، مع إضافة سنوات كبيسة كل أربع سنوات (مع استثناءات للسنوات المئوية).

تتبع أنظمة التقويم الأخرى قواعد مختلفة. التقويم الإسلامي قمري بحت، حيث تتبع الشهور أطوار القمر. هذا يعني أن السنة الإسلامية أقصر بحوالي 11 يومًا من السنة الشمسية، مما يتسبب في تنقل التواريخ الإسلامية عبر الفصول مع مرور الوقت. التقويمان العبري والصيني هما تقويمان قمريان شمسيان، يجمعان بين الشهور القمرية مع تعديلات للحفاظ على التقويم متزامنًا مع السنة الشمسية.

عندما تقوم بتنسيق التواريخ في جافا سكريبت، يحدد نظام التقويم أرقام السنة والشهر واليوم التي تظهر. نفس اللحظة الزمنية لها تمثيلات تاريخ مختلفة في أنظمة التقويم المختلفة.

استخدام Intl.supportedValuesOf للحصول على أنظمة التقويم

تقبل طريقة Intl.supportedValuesOf() معلمة نصية تحدد نوع القيم التي يجب إرجاعها. للحصول على أنظمة التقويم، مرر "calendar":

const calendars = Intl.supportedValuesOf("calendar");
console.log(calendars);
// Output: ["buddhist", "chinese", "coptic", "dangi", "ethioaa",
//          "ethiopic", "gregory", "hebrew", "indian", "islamic",
//          "islamic-civil", "islamic-rgsa", "islamic-tbla",
//          "islamic-umalqura", "iso8601", "japanese", "persian", "roc"]

تُرجع الطريقة مصفوفة من السلاسل النصية التي تمثل معرفات التقويم. تتبع هذه المعرفات معيار Unicode CLDR (مستودع بيانات اللغات المشتركة)، الذي يوفر طريقة متسقة للإشارة إلى أنظمة التقويم عبر المنصات ولغات البرمجة المختلفة.

تتميز المصفوفة المُرجعة بالخصائص التالية:

  • القيم مرتبة تصاعدياً حسب الترتيب الأبجدي
  • تمت إزالة القيم المكررة
  • كل معرف يستخدم الأحرف الصغيرة والشرطات
  • تتضمن القائمة جميع أنظمة التقويم المدعومة من قبل تنفيذ جافا سكريبت

تدعم المتصفحات وبيئات جافا سكريبت المختلفة مجموعات مختلفة من التقويمات، على الرغم من أن جميع المتصفحات الحديثة تدعم مجموعة أساسية من التقويمات الشائعة.

فهم معرفات التقويم

يمثل كل معرف تقويم نظام تقويم محدد تستخدمه ثقافة واحدة أو أكثر. فيما يلي المعرفات الأكثر شيوعاً:

يمثل معرف "gregory" التقويم الميلادي (الغريغوري)، وهو التقويم المدني القياسي المستخدم في معظم البلدان. هذا هو التقويم الذي تستخدمه في حياتك اليومية إذا كنت تعيش في الولايات المتحدة أو أوروبا أو معظم أنحاء العالم الأخرى.

يمثل معرف "buddhist" التقويم البوذي التايلاندي، الذي يستخدم نفس هيكل الشهر واليوم مثل التقويم الميلادي ولكنه يحسب السنوات من ميلاد بوذا (543 قبل الميلاد في التقويم الميلادي). سنة 2025 في التقويم الميلادي هي سنة 2568 في التقويم البوذي.

يمثل معرف "chinese" التقويم الصيني التقليدي، وهو تقويم قمري شمسي حيث تتبع الشهور أطوار القمر وتتوافق السنوات مع الفترة المدارية لكوكب المشتري. يُستخدم التقويم الصيني لتحديد العطلات التقليدية مثل رأس السنة الصينية.

يمثل معرف "islamic" التقويم الهجري الإسلامي، وهو تقويم قمري بحت يتكون من 12 شهراً من 29 أو 30 يوماً. تُحسب السنوات من الهجرة، عندما هاجر النبي محمد من مكة إلى المدينة في 622 ميلادية.

يمثل معرف "hebrew" التقويم العبري، وهو تقويم قمري شمسي يُستخدم للمناسبات الدينية اليهودية. يحسب السنوات من تاريخ الخلق التقليدي (3761 قبل الميلاد في التقويم الميلادي).

يمثل معرف "japanese" التقويم الياباني، الذي يستخدم نفس هيكل الشهر واليوم مثل التقويم الميلادي ولكنه يقسم الوقت إلى عصور بناءً على الإمبراطور الحاكم. العصر الحالي هو ريوا، الذي بدأ في عام 2019.

يمثل معرف "persian" التقويم الهجري الشمسي المستخدم في إيران وأفغانستان. إنه تقويم شمسي مع سنوات محسوبة من الهجرة، مما يجعله مختلفاً عن التقويم الإسلامي القمري.

تشمل المعرفات الإضافية "coptic" (التقويم القبطي الأرثوذكسي)، و"dangi" (التقويم الكوري التقليدي)، و"ethiopic" (التقويم الإثيوبي)، و"indian" (التقويم الوطني الهندي)، و"roc" (تقويم جمهورية الصين المستخدم في تايوان).

بعض المعرفات لها متغيرات مثل "islamic-civil"، و"islamic-rgsa"، و"islamic-tbla"، و"islamic-umalqura"، والتي تمثل طرق حساب مختلفة للتقويم الإسلامي.

يمثل معرف "iso8601" تقويم ISO 8601، وهو في الأساس التقويم الميلادي ولكنه يستخدم دائماً التقويم الميلادي الاستقرائي (تمديد التقويم الميلادي للخلف قبل إدخاله في عام 1582).

مشاهدة أنظمة التقويم قيد التنفيذ

لفهم كيفية تأثير أنظمة التقويم على تنسيق التاريخ، قم بتنسيق نفس التاريخ باستخدام تقويمات مختلفة:

const date = new Date("2025-10-15");

const gregorian = new Intl.DateTimeFormat("en-US", {
  calendar: "gregory",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const islamic = new Intl.DateTimeFormat("en-US", {
  calendar: "islamic",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const hebrew = new Intl.DateTimeFormat("en-US", {
  calendar: "hebrew",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const buddhist = new Intl.DateTimeFormat("en-US", {
  calendar: "buddhist",
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(gregorian.format(date));
// Output: "October 15, 2025"

console.log(islamic.format(date));
// Output: "Rabi' II 16, 1447 AH"

console.log(hebrew.format(date));
// Output: "Tishrei 23, 5786"

console.log(buddhist.format(date));
// Output: "October 15, 2568 BE"

يمثل كائن Date في جافا سكريبت نفس اللحظة الزمنية، لكن كل نظام تقويم يعبر عن تلك اللحظة بقيم مختلفة للسنة والشهر واليوم. يتوافق تاريخ 15 أكتوبر 2025 في التقويم الميلادي مع 16 ربيع الثاني 1447 في التقويم الهجري، و23 تشري 5786 في التقويم العبري، و15 أكتوبر 2568 في التقويم البوذي.

هذا يوضح سبب ضرورة تحديد نظام التقويم المراد استخدامه عند تنسيق التواريخ للمستخدمين الذين يتبعون تقويمات مختلفة.

بناء أداة اختيار التقويم

عند إنشاء واجهات مستخدم تتيح للمستخدمين اختيار التقويم المفضل لديهم، قم بالاستعلام عن التقويمات المتاحة وبناء أداة اختيار ديناميكية:

function buildCalendarSelector() {
  const calendars = Intl.supportedValuesOf("calendar");
  const select = document.createElement("select");
  select.id = "calendar-selector";

  calendars.forEach(calendar => {
    const option = document.createElement("option");
    option.value = calendar;
    option.textContent = calendar;
    select.appendChild(option);
  });

  return select;
}

const selector = buildCalendarSelector();
document.body.appendChild(selector);

هذا ينشئ قائمة منسدلة تحتوي على كل تقويم مدعوم. ومع ذلك، فإن المعرفات التقنية مثل "gregory" و"islamic" ليست سهلة الاستخدام. يحتاج المستخدمون إلى رؤية أسماء وصفية بلغتهم الخاصة.

عرض أسماء التقويمات بصيغة مقروءة للإنسان

تقوم واجهة برمجة التطبيقات Intl.DisplayNames بتحويل معرّفات التقويم إلى أسماء مقروءة للإنسان. استخدمها لإنشاء محدد تقويم أفضل:

function buildCalendarSelector(locale = "en-US") {
  const calendars = Intl.supportedValuesOf("calendar");
  const displayNames = new Intl.DisplayNames([locale], { type: "calendar" });

  const select = document.createElement("select");
  select.id = "calendar-selector";

  calendars.forEach(calendar => {
    const option = document.createElement("option");
    option.value = calendar;
    option.textContent = displayNames.of(calendar);
    select.appendChild(option);
  });

  return select;
}

const selector = buildCalendarSelector("en-US");
document.body.appendChild(selector);

الآن تعرض القائمة المنسدلة أسماء مثل "التقويم الميلادي"، "التقويم الهجري"، و"التقويم العبري" بدلاً من المعرّفات التقنية.

يمكنك عرض أسماء التقويمات بلغات مختلفة عن طريق تغيير الإعدادات المحلية:

const calendars = ["gregory", "islamic", "hebrew", "buddhist", "chinese"];

const englishNames = new Intl.DisplayNames(["en-US"], { type: "calendar" });
const frenchNames = new Intl.DisplayNames(["fr-FR"], { type: "calendar" });
const arabicNames = new Intl.DisplayNames(["ar-SA"], { type: "calendar" });

calendars.forEach(calendar => {
  console.log(`${calendar}:`);
  console.log(`  English: ${englishNames.of(calendar)}`);
  console.log(`  French: ${frenchNames.of(calendar)}`);
  console.log(`  Arabic: ${arabicNames.of(calendar)}`);
});

// النتيجة:
// gregory:
//   English: Gregorian Calendar
//   French: calendrier grégorien
//   Arabic: التقويم الميلادي
// islamic:
//   English: Islamic Calendar
//   French: calendrier musulman
//   Arabic: التقويم الهجري
// ...

هذا يسمح للمستخدمين برؤية أسماء التقويمات بلغتهم المفضلة.

التحقق مما إذا كان تقويم معين مدعومًا

قبل استخدام تقويم في تطبيقك، تحقق مما إذا كانت بيئة جافاسكريبت تدعمه. هذا يمنع أخطاء وقت التشغيل ويسمح لك بتنفيذ سلوك احتياطي:

function isCalendarSupported(calendar) {
  const supported = Intl.supportedValuesOf("calendar");
  return supported.includes(calendar);
}

if (isCalendarSupported("islamic")) {
  const formatter = new Intl.DateTimeFormat("en-US", {
    calendar: "islamic",
    year: "numeric",
    month: "long",
    day: "numeric"
  });
  console.log(formatter.format(new Date()));
} else {
  console.log("Islamic calendar is not supported");
}

هذا النمط يعمل مع أي معرّف تقويم. يمكنك استخدامه لإظهار أو إخفاء خيارات التقويم في واجهة المستخدم الخاصة بك، أو للرجوع إلى تقويم افتراضي عندما يكون التقويم المفضل غير متوفر.

إنشاء دالة قابلة لإعادة الاستخدام للكشف عن الميزات

قم ببناء دالة عامة للتحقق من دعم التقويم والتعامل مع التقويمات المفقودة بسلاسة:

function getCalendarOrFallback(preferredCalendar, fallbackCalendar = "gregory") {
  const supported = Intl.supportedValuesOf("calendar");

  if (supported.includes(preferredCalendar)) {
    return preferredCalendar;
  }

  if (supported.includes(fallbackCalendar)) {
    return fallbackCalendar;
  }

  return supported[0];
}

const calendar = getCalendarOrFallback("islamic", "gregory");
const formatter = new Intl.DateTimeFormat("en-US", {
  calendar,
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(formatter.format(new Date()));

تحاول هذه الدالة استخدام التقويم المفضل، وتعود إلى التقويم الاحتياطي المحدد إذا كان التقويم المفضل غير متوفر، وفي النهاية تعيد أول تقويم متاح إذا كان كلاهما غير مدعوم.

تصفية التقويمات لتطبيقك

معظم التطبيقات لا تحتاج إلى دعم كل نظام تقويم. قم بتصفية القائمة لتشمل فقط التقويمات ذات الصلة بمستخدميك:

function getRelevantCalendars(allowedCalendars) {
  const supported = Intl.supportedValuesOf("calendar");
  return allowedCalendars.filter(calendar => supported.includes(calendar));
}

const allowedCalendars = ["gregory", "islamic", "hebrew", "buddhist"];
const availableCalendars = getRelevantCalendars(allowedCalendars);

console.log(availableCalendars);
// Output: ["gregory", "islamic", "hebrew", "buddhist"]
// (assuming all are supported in the current environment)

هذا يضمن أنك تقدم فقط التقويمات التي تلبي متطلباتك وتعمل في متصفح المستخدم.

يمكنك دمج هذا مع اختيار التقويم لإنشاء واجهة مستخدم مركزة:

function buildFilteredCalendarSelector(allowedCalendars, locale = "en-US") {
  const supported = Intl.supportedValuesOf("calendar");
  const available = allowedCalendars.filter(cal => supported.includes(cal));
  const displayNames = new Intl.DisplayNames([locale], { type: "calendar" });

  const select = document.createElement("select");

  available.forEach(calendar => {
    const option = document.createElement("option");
    option.value = calendar;
    option.textContent = displayNames.of(calendar);
    select.appendChild(option);
  });

  return select;
}

const selector = buildFilteredCalendarSelector(
  ["gregory", "islamic", "hebrew", "buddhist"],
  "en-US"
);
document.body.appendChild(selector);

هذا ينشئ أداة اختيار تعرض فقط التقويمات التي تريد دعمها، بأسماء مقروءة للإنسان، مضمونة للعمل في البيئة الحالية.

تجميع التقاويم حسب الفئة

بالنسبة للتطبيقات التي تدعم العديد من التقاويم، قم بتجميعها حسب النوع أو المنطقة لتحسين قابلية الاستخدام:

function groupCalendars() {
  const calendars = Intl.supportedValuesOf("calendar");

  const groups = {
    solar: ["gregory", "iso8601", "persian", "ethiopic", "coptic"],
    lunar: ["islamic", "islamic-civil", "islamic-rgsa", "islamic-tbla", "islamic-umalqura"],
    lunisolar: ["hebrew", "chinese", "dangi"],
    erasBased: ["japanese", "roc", "buddhist"],
    other: []
  };

  const grouped = {
    solar: [],
    lunar: [],
    lunisolar: [],
    erasBased: [],
    other: []
  };

  calendars.forEach(calendar => {
    let placed = false;

    for (const [group, members] of Object.entries(groups)) {
      if (members.includes(calendar)) {
        grouped[group].push(calendar);
        placed = true;
        break;
      }
    }

    if (!placed) {
      grouped.other.push(calendar);
    }
  });

  return grouped;
}

const grouped = groupCalendars();
console.log(grouped);
// Output:
// {
//   solar: ["gregory", "iso8601", "persian", "ethiopic", "coptic"],
//   lunar: ["islamic", "islamic-civil", "islamic-rgsa", ...],
//   lunisolar: ["hebrew", "chinese", "dangi"],
//   erasBased: ["japanese", "roc", "buddhist"],
//   other: ["ethioaa", "indian"]
// }

يساعد هذا التنظيم المستخدمين على فهم خصائص أنظمة التقويم المختلفة والعثور على ما يحتاجونه.

التعامل مع البيئات غير المدعومة

تمت إضافة طريقة Intl.supportedValuesOf() إلى جافاسكريبت في عام 2022. المتصفحات القديمة لا تدعمها. تحقق مما إذا كانت الطريقة موجودة قبل استخدامها:

function getCalendars() {
  if (typeof Intl.supportedValuesOf === "function") {
    return Intl.supportedValuesOf("calendar");
  }

  return ["gregory"];
}

const calendars = getCalendars();
console.log(calendars);

هذا يعيد القائمة الكاملة للتقاويم المدعومة في المتصفحات الحديثة، ويعود إلى التقويم الغريغوري فقط في البيئات القديمة.

للحصول على توافق أفضل مع الإصدارات السابقة، قدم قائمة احتياطية أكثر اكتمالاً:

function getCalendars() {
  if (typeof Intl.supportedValuesOf === "function") {
    return Intl.supportedValuesOf("calendar");
  }

  return [
    "buddhist",
    "chinese",
    "coptic",
    "ethiopic",
    "gregory",
    "hebrew",
    "indian",
    "islamic",
    "japanese",
    "persian",
    "roc"
  ];
}

هذا يوفر مجموعة معقولة من التقاويم للمتصفحات القديمة، على الرغم من أنك لا تستطيع ضمان عمل جميعها في كل بيئة.

فهم الفرق بين التقويم واللغة المحلية

التقويم واللغة المحلية مفهومان مرتبطان ولكنهما منفصلان. تحدد اللغة المحلية لغة وتنسيقات العرض الإقليمية، بينما يحدد التقويم نظام التقويم المستخدم.

يمكن للغة محلية واحدة استخدام تقويمات متعددة. على سبيل المثال، يستخدم المتحدثون باللغة العربية في المملكة العربية السعودية عادةً التقويم الهجري للأغراض الدينية والتقويم الميلادي للأغراض المدنية. يمكنك تنسيق التواريخ باللغة العربية باستخدام أي من التقويمين:

const date = new Date("2025-10-15");

const arabicGregorian = new Intl.DateTimeFormat("ar-SA", {
  calendar: "gregory",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const arabicIslamic = new Intl.DateTimeFormat("ar-SA", {
  calendar: "islamic",
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(arabicGregorian.format(date));
// Output: "١٥ أكتوبر ٢٠٢٥"

console.log(arabicIslamic.format(date));
// Output: "١٦ ربيع الآخر ١٤٤٧ هـ"

كلاهما يستخدم النص والأرقام العربية، ولكنهما يعرضان تواريخ مختلفة وفقًا لتقويماتهما المعنية.

وبالمقابل، يمكنك تنسيق نفس التقويم بلغات مختلفة:

const date = new Date("2025-10-15");

const englishIslamic = new Intl.DateTimeFormat("en-US", {
  calendar: "islamic",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const arabicIslamic = new Intl.DateTimeFormat("ar-SA", {
  calendar: "islamic",
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(englishIslamic.format(date));
// Output: "Rabi' II 16, 1447 AH"

console.log(arabicIslamic.format(date));
// Output: "١٦ ربيع الآخر ١٤٤٧ هـ"

كلاهما يعرض التاريخ الهجري، ولكن باستخدام لغات وأنظمة أرقام مختلفة.

متى يجب الاستعلام عن التقويمات المتاحة

استعلم عن التقويمات المتاحة في الحالات التالية:

عند بناء واجهة اختيار التقويم، استدعِ Intl.supportedValuesOf("calendar") لتعبئة الخيارات. هذا يضمن أنك تعرض فقط التقويمات التي تعمل في البيئة الحالية.

عند تنفيذ ميزات تعتمد على التقويم، تحقق مما إذا كان التقويم المطلوب مدعومًا قبل استخدامه. هذا يمنع الأخطاء ويسمح بالرجوع بسلاسة إلى تقويمات بديلة.

عند تخزين تفضيلات المستخدم، تحقق من صحة اختيارات التقويم مقابل القائمة المدعومة. هذا يضمن أن التفضيلات المحفوظة تظل صالحة عبر الأجهزة والمتصفحات المختلفة.

عند الانتقال بين البيئات، تحقق من دعم التقويم في كل من البيئة المصدر والبيئة المستهدفة. يمكن أن يختلف دعم التقويم بين إصدارات المتصفح، وإصدارات Node.js، وبيئات تشغيل JavaScript المختلفة.

عند تحميل بيانات تعتمد على التقويم، تحقق من توفر التقويم قبل محاولة تحليل أو تنسيق التواريخ. هذا يمنع أخطاء وقت التشغيل عند العمل مع التواريخ في أنظمة تقويم محددة.