كائن Date في JavaScript: دليلك الشامل للحصول على التاريخ والوقت وتنسيقهما
في عالم تطوير الويب الحديث، تُعد إدارة التاريخ والوقت مكونًا أساسيًا لا غنى عنه في معظم التطبيقات. سواء كنت تقوم بتسجيل تاريخ إنشاء مورد، أو تتبع طابع زمني لنشاط معين، فإن التعامل مع تنسيقات التاريخ والوقت يمكن أن يكون مهمة معقدة. لحسن الحظ، توفر لغة JavaScript أدوات قوية لتبسيط هذه العملية.
في هذا الدليل الشامل، سنتعمق في استكشاف كائن Date في JavaScript، وكيفية استخدامه للحصول على التاريخ والوقت الحاليين، وتنسيقهما بطرق متنوعة، وحتى بناء دالة مخصصة لتلبية احتياجات التنسيق الفريدة لتطبيقك. هدفنا هو تزويدك بالمعرفة اللازمة للتعامل مع التواريخ بثقة وفعالية.
كائن Date في JavaScript: الأساسيات
يحتوي JavaScript على كائن مدمج يُسمى Date، وهو مصمم لتخزين معلومات التاريخ والوقت وتوفير مجموعة من الدوال (methods) لمعالجتها. لإنشاء نسخة جديدة (instance) من كائن Date، يمكنك استخدام الكلمة المفتاحية new:
const date = new Date();
عند إنشاء كائن Date بهذه الطريقة، فإنه يمثل التاريخ والوقت الحاليين في لحظة الإنشاء.
فهم قيمة كائن Date
في جوهره، يحتوي كائن Date على قيمة رقمية تمثل عدد المللي ثانية التي انقضت منذ “عصر يونكس” (Unix Epoch)، وهو تاريخ 1 يناير 1970، الساعة 00:00:00 بالتوقيت العالمي المنسق (UTC). هذه القيمة هي الأساس الذي تُبنى عليه جميع عمليات التاريخ والوقت.
يمكنك أيضًا تمرير سلسلة نصية تحتوي على تاريخ محدد إلى مُنشئ (constructor) كائن Date لإنشاء كائن يمثل ذلك التاريخ:
const specificDate = new Date('Jul 12 2011');
هذه المرونة تتيح لك العمل مع تواريخ محددة بالإضافة إلى التاريخ والوقت الحاليين.
استخلاص مكونات التاريخ والوقت
يوفر كائن Date دوالًا متعددة لاستخلاص مكونات محددة من التاريخ والوقت. لنلقِ نظرة على بعضها:
الحصول على السنة الحالية باستخدام getFullYear()
للحصول على السنة الحالية من كائن Date، استخدم الدالة getFullYear(). هذه الدالة تُرجع السنة المكونة من أربعة أرقام للتاريخ المحدد في كائن Date:
const date = new Date(); // لنفترض أن التاريخ الحالي هو 2023-10-27
const currentYear = date.getFullYear();
console.log(currentYear); // الناتج: 2023
الحصول على اليوم والشهر: getDate() و getMonth()
بالمثل، توجد دوال للحصول على اليوم من الشهر والشهر الحالي:
const date = new Date(); // لنفترض أن التاريخ الحالي هو 2023-10-27
const today = date.getDate(); // اليوم من الشهر (1-31)
const currentMonth = date.getMonth(); // الشهر (0-11)
console.log(`اليوم: ${today}, الشهر (مؤشر): ${currentMonth}`); // الناتج: اليوم: 27, الشهر (مؤشر): 9
تُرجع الدالة getDate() اليوم الحالي من الشهر (من 1 إلى 31). أما الدالة getMonth()، فتُرجع الشهر من التاريخ المحدد، ولكن يجب الانتباه إلى أنها تُرجع قيمًا مفهرسة من الصفر (0-11)، حيث يمثل 0 شهر يناير و 11 شهر ديسمبر. لهذا السبب، غالبًا ما نضيف 1 إلى القيمة المُرجعة لتطبيع قيمة الشهر إلى النطاق المعتاد (1-12):
const normalizedMonth = date.getMonth() + 1;
console.log(`الشهر الفعلي: ${normalizedMonth}`); // الناتج: الشهر الفعلي: 10
الدالة الثابتة Date.now(): الحصول على الطابع الزمني
بالإضافة إلى إنشاء كائنات Date، يوفر JavaScript دالة ثابتة (static method) مفيدة جدًا تُسمى now() ضمن كائن Date. تُرجع هذه الدالة القيمة بالمللي ثانية التي تمثل الوقت المنقضي منذ عصر يونكس (1 يناير 1970، 00:00:00 UTC) حتى اللحظة الحالية.
const timeElapsed = Date.now();
console.log(timeElapsed); // الناتج: عدد كبير من المللي ثانية، مثل 1678886400000
يمكنك تمرير المللي ثانية المُرجعة من الدالة now() إلى مُنشئ Date لإنشاء كائن Date جديد يمثل تلك اللحظة الزمنية:
const timeElapsed = Date.now();
const todayFromTimestamp = new Date(timeElapsed);
console.log(todayFromTimestamp); // الناتج: كائن Date يمثل اللحظة التي تم فيها استدعاء Date.now()
تُعد الدالة Date.now() مفيدة بشكل خاص لقياس الأداء أو عند الحاجة إلى طابع زمني دقيق بالمللي ثانية.
تنسيق التاريخ والوقت بطرق متنوعة
بعد الحصول على كائن Date، غالبًا ما تحتاج إلى عرضه بتنسيقات مختلفة لتناسب متطلبات تطبيقك أو لجعله أكثر قابلية للقراءة للمستخدم. يوفر كائن Date عدة دوال لهذا الغرض:
-
toDateString(): تنسيق سهل القراءةتُرجع الدالة
toDateString()التاريخ بتنسيق سهل القراءة ومفهوم للإنسان، مع التركيز على اليوم والشهر والسنة:const today = new Date('June 14 2020'); console.log(today.toDateString()); // الناتج: "Sun Jun 14 2020" -
toISOString(): تنسيق ISO 8601 القياسيتُرجع الدالة
toISOString()التاريخ بتنسيق ISO 8601 الممتد، وهو تنسيق قياسي عالمي يُستخدم غالبًا في تبادل البيانات بين الأنظمة:const today = new Date('June 14 2020'); console.log(today.toISOString()); // الناتج: "2020-06-13T21:00:00.000Z" (قد يختلف التوقيت حسب المنطقة الزمنية) -
toUTCString(): تنسيق التوقيت العالمي المنسق (UTC)تُرجع الدالة
toUTCString()التاريخ والوقت بتنسيق التوقيت العالمي المنسق (UTC)، وهو مفيد جدًا عند التعامل مع التواريخ عبر مناطق زمنية مختلفة لضمان الاتساق:const today = new Date('June 14 2020'); console.log(today.toUTCString()); // الناتج: "Sat, 13 Jun 2020 21:00:00 GMT" (قد يختلف التوقيت حسب المنطقة الزمنية) -
toLocaleDateString(): تنسيق حساس للغة المحليةتُرجع الدالة
toLocaleDateString()التاريخ بتنسيق حساس للغة المحلية (Locale-sensitive format)، مما يعني أنها ستعرض التاريخ وفقًا لإعدادات اللغة والمنطقة في نظام المستخدم. هذا يوفر تجربة مستخدم أفضل:const today = new Date('June 14 2020'); console.log(today.toLocaleDateString()); // الناتج: "6/14/2020" (في الولايات المتحدة)، أو "14/6/2020" (في مناطق أخرى)
للحصول على مرجع كامل لدوال كائن Date، يمكنك الرجوع إلى توثيقات MDN الرسمية.
بناء دالة مخصصة لتنسيق التاريخ
على الرغم من أن دوال التنسيق المدمجة في كائن Date مفيدة، إلا أن تطبيقك قد يتطلب تنسيقات تاريخ فريدة غير متوفرة بشكل افتراضي. قد تحتاج إلى تنسيقات مثل yy/dd/mm أو yyyy-dd-mm أو أي نمط آخر مخصص. لمعالجة هذه المشكلة بفعالية، يُفضل إنشاء دالة قابلة لإعادة الاستخدام يمكن تطبيقها عبر مشاريع متعددة.
في هذا القسم، سنقوم ببناء دالة مساعدة (utility function) تُرجع التاريخ بالتنسيق المحدد كمعامل (argument) للدالة.
الخطوة الأولى: تعريف الدالة الأساسية
لنبدأ بتعريف هيكل الدالة الذي سيستقبل كائن Date وسلسلة التنسيق المطلوبة:
function formatDate(date, format) {
// هنا سيتم إضافة منطق التنسيق
}
const today = new Date();
formatDate(today, 'mm/dd/yy'); // مثال على الاستخدام
الخطوة الثانية: استبدال الأجزاء في سلسلة التنسيق
الهدف هو استبدال السلاسل النصية مثل “mm” و “dd” و “yy” بقيم الشهر واليوم والسنة المقابلة من كائن Date. قد يفكر البعض في استخدام الدالة replace() بشكل متسلسل كما يلي:
format.replace('mm', date.getMonth() + 1);
ولكن هذا النهج سيؤدي إلى سلسلة طويلة من استدعاءات الدالة replace()، مما يجعل الكود صعب الصيانة والتوسيع كلما أردت إضافة المزيد من خيارات التنسيق:
format
.replace('mm', date.getMonth() + 1)
.replace('dd', date.getDate())
.replace('yy', date.getFullYear()); // هذا النهج غير مثالي
الخطوة الثالثة: استخدام التعبيرات النمطية (Regular Expressions) لتحسين الكفاءة
بدلاً من التسلسل المباشر للدوال، يمكننا استخدام التعبيرات النمطية (Regular Expressions) مع الدالة replace() لجعل العملية أكثر مرونة وكفاءة. أولاً، سنقوم بإنشاء كائن (object) يمثل أزواجًا من المفتاح والقيمة، حيث يكون المفتاح هو الجزء الذي نريد استبداله والقيمة هي البيانات المقابلة من كائن Date:
const date = new Date(); // لنفترض تاريخًا معينًا
const formatMap = {
mm: date.getMonth() + 1,
dd: date.getDate(),
yy: date.getFullYear().toString().slice(-2), // آخر رقمين من السنة
yyyy: date.getFullYear()
};
console.log(formatMap); // الناتج: { mm: 10, dd: 27, yy: "23", yyyy: 2023 }
لاحظ كيف استخدمنا .toString().slice(-2) للحصول على آخر رقمين من السنة. هذا يضمن أن yy سيتم استبدالها بشكل صحيح.
الخطوة الرابعة: تطبيق الاستبدال باستخدام التعبيرات النمطية
الآن، يمكننا استخدام تعبير نمطي لمطابقة أي من المفاتيح في formatMap واستبدالها بالقيمة المقابلة. سنستخدم الدالة replace() مع تعبير نمطي ومع دالة استدعاء خلفي (callback function) لتحديد القيمة المستبدلة:
// لنفترض أن 'format' هي 'yyyy-mm-dd'
// ولنفترض أن 'map' هي 'formatMap' المذكورة أعلاه
let formattedDate = format.replace(/mm|dd|yy|yyyy/gi, matched => formatMap[matched]);
console.log(formattedDate); // الناتج: "2023-10-27"
هنا، /mm|dd|yy|yyyy/gi هو التعبير النمطي. g تعني البحث العالمي (global)، و i تعني عدم حساسية حالة الأحرف (case-insensitive). الدالة السهمية matched => formatMap[matched] هي دالة الاستدعاء الخلفي التي تُنفذ لكل تطابق، حيث matched هو الجزء الذي تم العثور عليه (مثل “mm” أو “yyyy”)، ونحن نستخدمه كمفتاح لاسترداد القيمة من formatMap.
الخطوة الخامسة: الدالة الكاملة لتنسيق التاريخ
بدمج كل هذه الأجزاء، تبدو الدالة الكاملة لتنسيق التاريخ كالتالي:
function formatDate(date, format) {
const map = {
mm: (date.getMonth() + 1).toString().padStart(2, '0'), // إضافة صفر بادئ
dd: date.getDate().toString().padStart(2, '0'), // إضافة صفر بادئ
yy: date.getFullYear().toString().slice(-2),
yyyy: date.getFullYear()
};
return format.replace(/mm|dd|yy|yyyy/gi, matched => map[matched]);
}
// أمثلة على الاستخدام:
const today = new Date(); // لنفترض 2023-10-07
console.log(formatDate(today, 'yyyy-mm-dd')); // الناتج: "2023-10-07"
console.log(formatDate(today, 'dd/mm/yy')); // الناتج: "07/10/23"
console.log(formatDate(today, 'mm-yyyy')); // الناتج: "10-2023"
لقد أضفنا أيضًا .toString().padStart(2, '0') لضمان أن تكون الأرقام ذات خانتين (مثل 07 بدلاً من 7) للحصول على تنسيق موحد وجميل، وهو ما يُعرف بالـ “padding”.
يمكنك أيضًا توسيع هذه الدالة لإضافة القدرة على تنسيق الطوابع الزمنية (timestamps) أو إضافة المزيد من خيارات التنسيق مثل الساعات والدقائق والثواني.
الخلاصة التقنية
يُعد كائن Date في JavaScript أداة أساسية وقوية للتعامل مع التاريخ والوقت في تطبيقات الويب. من خلال فهم كيفية إنشاء نسخ من هذا الكائن، واستخلاص مكوناته المختلفة، وتطبيق دوال التنسيق المدمجة، يمكنك إدارة متطلبات التاريخ والوقت بكفاءة.
ولكن، تكمن القوة الحقيقية والمرونة في القدرة على بناء دوال تنسيق مخصصة باستخدام التعبيرات النمطية، مما يمنح المطورين التحكم الكامل في كيفية عرض البيانات الزمنية لتناسب أي سيناريو استخدام. في حين أن المكتبات الخارجية مثل Moment.js (التي لم تعد موصى بها للمشاريع الجديدة) أو date-fns أو Luxon يمكن أن توفر حلولًا أكثر شمولاً وتعقيدًا، فإن فهم الأساسيات التي يوفرها كائن Date الأصلي في JavaScript أمر لا غنى عنه لأي مطور، ويُعد نقطة انطلاق ممتازة قبل اللجوء إلى حلول الطرف الثالث.
تذكر دائمًا أن التعامل مع التواريخ يتطلب دقة، خاصة فيما يتعلق بالمناطق الزمنية والتوقيت الصيفي، وهي جوانب قد تحتاج إلى معالجة إضافية في التطبيقات الأكثر تعقيدًا.