Temporal بدل Date: إزاي تتعامل مع الوقت صح في JavaScript

الساعة في مصر رجعت ساعة يوم 29 أكتوبر، وده بالظبط اليوم اللي بيكشف مشاكل Date. Temporal بديل كامل ليه ومتاح افتراضيًا من Node.js 26، ودي 4 حاجات تبدأ بيها.

الساعة في مصر رجعت ساعة آخر يوم الخميس 29 أكتوبر. سؤال بسيط: الكود بتاعك اللي بيحسب مواعيد وتذكيرات عدّى اليوم ده صح؟ لو بتستخدم Date في JavaScript، فيه احتمال كبير إن فيه حاجة اتلخبطت من غير ما تاخد بالك. النهارده هنتكلم عن Temporal، الـ API الجديد اللي اتعمل عشان يبقى بديل كامل لـ Date، وبقى متاح افتراضيًا من Node.js 26.

مشكلة Date باختصار

  • منطقتين زمنيتين بس: Date بيعرف UTC والمنطقة الزمنية بتاعة الجهاز، ومفيش طريقة طبيعية تقوله «اشتغل بتوقيت القاهرة» وانت على سيرفر UTC.
  • مفيش تاريخ من غير ساعة: عيد ميلاد أو تاريخ تجديد اشتراك مالوش ساعة ولا منطقة، بس Date لازم يحطله لحظة زمنية كاملة.
  • mutation: الـ setters زي setDate بتعدّل نفس الـ object، وده مصدر bugs كلاسيكي لما نفس القيمة تتشارك في أكتر من مكان.

Temporal بيحل ده بأنواع منفصلة لكل حالة، وكل عملية فيه بترجع قيمة جديدة.

1) الوقت بالمنطقة الزمنية صراحة

const now = Temporal.Now.zonedDateTimeISO('Africa/Cairo');

هنا المنطقة الزمنية جزء من القيمة نفسها، مش حاجة متخبية في إعدادات الجهاز.

2) يوم مش دايمًا 24 ساعة

ده أهم مثال، وخصوصًا الأسبوع ده:

const t = Temporal.ZonedDateTime.from('2026-10-29T12:00[Africa/Cairo]');

t.add({ days: 1 });   // 2026-10-30 الساعة 12:00
t.add({ hours: 24 }); // 2026-10-30 الساعة 11:00

الفرق ساعة كاملة، عشان الساعة رجعت ساعة آخر يوم 29 أكتوبر. يعني لو عندك تذكير «كل يوم الساعة 12»، استخدم days مش hours: 24. أما لو عايز مدة ثابتة بالظبط (زي timeout أو token صلاحيته 24 ساعة)، يبقى hours هو الصح.

3) تاريخ من غير ساعة ولا منطقة

Temporal.PlainDate.from('2026-01-31').add({ months: 1 });
// 2026-02-28

PlainDate مناسب لتواريخ الميلاد ومواعيد الاشتراكات. ولاحظ إن إضافة شهر على 31 يناير بتديك 28 فبراير، مش تاريخ في مارس.

4) خزّن لحظة، واعرضها بالمنطقة

  • في الداتابيز خزّن Temporal.Instant (أو string بصيغة ISO آخرها Z)، يعني لحظة مطلقة مش مرتبطة بمنطقة.
  • وقت العرض للمستخدم حوّلها:
instant.toZonedDateTimeISO('Africa/Cairo');

وكل العمليات دي بترجع قيم جديدة، مفيش mutation.

خلي بالك قبل ما تستخدمه في المتصفح

  • MDN لسه معلّم Temporal إنه Limited availability، يعني مش شغال في كل المتصفحات المشهورة. لو الكود هيشتغل في المتصفح، اتأكد من الدعم أو استخدم polyfill.
  • على السيرفر، Node.js 26 مفعّله افتراضيًا حسب الـ release notes.
  • أنا جربت الأمثلة اللي فوق بـ @js-temporal/polyfill وطلعت نفس النتايج.

رأيي

مش محتاج تعمل migration لكل الكود مرة واحدة. ابدأ بالأماكن اللي بتوجع: الجدولة والتذكيرات وأي حساب فيه «بكرة» أو «الشهر الجاي». هناك الفرق بين days و hours بيبان، وأسبوع زي اللي فات ده بالظبط اللي بيكشفه.

وانت، لسه على Date ولا moment/dayjs ولا بدأت Temporal؟

المصادر

  • JavaScript
  • Node.js
  • Temporal
  • Full Stack Tips
  • Web Dev