واجهة برمجة تطبيقات Intl.DateTimeFormat
نسّق التواريخ والأوقات لأي لغة بدون استخدام مكتبات خارجية
المقدمة
يتم عرض التواريخ بشكل مختلف حول العالم. على سبيل المثال، يظهر 15 يناير 2024 كـ 1/15/2024 في الولايات المتحدة، و15/1/2024 في المملكة المتحدة، و2024/1/15 في اليابان. كذلك، تختلف صيغ الوقت؛ حيث يستخدم الأمريكيون نظام 12 ساعة مع AM وPM، بينما تعتمد معظم دول العالم نظام 24 ساعة.
كتابة منطق تنسيق التواريخ يدوياً لمختلف المناطق عملية معقدة وعرضة للأخطاء. إذ يجب مراعاة ترتيب اليوم والشهر، والفواصل، وصيغ الوقت، وتحويل المناطق الزمنية، والحالات الخاصة مثل التقويمات غير الميلادية.
واجهة البرمجة Intl.DateTimeFormat توفر لك حلاً لهذه المشكلة. فهي تقدم تنسيق تواريخ وأوقات مدمج وواعٍ للغة والموقع في جميع المتصفحات الحديثة، ودون الحاجة إلى مكتبات خارجية.
الاستخدام الأساسي
أسهل طريقة لتنسيق التاريخ هي إنشاء كائن Intl.DateTimeFormat واستخدام الطريقة format() عليه.
const date = new Date(2024, 0, 15, 14, 30);
const formatter = new Intl.DateTimeFormat("en-US");
formatter.format(date);
// "1/15/2024"
غيّر اللغة لترى اختلاف طرق عرض التواريخ.
const ukFormatter = new Intl.DateTimeFormat("en-GB");
ukFormatter.format(date);
// "15/01/2024"
const japanFormatter = new Intl.DateTimeFormat("ja-JP");
japanFormatter.format(date);
// "2024/1/15"
سيتم عرض نفس التاريخ بثلاث طرق مختلفة حسب عادات كل منطقة.
فهم إعدادات الموقع (اللغة والمنطقة)
إعدادات الموقع (locale) هي سلسلة نصية تحدد اللغة والتفضيلات الإقليمية للمستخدم. يتبع تنسيقها معيار BCP 47: رمز اللغة ويليه بشكل اختياري رمز المنطقة.
أمثلة شائعة على أنماط locale:
"en" // English (generic)
"en-US" // English (United States)
"en-GB" // English (United Kingdom)
"es" // Spanish (generic)
"es-MX" // Spanish (Mexico)
"es-ES" // Spanish (Spain)
"zh-CN" // Chinese (China, Simplified)
"zh-TW" // Chinese (Taiwan, Traditional)
إذا لم تضع متغير اللغة، سيستخدم المتصفح اللغة الافتراضية للمستخدم.
const formatter = new Intl.DateTimeFormat();
formatter.format(date);
// Output varies based on user's browser locale
يمكنك أيضًا تمرير مصفوفة من الإعدادات المحلية. سيختار المتصفح أول إعداد مدعوم.
const formatter = new Intl.DateTimeFormat(["es-MX", "es", "en"]);
// Uses Spanish (Mexico) if available, falls back to generic Spanish, then English
نظرة عامة على خيارات التنسيق
منشئ Intl.DateTimeFormat يقبل كائن خيارات يحدد ما سيظهر في النتيجة النهائية للتنسيق. هناك طريقتان للتنسيق.
الطريقة الأولى تستخدم أنماط جاهزة، وهي تعطيك تنسيقات شائعة بسرعة.
const formatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "full",
timeStyle: "short"
});
formatter.format(date);
// "Monday, January 15, 2024 at 2:30 PM"
النهج الثاني يستخدم خيارات المكونات، والتي تمنحك تحكمًا دقيقًا في كل جزء من أجزاء التاريخ.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric"
});
formatter.format(date);
// "January 15, 2024 at 2:30 PM"
لا يمكنك دمج الاختصارات الأسلوبية مع خيارات المكونات. اختر نهجًا واحدًا فقط لكل مُنسق.
اختصارات الأسلوب
خيارات dateStyle وtimeStyle توفر أربع مستويات تنسيق جاهزة مسبقًا.
خيار dateStyle يقوم بتنسيق جزء التاريخ.
const date = new Date(2024, 0, 15);
const full = new Intl.DateTimeFormat("en-US", { dateStyle: "full" });
full.format(date);
// "Monday, January 15, 2024"
const long = new Intl.DateTimeFormat("en-US", { dateStyle: "long" });
long.format(date);
// "January 15, 2024"
const medium = new Intl.DateTimeFormat("en-US", { dateStyle: "medium" });
medium.format(date);
// "Jan 15, 2024"
const short = new Intl.DateTimeFormat("en-US", { dateStyle: "short" });
short.format(date);
// "1/15/24"
خيار timeStyle يقوم بتنسيق جزء الوقت.
const date = new Date(2024, 0, 15, 14, 30, 45);
const full = new Intl.DateTimeFormat("en-US", { timeStyle: "full" });
full.format(date);
// "2:30:45 PM Eastern Standard Time"
const long = new Intl.DateTimeFormat("en-US", { timeStyle: "long" });
long.format(date);
// "2:30:45 PM EST"
const medium = new Intl.DateTimeFormat("en-US", { timeStyle: "medium" });
medium.format(date);
// "2:30:45 PM"
const short = new Intl.DateTimeFormat("en-US", { timeStyle: "short" });
short.format(date);
// "2:30 PM"
قم بدمج الخيارين معًا لتنسيق التاريخ والوقت في نفس الوقت.
const formatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "medium",
timeStyle: "short"
});
formatter.format(date);
// "Jan 15, 2024, 2:30 PM"
اختصارات الأسلوب تتكيف تلقائيًا مع تقاليد المنطقة المحلية.
const usFormatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "short",
timeStyle: "short"
});
usFormatter.format(date);
// "1/15/24, 2:30 PM"
const deFormatter = new Intl.DateTimeFormat("de-DE", {
dateStyle: "short",
timeStyle: "short"
});
deFormatter.format(date);
// "15.1.24, 14:30"
التنسيق الألماني يستخدم النقاط كفواصل، ويعكس ترتيب اليوم والشهر، ويعرض الوقت بصيغة 24 ساعة. التنسيق الأمريكي يستخدم الشرط المائلة، ويضع الشهر أولاً، ويعرض الوقت بصيغة 12 ساعة مع AM/PM. نفس الخيارات، لكن المخرجات تختلف حسب المنطقة.
خيارات المكونات
خيارات المكونات تمنحك تحكمًا دقيقًا فيما يتم عرضه وكيفية عرضه. كل خيار يحدد جزءًا من التاريخ أو الوقت.
خيار year يعرض السنة.
const formatter = new Intl.DateTimeFormat("en-US", { year: "numeric" });
formatter.format(date);
// "2024"
const twoDigit = new Intl.DateTimeFormat("en-US", { year: "2-digit" });
twoDigit.format(date);
// "24"
خيار month يعرض الشهر بعدة تنسيقات مختلفة.
const numeric = new Intl.DateTimeFormat("en-US", { month: "numeric" });
numeric.format(date);
// "1"
const twoDigit = new Intl.DateTimeFormat("en-US", { month: "2-digit" });
twoDigit.format(date);
// "01"
const long = new Intl.DateTimeFormat("en-US", { month: "long" });
long.format(date);
// "January"
const short = new Intl.DateTimeFormat("en-US", { month: "short" });
short.format(date);
// "Jan"
const narrow = new Intl.DateTimeFormat("en-US", { month: "narrow" });
narrow.format(date);
// "J"
خيار day يعرض يوم الشهر.
const formatter = new Intl.DateTimeFormat("en-US", { day: "numeric" });
formatter.format(date);
// "15"
const twoDigit = new Intl.DateTimeFormat("en-US", { day: "2-digit" });
twoDigit.format(date);
// "15"
خيار weekday يعرض يوم الأسبوع.
const long = new Intl.DateTimeFormat("en-US", { weekday: "long" });
long.format(date);
// "Monday"
const short = new Intl.DateTimeFormat("en-US", { weekday: "short" });
short.format(date);
// "Mon"
const narrow = new Intl.DateTimeFormat("en-US", { weekday: "narrow" });
narrow.format(date);
// "M"
اجمع بين خيارات المكونات المختلفة لإنشاء تنسيقات تواريخ مخصصة.
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
formatter.format(date);
// "Monday, January 15, 2024"
يتولى المتصفح التحكم في المسافات وعلامات الترقيم وفقًا لعادات اللغة المحلية.
تنسيقات الوقت
تتحكم خيارات مكون الوقت في عرض الساعة والدقائق والثواني.
const date = new Date(2024, 0, 15, 14, 30, 45);
const formatter = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
second: "numeric"
});
formatter.format(date);
// "2:30:45 PM"
تتحكم خيار hour12 في عرض الوقت بنظام 12 ساعة أو 24 ساعة.
const hour12 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
hour12: true
});
hour12.format(date);
// "2:30 PM"
const hour24 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
hour12: false
});
hour24.format(date);
// "14:30"
يوفر خيار hourCycle مزيدًا من التحكم في كيفية عرض الساعة. هناك أربعة خيارات.
// h11: 0-11
const h11 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
hourCycle: "h11"
});
h11.format(new Date(2024, 0, 15, 0, 30));
// "0:30 AM"
// h12: 1-12
const h12 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
hourCycle: "h12"
});
h12.format(new Date(2024, 0, 15, 0, 30));
// "12:30 AM"
// h23: 0-23
const h23 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
hourCycle: "h23"
});
h23.format(new Date(2024, 0, 15, 0, 30));
// "0:30"
// h24: 1-24
const h24 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
hourCycle: "h24"
});
h24.format(new Date(2024, 0, 15, 0, 30));
// "24:30"
يظهر الفرق مهمًا عند منتصف الليل. الدورة h11 تبدأ من 0، بينما h12 تبدأ من 12. وبالمثل، خيار h23 يبدأ من 0، في حين أن h24 يبدأ من 24.
يضيف خيار dayPeriod مؤشرات وصفية لفترات اليوم عند استخدام تنسيقات الوقت 12 ساعة.
const morning = new Date(2024, 0, 15, 10, 30);
const afternoon = new Date(2024, 0, 15, 14, 30);
const night = new Date(2024, 0, 15, 22, 30);
const formatter = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
dayPeriod: "long"
});
formatter.format(morning);
// "10:30 in the morning"
formatter.format(afternoon);
// "2:30 in the afternoon"
formatter.format(night);
// "10:30 at night"
يعمل خيار dayPeriod فقط مع تنسيقات الوقت بنظام 12 ساعة.
يعرض خيار fractionalSecondDigits الدقة بالثواني الفرعية.
const date = new Date(2024, 0, 15, 14, 30, 45, 123);
const oneDigit = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
second: "numeric",
fractionalSecondDigits: 1
});
oneDigit.format(date);
// "2:30:45.1 PM"
const threeDigits = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
second: "numeric",
fractionalSecondDigits: 3
});
threeDigits.format(date);
// "2:30:45.123 PM"
يمكنك تحديد رقم أو رقمين أو ثلاثة أرقام عشرية كسُبليات للثانية.
معالجة المناطق الزمنية
يحوّل خيار timeZone التواريخ إلى مناطق زمنية محددة.
const date = new Date("2024-01-15T14:30:00Z"); // UTC time
const newYork = new Intl.DateTimeFormat("en-US", {
timeZone: "America/New_York",
dateStyle: "full",
timeStyle: "long"
});
newYork.format(date);
// "Monday, January 15, 2024 at 9:30:00 AM EST"
const tokyo = new Intl.DateTimeFormat("ja-JP", {
timeZone: "Asia/Tokyo",
dateStyle: "full",
timeStyle: "long"
});
tokyo.format(date);
// "2024年1月15日月曜日 23:30:00 日本標準時"
const london = new Intl.DateTimeFormat("en-GB", {
timeZone: "Europe/London",
dateStyle: "full",
timeStyle: "long"
});
london.format(date);
// "Monday, 15 January 2024 at 14:30:00 GMT"
يظهر نفس اللحظة الزمنية بشكل مختلف حسب المنطقة الزمنية. استخدم معرفات المنطقة الزمنية الخاصة بـ IANA مثل America/New_York أو Europe/London أو Asia/Tokyo.
يعرض خيار timeZoneName اسم المنطقة الزمنية.
const formatter = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/New_York",
timeZoneName: "short"
});
formatter.format(date);
// "9:30 AM EST"
const long = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/New_York",
timeZoneName: "long"
});
long.format(date);
// "9:30 AM Eastern Standard Time"
const shortOffset = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/New_York",
timeZoneName: "shortOffset"
});
shortOffset.format(date);
// "9:30 AM GMT-5"
const longOffset = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/New_York",
timeZoneName: "longOffset"
});
longOffset.format(date);
// "9:30 AM GMT-05:00"
توفر القيم المختلفة لخيار timeZoneName مستويات مختلفة من التفاصيل.
أنظمة التقويم وأنظمة الترقيم
خيار calendar يدعم التقاويم غير الميلادية.
const date = new Date(2024, 0, 15);
const gregorian = new Intl.DateTimeFormat("en-US", {
calendar: "gregory",
year: "numeric",
month: "long",
day: "numeric"
});
gregorian.format(date);
// "January 15, 2024"
const japanese = new Intl.DateTimeFormat("ja-JP", {
calendar: "japanese",
year: "numeric",
month: "long",
day: "numeric"
});
japanese.format(date);
// "令和6年1月15日"
const islamic = new Intl.DateTimeFormat("ar-SA", {
calendar: "islamic",
year: "numeric",
month: "long",
day: "numeric"
});
islamic.format(date);
// "٦ رجب ١٤٤٥"
const chinese = new Intl.DateTimeFormat("zh-CN", {
calendar: "chinese",
year: "numeric",
month: "long",
day: "numeric"
});
chinese.format(date);
// "2023甲辰年腊月初五"
نفس التاريخ يمكن تحويله إلى أنظمة تقويم مختلفة. من التقاويم المتوفرة: gregory، japanese، islamic، islamic-umalqura، islamic-tbla، islamic-civil، islamic-rgsa، chinese، hebrew، indian، persian وغيرها.
خيار numberingSystem يعرض الأرقام بأنظمة كتابة مختلفة.
const date = new Date(2024, 0, 15);
const western = new Intl.DateTimeFormat("en-US", {
numberingSystem: "latn",
year: "numeric",
month: "numeric",
day: "numeric"
});
western.format(date);
// "1/15/2024"
const arabic = new Intl.DateTimeFormat("en-US", {
numberingSystem: "arab",
year: "numeric",
month: "numeric",
day: "numeric"
});
arabic.format(date);
// "١/١٥/٢٠٢٤"
const devanagari = new Intl.DateTimeFormat("en-US", {
numberingSystem: "deva",
year: "numeric",
month: "numeric",
day: "numeric"
});
devanagari.format(date);
// "१/१५/२०२४"
const bengali = new Intl.DateTimeFormat("en-US", {
numberingSystem: "beng",
year: "numeric",
month: "numeric",
day: "numeric"
});
bengali.format(date);
// "১/১৫/২০২৪"
تشمل أنظمة الأرقام المتاحة latn (أرقام غربية)، arab (أرقام هندية عربية)، arabext (أرقام هندية عربية موسعة)، beng (أرقام بنغالية)، deva (أرقام ديفاناغاري)، وغيرها الكثير.
تنسيق نطاقات التواريخ
تقوم طريقة formatRange() بتنسيق نطاق تواريخ مع حذف ذكي للمعلومات المكررة.
const start = new Date(2024, 0, 15);
const end = new Date(2024, 0, 20);
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
formatter.formatRange(start, end);
// "January 15 – 20, 2024"
يقوم المُنسِّق بحذف المعلومات المتكررة؛ كلا التاريخين في يناير 2024، لذلك يتم تضمين اسم الشهر والسنة مرة واحدة فقط في الناتج.
عندما يشمل النطاق أشهرًا مختلفة، يظهر كل شهر.
const start = new Date(2024, 0, 15);
const end = new Date(2024, 1, 20);
formatter.formatRange(start, end);
// "January 15 – February 20, 2024"
عندما يشمل النطاق سنوات مختلفة، تظهر جميع المعلومات.
const start = new Date(2024, 0, 15);
const end = new Date(2025, 1, 20);
formatter.formatRange(start, end);
// "January 15, 2024 – February 20, 2025"
طريقة formatRange() تعمل مع نطاقات الوقت أيضاً.
const start = new Date(2024, 0, 15, 14, 30);
const end = new Date(2024, 0, 15, 16, 45);
const formatter = new Intl.DateTimeFormat("en-US", {
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric"
});
formatter.formatRange(start, end);
// "January 15, 2:30 – 4:45 PM"
يتم عرض التاريخ مرة واحدة لأن الوقتين في نفس اليوم.
الحصول على الأجزاء المنسقة
طريقة formatToParts() تُرجع مصفوفة من الكائنات يُمثل كل منها جزءًا من التاريخ المنسق. يتيح ذلك بناء منطق تنسيق مُخصص.
const date = new Date(2024, 0, 15, 14, 30);
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric"
});
const parts = formatter.formatToParts(date);
كل كائن في المصفوفة يحتوي على خاصيتي type وvalue.
[
{ type: "month", value: "January" },
{ type: "literal", value: " " },
{ type: "day", value: "15" },
{ type: "literal", value: ", " },
{ type: "year", value: "2024" },
{ type: "literal", value: " at " },
{ type: "hour", value: "2" },
{ type: "literal", value: ":" },
{ type: "minute", value: "30" },
{ type: "literal", value: " " },
{ type: "dayPeriod", value: "PM" }
]
يمكنك تصفية ومعالجة هذه الأجزاء لإنشاء تنسيقات مخصصة.
const dateParts = parts.filter(part =>
["month", "day", "year"].includes(part.type)
);
const dateString = dateParts.map(part => part.value).join("/");
// "January/15/2024"
توفر طريقة formatRangeToParts() نفس الوظيفة لنطاقات التواريخ.
const start = new Date(2024, 0, 15);
const end = new Date(2024, 0, 20);
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const parts = formatter.formatRangeToParts(start, end);
يتضمن كل كائن part خاصية source تشير إلى ما إذا كان المصدر هو تاريخ البداية أو النهاية.
[
{ type: "month", value: "January", source: "startRange" },
{ type: "literal", value: " ", source: "startRange" },
{ type: "day", value: "15", source: "startRange" },
{ type: "literal", value: " – ", source: "shared" },
{ type: "day", value: "20", source: "endRange" },
{ type: "literal", value: ", ", source: "shared" },
{ type: "year", value: "2024", source: "shared" }
]
أفضل الممارسات
استخدم نفس مثيلات المُنسق عند تنسيق عدة تواريخ بنفس الخيارات. إنشاء مُنسق جديد يتطلب تفاوض حول اللغة وحل الخيارات، وهذا يحمل تكلفة بسيطة على الأداء.
// Less efficient
dates.forEach(date => {
const formatted = new Intl.DateTimeFormat("en-US").format(date);
console.log(formatted);
});
// More efficient
const formatter = new Intl.DateTimeFormat("en-US");
dates.forEach(date => {
const formatted = formatter.format(date);
console.log(formatted);
});
استخدم إعدادات لغة متصفح المستخدم كلما أمكن، وذلك بإهمال معلمة اللغة. هذا يحترم تفضيلات المستخدم.
const formatter = new Intl.DateTimeFormat();
// Uses browser locale automatically
قدم لغات بديلة عند استهداف مناطق محددة. إذا لم تتوفر اللغة المفضلة، يستخدم المتصفح الخيار التالي.
const formatter = new Intl.DateTimeFormat(["fr-CA", "fr", "en"]);
// Prefers French (Canada), falls back to French, then English
استخدم اختصارات الأسلوب لعرض التواريخ والأوقات الشائعة. هذه الاختصارات تتكيف تلقائياً مع أساليب العرض في اللغة المطلوبة وتحتاج ضبطاً أقل.
const formatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "medium",
timeStyle: "short"
});
استخدم خيارات المكونات عندما تحتاج إلى تحكم دقيق في شكل الناتج.
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
حدد المنطقة الزمنية دائماً عند عرض الأوقات للمستخدمين البعيدين أو للأحداث المجدولة. بدون تحديد المنطقة الزمنية، سيتم عرض التواريخ حسب توقيت منطقة المستخدم المحلية، وقد لا يعكس ذلك هدفك.
const formatter = new Intl.DateTimeFormat("en-US", {
timeZone: "America/New_York",
dateStyle: "full",
timeStyle: "long"
});
استخدم formatRange() لفترات التواريخ بدلاً من تنسيق كل تاريخ بشكل منفصل وجمع النتائج. هذه الطريقة تتعامل بذكاء مع حذف المعلومات المكررة.
// Less clear
const startFormatted = formatter.format(start);
const endFormatted = formatter.format(end);
const range = `${startFormatted} to ${endFormatted}`;
// Better
const range = formatter.formatRange(start, end);
تحقق من توافق المتصفحات مع الميزات المتقدمة مثل dayPeriod وfractionalSecondDigits وبعض قيم timeZoneName. جميع المتصفحات الحديثة تدعم الوظائف الأساسية، أما الخيارات الأحدث فقد تحتاج لحلول بديلة في المتصفحات الأقدم.