مقدمة: لماذا لا يكفي Date() القياسي؟
الكائن المدمج Date في JavaScript هو أداة قوية، لكنها ليست مريحة دائمًا. عند تطوير تطبيقات معقدة على Node.js (مثل مخططي المهام، أنظمة التحليلات أو الخدمات المالية)، يواجه المطورون مجموعة من المشاكل:
- القابلية للتغيير: طرق
setMonth()تغير الكائن الأصلي. - دعم محدود للمناطق الزمنية:
Dateيعمل فقط مع الوقت المحلي و UTC. - صعوبة التنسيق: لا يوجد بديل مدمج لـ
strftime. - تحليل السلاسل النصية:
new Date("2023-13-01")لن يرمي خطأ، بل سينشئ "2024-01-01".
في هذه المقالة، سنستعرض الأساليب المتقدمة للعمل مع التواريخ والوقت في Node.js، والتي ستساعد في تجنب هذه المشاكل وكتابة كود أكثر موثوقية.
1. Intl.DateTimeFormat: التنسيق بدون تبعيات خارجية
JavaScript الحديث (ES6+) يوفر واجهة برمجة تطبيقات التدويل المدمجة Intl.DateTimeFormat. هذه أداة قوية تسمح بتنسيق التواريخ والوقت لأي لغة محلية دون الحاجة إلى مكتبات طرف ثالث.
الاستخدام الأساسي
const date = new Date('2024-03-15T14:30:00Z');
// التنسيق للغة المحلية الروسيةconst formatterRU = new Intl.DateTimeFormat('ru-RU', { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long', hour: '2-digit', minute: '2-digit'});
console.log(formatterRU.format(date));// "пятница, 15 марта 2024 г., 17:30"خيارات متقدمة: المناطق الزمنية والوقت النسبي
// التنسيق مع مراعاة المنطقة الزمنيةconst formatterTZ = new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York', dateStyle: 'full', timeStyle: 'short'});console.log(formatterTZ.format(date));// "Friday, March 15, 2024 at 10:30 AM"
// التنسيق النسبي (Intl.RelativeTimeFormat)const rtf = new Intl.RelativeTimeFormat('ru', { numeric: 'auto' });console.log(rtf.format(-5, 'day')); // "5 дней назад"console.log(rtf.format(2, 'month')); // "через 2 месяца"هذا النهج مثالي عندما تحتاج إلى تجنب التبعيات غير الضرورية، ولكنك تحتاج إلى تنسيق مرن لواجهة المستخدم.
2. مكتبة date-fns: النمطية والوظائف
date-fns هي مكتبة حديثة مبنية على مبادئ البرمجة الوظيفية. ميزتها الرئيسية هي النمطية: يمكنك استيراد الوظائف التي تحتاجها فقط، مما يقلل بشكل كبير من حجم الحزمة.
التثبيت والأمثلة الأساسية
// التثبيت: npm install date-fnsimport { format, addDays, subMonths, differenceInDays, isWeekend } from 'date-fns';import { ru } from 'date-fns/locale';
const today = new Date();
// التنسيق مع اللغة المحليةconsole.log(format(today, 'dd MMMM yyyy, EEEE', { locale: ru }));// "15 марта 2024, пятница"
// عمليات حسابية على التواريخconst nextWeek = addDays(today, 7);const lastMonth = subMonths(today, 1);
// الفرق بين التواريخconst diff = differenceInDays(nextWeek, today);console.log(diff); // 7
// التحقق من عطلة نهاية الأسبوعconsole.log(isWeekend(today)); // true أو falseسيناريوهات معقدة: المقارنة والتحقق من الصحة
import { parse, isValid, isBefore, isAfter, startOfMonth, endOfMonth } from 'date-fns';
// تحليل آمنconst parsed = parse('2024-13-01', 'yyyy-MM-dd', new Date());console.log(isValid(parsed)); // false — تاريخ غير صالح
// العمل مع النطاقاتconst start = startOfMonth(new Date(2024, 2, 1)); // 1 مارسconst end = endOfMonth(new Date(2024, 2, 1)); // 31 مارس
const targetDate = new Date(2024, 2, 15);if (isAfter(targetDate, start) && isBefore(targetDate, end)) { console.log('التاريخ يقع في مارس 2024');}date-fns