كيفية الحصول على الأجزاء الفردية من تاريخ منسق في JavaScript
استخدم formatToParts() للوصول إلى كل مكون من مكونات التاريخ المنسق بشكل منفصل
مقدمة
تُرجع طريقة format() سلسلة نصية منسقة كاملة مثل "15 يناير، 2025" أو "15/01/2025". هذا يعمل بشكل جيد للعرض البسيط، لكن لا يمكنك تنسيق الأجزاء الفردية بشكل مختلف. لا يمكنك جعل اسم الشهر بخط عريض، أو تلوين السنة بشكل مختلف، أو تطبيق علامات مخصصة على مكونات محددة.
توفر جافا سكريبت طريقة formatToParts() لحل هذه المشكلة. بدلاً من إرجاع سلسلة نصية واحدة، فإنها تُرجع مصفوفة من الكائنات، كل منها يمثل جزءًا واحدًا من التاريخ المنسق. كل جزء له نوع مثل month أو day أو year، وقيمة مثل January أو 15 أو 2025. يمكنك بعد ذلك معالجة هذه الأجزاء لتطبيق تنسيق مخصص، أو بناء تخطيطات معقدة، أو دمج تواريخ منسقة في واجهات مستخدم غنية.
لماذا يصعب تخصيص السلاسل النصية المنسقة
عندما تتلقى سلسلة نصية منسقة مثل "15 يناير، 2025"، لا يمكنك تحديد بسهولة أين ينتهي الشهر ويبدأ اليوم. تضع اللغات المختلفة المكونات بترتيب مختلف. تستخدم بعض اللغات فواصل مختلفة. يتطلب تحليل هذه السلاسل النصية بشكل موثوق منطقًا معقدًا يكرر قواعد التنسيق المُنفذة بالفعل في واجهة برمجة التطبيقات Intl.
فكر في تطبيق تقويم يعرض التواريخ مع اسم الشهر بخط عريض. باستخدام format()، ستحتاج إلى:
- اكتشاف الأحرف التي تمثل اسم الشهر
- مراعاة المسافات وعلامات الترقيم بين المكونات
- التعامل مع تنسيقات الشهور المختلفة عبر اللغات
- تحليل السلسلة النصية بعناية لتجنب إفساد التاريخ
هذا النهج هش وعرضة للأخطاء. أي تغيير في قواعد تنسيق اللغة يؤدي إلى تعطيل منطق التحليل الخاص بك.
تُلغي طريقة formatToParts() هذه المشكلة من خلال توفير المكونات بشكل منفصل. تتلقى بيانات منظمة تخبرك بالضبط أي جزء هو أي، بغض النظر عن اللغة.
استخدام formatToParts للحصول على مكونات التاريخ
تعمل طريقة formatToParts() بشكل مطابق لطريقة format() باستثناء القيمة المرجعة. يمكنك إنشاء منسق بنفس الخيارات، ثم استدعاء formatToParts() بدلاً من format().
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);
هذا يُخرج مصفوفة من الكائنات:
[
{ type: "month", value: "January" },
{ type: "literal", value: " " },
{ type: "day", value: "15" },
{ type: "literal", value: ", " },
{ type: "year", value: "2025" }
]
يحتوي كل كائن على خاصية type تحدد ما يمثله الجزء وخاصية value تحتوي على السلسلة النصية الفعلية. تظهر الأجزاء بنفس الترتيب الذي ستظهر به في المخرجات المنسقة.
يمكنك التحقق من ذلك عن طريق دمج جميع القيم معًا:
const formatted = parts.map(part => part.value).join("");
console.log(formatted);
// Output: "January 15, 2025"
تنتج الأجزاء المتصلة نفس المخرجات تمامًا مثل استدعاء format().
فهم أنواع الأجزاء
تحدد خاصية type كل مكون. تنتج خيارات التنسيق المختلفة أنواعًا مختلفة من الأجزاء.
لتنسيق التاريخ الأساسي:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "day", value: "15" },
// { type: "literal", value: ", " },
// { type: "year", value: "2025" }
// ]
يمثل نوع month اسم الشهر أو رقمه. يمثل نوع day يوم الشهر. يمثل نوع year السنة. يمثل نوع literal المسافات أو علامات الترقيم أو النصوص الأخرى التي يدرجها المنسق.
للتواريخ مع أيام الأسبوع:
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
// { type: "weekday", value: "Wednesday" },
// { type: "literal", value: ", " },
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "day", value: "15" },
// { type: "literal", value: ", " },
// { type: "year", value: "2025" }
// ]
يمثل نوع weekday يوم الأسبوع.
للتواريخ مع الأوقات:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric"
});
const date = new Date(2025, 0, 15, 14, 30, 45);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "day", value: "15" },
// { type: "literal", value: ", " },
// { type: "year", value: "2025" },
// { type: "literal", value: " at " },
// { type: "hour", value: "2" },
// { type: "literal", value: ":" },
// { type: "minute", value: "30" },
// { type: "literal", value: ":" },
// { type: "second", value: "45" },
// { type: "literal", value: " " },
// { type: "dayPeriod", value: "PM" }
// ]
تمثل أنواع hour وminute وsecond مكونات الوقت. يمثل نوع dayPeriod صباحًا (AM) أو مساءً (PM) في تنسيق 12 ساعة.
تطبيق التنسيق المخصص على أجزاء التاريخ
الاستخدام الأساسي لـ formatToParts() هو تطبيق أنماط مختلفة على مكونات مختلفة. يمكنك معالجة مصفوفة الأجزاء لتغليف أنواع محددة في عناصر HTML.
جعل اسم الشهر بخط عريض:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
.map(part => {
if (part.type === "month") {
return `<strong>${part.value}</strong>`;
}
return part.value;
})
.join("");
console.log(html);
// النتيجة: "<strong>January</strong> 15, 2025"
هذا النهج يعمل مع أي لغة ترميز. يمكنك إنشاء HTML أو JSX أو أي تنسيق آخر من خلال معالجة مصفوفة الأجزاء.
تنسيق السنة بشكل مختلف:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
.map(part => {
if (part.type === "year") {
return `<span class="text-gray-500">${part.value}</span>`;
}
return part.value;
})
.join("");
console.log(html);
// النتيجة: "January 15, <span class="text-gray-500">2025</span>"
هذا النمط شائع في عروض التقويم حيث تحتاج المكونات المختلفة إلى تأكيد بصري مختلف.
بناء عروض تاريخ مخصصة بأنماط متعددة
غالبًا ما تجمع الواجهات المعقدة بين قواعد تنسيق متعددة. يمكنك تطبيق فئات أو عناصر مختلفة على أنواع أجزاء مختلفة في وقت واحد.
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
.map(part => {
switch (part.type) {
case "weekday":
return `<span class="weekday">${part.value}</span>`;
case "month":
return `<span class="month">${part.value}</span>`;
case "day":
return `<span class="day">${part.value}</span>`;
case "year":
return `<span class="year">${part.value}</span>`;
case "literal":
return `<span class="literal">${part.value}</span>`;
default:
return part.value;
}
})
.join("");
console.log(html);
// النتيجة: "<span class="weekday">Wednesday</span><span class="literal">, </span><span class="month">January</span><span class="literal"> </span><span class="day">15</span><span class="literal">, </span><span class="year">2025</span>"
هذا التحكم الدقيق يتيح تنسيقًا دقيقًا لكل مكون. يمكنك بعد ذلك استخدام CSS لتنسيق كل فئة بشكل مختلف.
إنشاء تخطيطات تاريخ مخصصة
يمكنك إعادة ترتيب مكونات التاريخ في تخطيطات مخصصة تختلف عن تنسيق اللغة القياسي. استخرج أجزاء محددة وقم بتركيبها بأي ترتيب.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const day = parts.find(p => p.type === "day").value;
const month = parts.find(p => p.type === "month").value;
const year = parts.find(p => p.type === "year").value;
const customLayout = `
<div class="date-card">
<div class="day-large">${day}</div>
<div class="month-small">${month}</div>
<div class="year-small">${year}</div>
</div>
`;
console.log(customLayout);
هذا ينشئ تخطيط بطاقة عمودية مع عرض اليوم بشكل بارز، يليه الشهر والسنة. تظل المكونات مترجمة بشكل صحيح حسب اللغة حتى لو كان التخطيط يختلف عن التنسيق القياسي.
جميع أنواع الأجزاء المتاحة
يمكن أن تحتوي خاصية type على هذه القيم اعتمادًا على خيارات التنسيق المستخدمة:
weekday: يوم الأسبوع مثل الاثنين أو الإثنينera: مؤشر العصر مثل قبل الميلاد، بعد الميلاد، أو BCEyear: السنة مثل 2025month: اسم الشهر أو رقمه مثل يناير أو 01day: يوم الشهر مثل 15dayPeriod: صباحًا أو مساءً أو فترات يوم أخرى خاصة باللغةhour: الساعة مثل 14 أو 2minute: الدقيقة مثل 30second: الثانية مثل 45fractionalSecond: الميلي ثانية أو أجزاء أخرى من الثانيةtimeZoneName: اسم المنطقة الزمنية مثل PST أو توقيت المحيط الهادئ القياسيliteral: المسافات، علامات الترقيم، أو نص آخر مضاف بواسطة التنسيقrelatedYear: السنة الميلادية في أنظمة التقويم البديلةyearName: السنة المسماة في بعض أنظمة التقويمunknown: الرموز غير المعروفة
لا تنتج كل خيارات التنسيق كل نوع من أنواع الأجزاء. تعتمد الأجزاء التي تتلقاها على قيمة التاريخ وتكوين المنسق.
التواريخ مع مؤشرات العصر:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
era: "short"
});
const date = new Date(-100, 0, 1);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
// { type: "year", value: "101" },
// { type: "literal", value: " " },
// { type: "era", value: "BC" }
// ]
التواريخ مع المناطق الزمنية:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
timeZoneName: "short"
});
const date = new Date(2025, 0, 15, 14, 30);
const parts = formatter.formatToParts(date);
console.log(parts);
// ستتضمن الأجزاء { type: "timeZoneName", value: "PST" } أو ما شابه
التواريخ مع أجزاء الثانية:
const formatter = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
second: "numeric",
fractionalSecondDigits: 3
});
const date = new Date(2025, 0, 15, 14, 30, 45, 123);
const parts = formatter.formatToParts(date);
// ستتضمن الأجزاء { type: "fractionalSecond", value: "123" }
إبراز مكونات التاريخ بشكل مشروط
تقوم بعض التطبيقات بإبراز مكونات تاريخ محددة بناءً على منطق العمل. باستخدام formatToParts()، يمكنك تطبيق التنسيق بناءً على قيمة التاريخ مع الحفاظ على التنسيق المناسب.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
function formatDateWithHighlight(date) {
const parts = formatter.formatToParts(date);
const isWeekend = date.getDay() === 0 || date.getDay() === 6;
const html = parts
.map(part => {
if (part.type === "day" && isWeekend) {
return `<span class="text-blue-600 font-bold">${part.value}</span>`;
}
return part.value;
})
.join("");
return html;
}
const saturday = new Date(2025, 0, 18);
console.log(formatDateWithHighlight(saturday));
// Output: "January <span class="text-blue-600 font-bold">18</span>, 2025"
const monday = new Date(2025, 0, 13);
console.log(formatDateWithHighlight(monday));
// Output: "January 13, 2025"
يحصل التاريخ على التنسيق المناسب للغة المحلية بينما يتم تطبيق التنسيق المشروط بناءً على منطق العمل.
إنشاء عروض تاريخ سهلة الوصول
يمكنك استخدام formatToParts() لإضافة سمات إمكانية الوصول إلى التواريخ المنسقة. هذا يساعد قارئات الشاشة على نطق القيم بشكل صحيح.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
function formatAccessibleDate(date) {
const parts = formatter.formatToParts(date);
const formatted = parts.map(part => part.value).join("");
const isoDate = date.toISOString().split('T')[0];
return `<time datetime="${isoDate}">${formatted}</time>`;
}
const date = new Date(2025, 0, 15);
console.log(formatAccessibleDate(date));
// Output: "<time datetime="2025-01-15">January 15, 2025</time>"
هذا يضمن أن قارئات الشاشة يمكنها نطق التاريخ بشكل صحيح بينما يعرض العرض النسخة المنسقة حسب اللغة المحلية.
كيف تحافظ الأجزاء على تنسيق خاص باللغة المحلية
تحافظ مصفوفة الأجزاء على قواعد التنسيق الخاصة باللغة المحلية تلقائيًا. تضع اللغات المحلية المختلفة المكونات بترتيب مختلف وتستخدم تنسيقات مختلفة، لكن formatToParts() يتعامل مع هذه الاختلافات.
const usFormatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
console.log(usFormatter.formatToParts(date));
// [
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "day", value: "15" },
// { type: "literal", value: ", " },
// { type: "year", value: "2025" }
// ]
const ukFormatter = new Intl.DateTimeFormat("en-GB", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(ukFormatter.formatToParts(date));
// [
// { type: "day", value: "15" },
// { type: "literal", value: " " },
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "year", value: "2025" }
// ]
التنسيق البريطاني يضع اليوم قبل الشهر. يعالج كود التنسيق الخاص بك مصفوفة الأجزاء بنفس الطريقة بغض النظر عن اللغة المحلية، ويتكيف التنسيق تلقائيًا.
const jpFormatter = new Intl.DateTimeFormat("ja-JP", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(jpFormatter.formatToParts(date));
// [
// { type: "year", value: "2025" },
// { type: "literal", value: "年" },
// { type: "month", value: "1月" },
// { type: "day", value: "15" },
// { type: "literal", value: "日" }
// ]
التنسيق الياباني يستخدم ترتيبًا مختلفًا ويتضمن أحرفًا حرفية مثل 年 (سنة) و 日 (يوم). تعكس مصفوفة الأجزاء هذه الاتفاقيات الخاصة باللغة المحلية تلقائيًا.
دمج formatToParts مع مكونات الإطارات البرمجية
يمكن للإطارات البرمجية الحديثة مثل React استخدام formatToParts() لبناء المكونات بكفاءة.
function DateDisplay({ date, locale, options }) {
const formatter = new Intl.DateTimeFormat(locale, options);
const parts = formatter.formatToParts(date);
return (
<span className="date-display">
{parts.map((part, index) => {
if (part.type === "month") {
return <strong key={index}>{part.value}</strong>;
}
if (part.type === "year") {
return <span key={index} className="text-sm text-gray-500">{part.value}</span>;
}
return <span key={index}>{part.value}</span>;
})}
</span>
);
}
يطبق هذا المكون أنماط مختلفة على أجزاء مختلفة مع الحفاظ على التنسيق المناسب لأي لغة محلية.
متى تستخدم formatToParts مقابل format
استخدم format() عندما تحتاج إلى سلسلة نصية منسقة بسيطة دون أي تخصيص. هذه هي الحالة الشائعة لمعظم عرض التواريخ.
استخدم formatToParts() عندما تحتاج إلى:
- تطبيق أنماط مختلفة على أجزاء مختلفة من التاريخ
- بناء HTML أو JSX مع تواريخ منسقة
- إضافة سمات أو بيانات وصفية إلى مكونات محددة
- إعادة ترتيب مكونات التاريخ في تخطيطات مخصصة
- دمج التواريخ المنسقة في تخطيطات معقدة
- معالجة المخرجات المنسقة برمجياً
تتطلب طريقة formatToParts() عبئاً أكثر قليلاً من format() لأنها تنشئ مصفوفة من الكائنات بدلاً من سلسلة نصية واحدة. هذا الفرق ضئيل للتطبيقات النموذجية، ولكن إذا كنت تقوم بتنسيق آلاف التواريخ في الثانية، فإن format() يؤدي بشكل أفضل.
بالنسبة لمعظم التطبيقات، اختر بناءً على احتياجات التنسيق الخاصة بك بدلاً من اعتبارات الأداء. إذا كنت لا تحتاج إلى تخصيص المخرجات، استخدم format(). إذا كنت بحاجة إلى تنسيق مخصص أو ترميز، استخدم formatToParts().