يعمل أي نوع من التطبيقات المكتوبة بلغة JavaScript تقريبًا مع الأوقات أو التواريخ في بعض السعة. في البداية، كان هذا مقتصرًا على واجهة برمجة التطبيقات Date API المضمنة. تتضمن واجهة برمجة التطبيقات (API) هذه وظائف أساسية، ولكنها محدودة جدًا فيما يمكنها القيام به. تضيف مكتبات الجهات الخارجية مثل Moment.js، وواجهات برمجة التطبيقات المضمنة لاحقًا مثل Intl APIs وTemporal API الجديدة، مرونة أكبر بكثير في التعامل مع الأوقات والتواريخ. صعود وسقوط Moment.js Moment.js هي مكتبة JavaScript تحتوي على أدوات مساعدة قوية للتعامل مع الأوقات والتواريخ. وهو يتضمن ميزات مفقودة من واجهة برمجة تطبيقات التاريخ الأساسية، مثل معالجة المنطقة الزمنية، ويجعل العديد من العمليات الشائعة أكثر بساطة. تتضمن اللحظة أيضًا وظائف لتنسيق التواريخ والأوقات. أصبحت مكتبة مستخدمة على نطاق واسع في العديد من التطبيقات المختلفة. ومع ذلك، كان لـ Moment أيضًا نصيبها من المشكلات. إنها مكتبة كبيرة، ويمكن أن تزيد بشكل كبير من حجم حزمة التطبيق. نظرًا لأن المكتبة لا تدعم اهتزاز الشجرة (وهي إحدى ميزات المجمعات الحديثة التي يمكنها إزالة الأجزاء غير المستخدمة من المكتبات)، يتم تضمين مكتبة Moment بأكملها حتى لو كنت تستخدم وظيفة واحدة أو اثنتين فقط من وظائفها. هناك مشكلة أخرى تتعلق بـ Moment وهي حقيقة أن الكائنات التي تقوم بإنشائها قابلة للتغيير. إن استدعاء وظائف معينة في كائن Moment له آثار جانبية ويؤدي إلى تغيير قيمة ذلك الكائن. يمكن أن يؤدي هذا إلى سلوك أو أخطاء غير متوقعة. في عام 2020، قرر القائمون على Moment وضع المكتبة في وضع الصيانة. لم يتم تطوير ميزات جديدة، ويوصي المشرفون بعدم استخدامها في المشاريع الجديدة. توجد مكتبات تاريخ جافا سكريبت أخرى، مثل date-fns، ولكن هناك لاعب جديد في المدينة، وهي واجهة برمجة التطبيقات المضمنة مباشرة في JavaScript: Temporal. إنه معيار جديد يملأ الثغرات الموجودة في واجهة برمجة التطبيقات Date API الأصلية ويحل أيضًا بعض القيود الموجودة في Moment والمكتبات الأخرى. ما هو الزماني؟ Temporal عبارة عن واجهة برمجة تطبيقات جديدة للوقت والتاريخ تتم إضافتها إلى معيار ECMAScript، والتي تحدد JavaScript الحديثة. اعتبارًا من مارس 20266، وصلت إلى المرحلة 4 من عملية TC39 (اللجنة التي تشرف على المقترحات والإضافات إلى لغة JavaScript)، وسيتم تضمينها في الإصدار التالي من مواصفات ECMAScript. وقد تم تطبيقه بالفعل في العديد من المتصفحات: Chrome 144+ وFirefox 139+، ومن المتوقع أن يتبعه Safari قريبًا. يتوفر أيضًا polyfill للمتصفحات غير المدعومة وNode.js. تقوم واجهة برمجة التطبيقات المؤقتة بإنشاء كائنات تمثل لحظات زمنية بشكل عام. يمكن أن تكون هذه طوابع زمنية وطوابع تاريخ في منطقة زمنية معينة، أو يمكن أن تكون مثيلًا عامًا لوقت "ساعة الحائط" دون أي منطقة زمنية أو معلومات تاريخ. تتضمن بعض الميزات الرئيسية للزمنية ما يلي:
الأوقات مع أو بدون تواريخ. يمكن أن يمثل الكائن الزمني وقتًا محددًا في تاريخ محدد، أو وقتًا بدون أي معلومات تاريخ. ويمكن أيضًا تمثيل تاريخ محدد، بدون وقت. دعم المنطقة الزمنية. الكائنات المؤقتة تدرك المنطقة الزمنية بالكامل ويمكن تحويلها عبر مناطق زمنية مختلفة. يدعم Moment المناطق الزمنية أيضًا، ولكنه يتطلب مكتبة المنطقة الزمنية الإضافية. الثبات. بمجرد إنشاء كائن مؤقت، لا يمكن تغييره. لا تؤدي التحويلات الحسابية أو المنطقة الزمنية إلى تعديل الكائن الأساسي. بدلاً من ذلك، يقومون بإنشاء كائن مؤقت جديد. الفهرسة المستندة إلى 1. أحد المصادر الشائعة للأخطاء في Date API (وكذلك مع Moment) هو أن الأشهر غير مفهرسة بصفر. وهذا يعني أن شهر يناير هو الشهر 0، وليس الشهر 1 كما نفهم جميعًا في الحياة الواقعية. يتم إصلاح هذه المشكلة مؤقتًا باستخدام الفهرسة المستندة إلى 1 — يناير هو الشهر 1. إنه مدمج في المتصفح. نظرًا لأن Temporal عبارة عن واجهة برمجة التطبيقات (API) في المتصفح نفسه، فإنه لا يضيف شيئًا إلى حجم حزمة التطبيق الخاص بك.
من المهم أيضًا ملاحظة أن واجهة برمجة تطبيقات التاريخ لن تختفي. على الرغم من أن Temporal يحل محل واجهة برمجة التطبيقات هذه، إلا أنه لا تتم إزالته أو إهماله. قد تتعطل العديد من التطبيقات إذا قامت المتصفحات بإزالة واجهة برمجة تطبيقات التاريخ فجأة. ومع ذلك، ضع في اعتبارك أيضًا أن Moment يعتبر الآن مشروعًا قديمًا في وضع الصيانة. في بقية المقالة، سنلقي نظرة على بعض "الوصفات" لترحيل التعليمات البرمجية المستندة إلى اللحظة إلى واجهة برمجة التطبيقات المؤقتة الجديدة. لنبدأ بإعادة البناء! إنشاء كائنات التاريخ والوقت قبل أن نتمكن من التعامل مع التواريخ والأوقات، علينا إنشاء كائنات تمثلها. لإنشاء كائن لحظة يمثل التاريخ والوقت الحاليين، استخدم وظيفة اللحظة. ثابت الآن = لحظة ()؛ console.log(now); // لحظة<2026-02-18T21:26:29-05:00>
يمكن الآن تنسيق هذا الكائن أو معالجته حسب الحاجة.
// تحويل إلى UTC //تحذير: يؤدي هذا إلى تغيير كائن Moment ووضعه في وضع UTC! console.log(now.utc()); // لحظة<2026-02-19T02:26:29Z>
// طباعة سلسلة منسقة - لاحظ أنها تستخدم التوقيت العالمي المنسق (UTC) الآن console.log(now.format('MM/DD/YYYY hh:mm:ss a')); // 19/02/2026 02:27:07 صباحا
الشيء الأساسي الذي يجب تذكره بشأن Moment هو أن كائن Moment يتضمن دائمًا معلومات حول الوقت والتاريخ. إذا كنت تحتاج فقط إلى التعامل مع معلومات الوقت، فهذا أمر جيد عادةً، ولكنه قد يتسبب في سلوك غير متوقع في مواقف مثل التوقيت الصيفي أو السنوات الكبيسة، حيث يمكن أن يكون للتاريخ تأثير على حسابات الوقت. الزمانية أكثر مرونة. يمكنك إنشاء كائن يمثل التاريخ والوقت الحاليين عن طريق إنشاء كائن Temporal.Instant. يمثل هذا نقطة زمنية محددة بالوقت منذ "العصر" (منتصف الليل بالتوقيت العالمي المنسق في 1 يناير 1970). يمكن للزمنية الإشارة إلى هذه اللحظة في الوقت المناسب بدقة على مستوى النانو ثانية. const now = Temporal.Now.instant();
// انظر النانو ثانية الخام منذ العصر console.log(now.epochNanothans); // 1771466342612000000ن
// تنسيق UTC console.log(now.toString()); //2026-02-19T01:55:27.844Z
// التنسيق لمنطقة زمنية معينة console.log(now.toString({ timeZone: 'America/New_York' })); //2026-02-18T20:56:57.905-05:00
يمكن أيضًا إنشاء كائنات Temporal.Instant لوقت وتاريخ محددين باستخدام الأسلوب from static.
const myInstant = Temporal.Instant.from('2026-02-18T21:10:00-05:00');
// قم بتنسيق اللحظة بالمنطقة الزمنية المحلية. لاحظ أن هذا يتحكم فقط // التنسيق - لا يؤدي إلى تغيير الكائن كما يفعل moment.utc. console.log(myInstant.toString({ timeZone: 'America/New_York' })); // 2026-02-18T21:10:00-05:00
يمكنك أيضًا إنشاء أنواع أخرى من الكائنات المؤقتة، بما في ذلك:
Temporal.PlainDate: تاريخ بدون معلومات الوقت. Temporal.PlainTime: وقت بدون معلومات التاريخ. Temporal.ZonedDateTime: التاريخ والوقت في منطقة زمنية محددة.
يحتوي كل منها على طريقة from يمكن استدعاؤها باستخدام كائن يحدد التاريخ و/أو الوقت، أو سلسلة تاريخ للتحليل. // مجرد موعد ثابت اليوم = Temporal.PlainDate.from({ السنة: 2026، الشهر: 2، // لاحظ أننا نستخدم 2 لشهر فبراير اليوم: 18 }); console.log(today.toString()); // 2026-02-18
// مجرد وقت وقت الغداء الثابت = Temporal.PlainTime.from({ الساعة: 12 }); console.log(lunchTime.toString()); // 12:00:00
// التاريخ والوقت بالمنطقة الزمنية الشرقية للولايات المتحدة const DueAt = Temporal.ZonedDateTime.from({ المنطقة الزمنية: "أمريكا/نيويورك"، السنة: 2026، الشهر: 3، اليوم: 1، الساعة: 12، الدقيقة: 0، الثاني: 0 }); console.log(dueAt.toString()); // 2026-03-01T12:00:00-05:00[America/New_York]
إعراب لقد قمنا بتغطية الإنشاء الآلي لمعلومات التاريخ والوقت. الآن دعونا نلقي نظرة على التحليل. يعد التحليل أحد المجالات التي تكون فيها Moment أكثر مرونة من واجهة برمجة التطبيقات المؤقتة المضمنة. يمكنك تحليل سلسلة تاريخ عن طريق تمريرها إلى الدالة moment. باستخدام وسيطة واحدة، تتوقع Moment سلسلة تاريخ ISO، ولكن يمكنك استخدام تنسيقات بديلة إذا قمت بتوفير وسيطة ثانية تحدد تنسيق التاريخ المستخدم.
const isoDate = moment('2026-02-21T09:00:00'); const formattedDate = moment('2/21/26 9:00:00', 'M/D/YY h:mm:ss');
console.log(isoDate); // لحظة<2026-02-21T09:00:00-05:00>
console.log(formattedDate); // لحظة<2026-02-21T09:00:00-05:00>
في الإصدارات الأقدم، كان Moment يقدم أفضل تخمين لتحليل أي سلسلة تاريخ منسقة بشكل عشوائي. وهذا يمكن أن يؤدي إلى نتائج غير متوقعة. على سبيل المثال، هل 2026-03-02 هو 2 فبراير أم 3 مارس؟ لهذا السبب، تعرض الإصدارات الأحدث من Moment تحذيرًا بارزًا بالإهمال إذا تم استدعاؤها بدون سلسلة تاريخ بتنسيق ISO (ما لم يتم أيضًا تقديم الوسيطة الثانية بالتنسيق المطلوب). سوف يقوم Temporal بتحليل سلسلة تاريخ منسقة بشكل خاص فقط. يجب أن تكون السلسلة متوافقة مع تنسيق ISO 8601 أو امتداده، RFC 9557. إذا تم تمرير سلسلة تاريخ غير متوافقة إلى أسلوب من، فسيقوم Temporal بإلقاء خطأ RangeError.
// باستخدام سلسلة تاريخ RFC 9557 const myDate = Temporal.Instant.from('2026-02-21T09:00:00-05:00[America/New_York]'); console.log(myDate.toString({ timeZone: 'America/New_York' })); // 2026-02-21T09:00:00-05:00
// استخدام سلسلة تاريخ غير معروفة constotherDate = Temporal.Instant.from('2/21/26 9:00:00'); // RangeError: خطأ مؤقت: حرف غير صالح أثناء تحليل قيمة السنة.
تعتمد المتطلبات الدقيقة لسلسلة التاريخ على نوع الكائن المؤقت الذي تقوم بإنشائه. في المثال أعلاه، يتطلب Temporal.Instant ISO كاملاًسلسلة تاريخ 8601 أو RFC 9557 تحدد التاريخ والوقت مع إزاحة المنطقة الزمنية، ولكن يمكنك أيضًا إنشاء كائنات PlainDate أو PlainTime باستخدام مجموعة فرعية فقط من تنسيق التاريخ. const myDate = Temporal.PlainDate.from('2026-02-21'); console.log(myDate.toString()); //2026-02-21
const myTime = Temporal.PlainTime.from('09:00:00'); console.log(myTime.toString()); // 09:00:00
لاحظ أن هذه السلاسل يجب أن تتوافق مع التنسيق المتوقع، وإلا فسيتم ظهور خطأ.
// استخدام سلاسل زمنية غير متوافقة. كل هذه سوف تؤدي إلى ظهور خطأ RangeError. Temporal.PlainTime.from('9:00'); Temporal.PlainTime.from('9:00:00 AM');
نصيحة احترافية: التعامل مع سلاسل غير ISO نظرًا لأن Temporal يعطي الأولوية للموثوقية، فلن يحاول تخمين تنسيق سلسلة مثل 02-01-2026. إذا كان مصدر البيانات الخاص بك يستخدم مثل هذه السلاسل، فستحتاج إلى إجراء بعض المعالجة للسلاسل لإعادة ترتيب القيم في سلسلة ISO مثل 01-02-2026 قبل محاولة استخدامها مع Temporal.
التنسيق بمجرد حصولك على كائن Moment أو Temporal، قد ترغب في تحويله إلى سلسلة منسقة في مرحلة ما. هذا هو المثال الذي تكون فيه Moment أكثر إيجازًا. يمكنك استدعاء أسلوب تنسيق الكائن باستخدام سلسلة من الرموز المميزة التي تصف تنسيق التاريخ المطلوب. تاريخ ثابت = لحظة ()؛
console.log(date.format('MM/DD/YYYY')); // 22/02/2026
console.log(date.format('MMMM Do YYYY, h:mm:ss a')); // 22 فبراير 2026، 8:18:30 مساءً
من ناحية أخرى، يتطلب Temporal منك أن تكون أكثر إسهابًا. الكائنات المؤقتة، مثل Instant، لها أسلوب toLocaleString الذي يقبل خيارات التنسيق المتنوعة المحددة كخصائص للكائن.
تاريخ ثابت = Temporal.Now.instant();
// بدون وسائط، سنحصل على التنسيق الافتراضي للغة الحالية console.log(date.toLocaleString()); // 22/02/2026، 8:23:36 مساءً (بافتراض لغة en-US)
// تمرير خيارات التنسيق لإنشاء سلسلة تنسيق مخصصة console.log(date.toLocaleString('en-US', { الشهر: "طويل"، اليوم: "رقمي"، السنة: 'رقمية'، الساعة: "مكونة من رقمين"، الدقيقة: "مكونة من رقمين" })); // 22 فبراير 2026 الساعة 8:23 مساءً
// قم بتمرير الحقول التي تريدها فقط في سلسلة التنسيق console.log(date.toLocaleString('en-US', { الشهر: "قصير"، اليوم: "رقمي" })); // 22 فبراير
يستخدم تنسيق التاريخ المؤقت في الواقع واجهة برمجة التطبيقات Intl.DateTimeFormat (المتوفرة بالفعل في المتصفحات الحديثة) أسفل الغطاء. وهذا يعني أنه يمكنك إنشاء كائن DateTimeFormat قابل لإعادة الاستخدام باستخدام خيارات التنسيق المخصصة، ثم تمرير الكائنات المؤقتة إلى طريقة التنسيق الخاصة به. ولهذا السبب، فهو لا يدعم تنسيقات التاريخ المخصصة مثل Moment. إذا كنت بحاجة إلى شيء مثل "الربع الأول من عام 2026" أو أي تنسيق متخصص آخر، فقد تحتاج إلى بعض التعليمات البرمجية المخصصة لتنسيق التاريخ أو الوصول إلى مكتبة تابعة لجهة خارجية. منسق const = new Intl.DateTimeFormat('en-US', { الشهر: "مكون من رقمين"، اليوم: "مكون من رقمين"، السنة: "رقمية" });
تاريخ ثابت = Temporal.Now.instant(); console.log(formatter.format(date)); // 22/02/2026
تعد رموز التنسيق المميزة لـ Moment أسهل في الكتابة، ولكنها ليست مناسبة للغة المحلية. سلاسل التنسيق "الكود الثابت" هي أشياء مثل ترتيب الشهر/اليوم. تتمثل ميزة استخدام كائن التكوين، كما يفعل Temporal، في أنه سيتكيف تلقائيًا مع أي لغة محددة ويستخدم التنسيق الصحيح. تاريخ ثابت = Temporal.Now.instant();
خيارات تنسيق ثابت = { الشهر: 'رقمي'، اليوم: "رقمي"، السنة: "رقمية" };
console.log(date.toLocaleString('en-US', formatOptions)); // 22/02/2026
console.log(date.toLocaleString('en-GB', formatOptions)); // 22/02/2026
حسابات التاريخ في العديد من التطبيقات، ستحتاج في النهاية إلى إجراء بعض العمليات الحسابية في تاريخ ما. قد ترغب في إضافة أو طرح وحدات زمنية (أيام، ساعات، ثواني، إلخ). على سبيل المثال، إذا كان لديك التاريخ الحالي، فقد ترغب في إظهار التاريخ للمستخدم بعد أسبوع واحد من الآن. تحتوي كائنات اللحظة على طرق مثل الجمع والطرح التي تنفذ هذه العمليات. تأخذ هذه الوظائف قيمة ووحدة، على سبيل المثال: add(7, 'days'). ومع ذلك، هناك اختلاف مهم جدًا بين Moment وTemporal، وهو أنه عند إجراء حسابات التاريخ هذه، يتم تعديل الكائن الأساسي ويتم فقدان قيمته الأصلية. ثابت الآن = لحظة ()؛
console.log(now); // لحظة<2026-02-24T20:08:36-05:00>
const nextWeek = now.add(7, 'days'); console.log(nextWeek); // لحظة<2026-03-03T20:08:36-05:00>
// مسكتك - تم تحور الكائن الأصلي console.log(now); // لحظة<2026-03-03T20:08:36-05:00>
لتجنب فقدان التاريخ الأصلي، يمكنك استدعاء clone على كائن Moment لإنشاء نسخة. ثابت الآن= لحظة()؛ const nextWeek = now.clone().add(7, 'days');
console.log(now); // لحظة<2026-02-24T20:12:55-05:00>
console.log(nextWeek); // لحظة<2026-03-03T20:12:55-05:00>
من ناحية أخرى، الكائنات الزمنية غير قابلة للتغيير. بمجرد إنشاء كائن مثل Instant وPlainDate وما إلى ذلك، لن تتغير قيمة هذا الكائن أبدًا. تحتوي الكائنات المؤقتة أيضًا على طرق الجمع والطرح. يعد Temporary أمرًا صعب الإرضاء بعض الشيء بشأن الوحدات الزمنية التي يمكن إضافتها إلى أنواع الكائنات. على سبيل المثال، لا يمكنك إضافة أيام إلى لحظة:
const now = Temporal.Now.instant(); const nextWeek = now.add({ day: 7 }); // RangeError: خطأ مؤقت: لا يمكن أن تكون الوحدة الأكبر وحدة تاريخ
وذلك لأن الكائنات الفورية تمثل نقطة زمنية محددة بالتوقيت العالمي المنسق (UTC) ولا تعتمد على التقويم. نظرًا لأن طول اليوم يمكن أن يتغير بناءً على قواعد المنطقة الزمنية مثل التوقيت الصيفي، فإن هذا الحساب غير متاح في اللحظة الفورية. ومع ذلك، يمكنك إجراء هذه العملية على أنواع أخرى من الكائنات، مثل PlainDateTime: const now = Temporal.Now.plainDateTimeISO(); console.log(now.toLocaleString()); // 24/02/2026، 8:23:59 مساءً
const nextWeek = now.add({ day: 7 });
// لاحظ أن PlainDateTime الأصلي يظل دون تغيير console.log(now.toLocaleString()); // 24/02/2026، 8:23:59 مساءً
console.log(nextWeek.toLocaleString()); // 3/3/2026، 8:23:59 مساءً
يمكنك أيضًا حساب مقدار الوقت بين كائنين Moment أو Temporal. باستخدام دالة الفرق في Moment، تحتاج إلى توفير وحدة للتفاصيل، وإلا فإنها ستعيد الفرق بالمللي ثانية. تاريخ ثابت1 = لحظة('2026-02-21T09:00:00'); تاريخ ثابت2 = لحظة('2026-02-22T10:30:00');
console.log(date2.diff(date1)); // 91800000
console.log(date2.diff(date1, 'days')); // 1
للقيام بذلك باستخدام كائن مؤقت، يمكنك تمرير كائن مؤقت آخر إلى الأساليب الخاصة به حتى أو منذ ذلك الحين. يؤدي هذا إلى إرجاع كائن Temporal.Duration الذي يحتوي على معلومات حول فارق التوقيت. يحتوي كائن Duration على خصائص لكل مكون من مكونات الفرق، ويمكنه أيضًا إنشاء سلسلة مدة ISO 8601 تمثل فرق الوقت.
تاريخ ثابت1 = Temporal.PlainDateTime.from('2026-02-21T09:00:00'); تاريخ ثابت2 = Temporal.PlainDateTime.from('2026-02-22T10:30:00');
// أكبر وحدة تحدد أكبر وحدة زمنية لتمثيلها // في حساب المدة const diff = date2.since(date1, { bigUnit: 'day' });
console.log(diff.days); // 1
console.log(diff.hours); // 1
console.log(diff.Minutes); // 30
console.log(diff.toString()); // P1DT1H30M // (سلسلة المدة ISO 8601: يوم واحد، ساعة واحدة، 30 دقيقة)
مقارنة التواريخ والأوقات يتيح لك كل من Moment وTemporal مقارنة التواريخ والأوقات لتحديد أيهما يأتي قبل الآخر، ولكن مع اتباع أساليب مختلفة مع واجهة برمجة التطبيقات. توفر Moment أساليب مثل isBefore، وisAfter، وisSame لمقارنة كائنين من كائنات Moment. تاريخ ثابت1 = لحظة('2026-02-21T09:00:00'); تاريخ ثابت2 = لحظة('2026-02-22T10:30:00');
console.log(date1.isBefore(date2)); // صحيح
يستخدم Temporal طريقة مقارنة ثابتة لإجراء مقارنة بين كائنين من نفس النوع. تُرجع -1 إذا كان التاريخ الأول يأتي قبل الثاني، أو 0 إذا كانا متساويين، أو 1 إذا كان التاريخ الأول يأتي بعد الثاني. يوضح المثال التالي كيفية مقارنة كائنين PlainDate. يجب أن تكون كلا الوسيطتين إلى Temporal.PlainDate.compare كائنات PlainDate.
const date1 = Temporal.PlainDate.from({ سنة: 2026، شهر: 2، يوم: 24 }); const date2 = Temporal.PlainDate.from({ سنة: 2026، شهر: 3، يوم: 24 });
// date1 يأتي قبل date2، لذا -1 console.log(Temporal.PlainDate.compare(date1, date2));
// خطأ إذا حاولنا مقارنة كائنين من نوعين مختلفين console.log(Temporal.PlainDate.compare(date1, Temporal.Now.instant())); // TypeError: خطأ مؤقت: تم توفير حقول PlainDate غير صالحة.
على وجه الخصوص، هذا يجعل من السهل فرز مجموعة من الكائنات الزمنية بتسلسل زمني. // مصفوفة من كائنات Temporal.PlainDate تواريخ ثابتة = [...]؛
// استخدم Temporal.PlainDate.compare كدالة للمقارنة dates.sort(Temporal.PlainDate.compare);
تحويلات المنطقة الزمنية لا تدعم مكتبة Moment الأساسية تحويلات المنطقة الزمنية. إذا كنت بحاجة إلى هذه الوظيفة، فستحتاج أيضًا إلى تثبيت حزمة moment-timezone. هذه الحزمة ليست قابلة للاهتزاز، وبالتالي يمكن أن تضيف بشكل كبير إلى حجم الحزمة الخاصة بك. بمجرد تثبيت moment-timezone، يمكنك تحويل كائنات Moment إلى مناطق زمنية مختلفة باستخدام التابع tz. كما هو الحال مع عمليات اللحظة الأخرى، يؤدي هذا إلى تغيير الأساسهدف. // بافتراض التوقيت الشرقي للولايات المتحدة ثابت الآن = لحظة ()؛ console.log(now); // لحظة<2026-02-28T20:08:20-05:00>
// تحويل إلى توقيت المحيط الهادئ. // ضاع التوقيت الشرقي الأصلي. now.tz('America/Los_Angeles'); console.log(now); // لحظة<2026-02-28T17:08:20-08:00>
تم تضمين وظيفة المنطقة الزمنية في Temporal API عند استخدام كائن Temporal.ZonedDateTime. تتضمن هذه الكائنات طريقة withTimeZone التي تقوم بإرجاع ZonedDateTime جديد يمثل نفس اللحظة الزمنية، ولكن في المنطقة الزمنية المحددة. // مرة أخرى، بافتراض التوقيت الشرقي للولايات المتحدة const now = Temporal.Now.zonedDateTimeISO(); console.log(now.toLocaleString()); // 28/02/2026، الساعة 8:12:02 مساءً بتوقيت شرق الولايات المتحدة
// تحويل إلى توقيت المحيط الهادئ const nowPacific = now.withTimeZone('America/Los_Angeles'); console.log(nowPacific.toLocaleString()); // 28/02/2026، الساعة 5:12:02 مساءً بتوقيت المحيط الهادئ
// يبقى الكائن الأصلي دون تغيير console.log(now.toLocaleString()); // 28/02/2026، الساعة 8:12:02 مساءً بتوقيت شرق الولايات المتحدة
ملاحظة: القيم المنسقة التي يتم إرجاعها بواسطة toLocaleString، كما يوحي الاسم، تعتمد على اللغة. تم تطوير نموذج التعليمات البرمجية باللغة الإنجليزية بالولايات المتحدة، لذا يكون التنسيق كما يلي: 28/02/2026، 5:12:02 م بتوقيت المحيط الهادئ. في لغة أخرى، قد يكون هذا مختلفا. على سبيل المثال، في لغة en-GB، ستحصل على شيء مثل 28/2/2026، 17:12:02 GMT-8. إعادة هيكلة العالم الحقيقي لنفترض أننا نبني تطبيقًا لجدولة الأحداث عبر المناطق الزمنية. جزء من هذا التطبيق عبارة عن وظيفة، getEventTimes، والتي تأخذ سلسلة ISO 8601 تمثل وقت وتاريخ الحدث، والمنطقة الزمنية المحلية، والمنطقة الزمنية المستهدفة. تقوم الوظيفة بإنشاء سلاسل زمنية وتاريخ منسقة للحدث في كلا المنطقتين الزمنيتين. إذا تم إعطاء الدالة سلسلة إدخال ليست سلسلة وقت/تاريخ صالحة، فسوف يؤدي ذلك إلى حدوث خطأ. إليك التنفيذ الأصلي، باستخدام Moment (يتطلب أيضًا استخدام حزمة moment-timezone).
لحظة الاستيراد من "المنطقة الزمنية لحظة"؛
وظيفة getEventTimes(inputString, userTimeZone, targetTimeZone) { const timeFormat = 'MMM D, YYYY, h:mm:ss a z';
// 1. أنشئ اللحظة الأولية بالمنطقة الزمنية للمستخدم زمن الحدث الثابت = moment.tz( سلسلة الإدخال, moment.ISO_8601، // توقع سلسلة ISO 8601 صحيح، // تحليل صارم userTimeZone );
// قم بإلقاء خطأ إذا كانت سلسلة الإدخال لا تمثل تاريخًا صالحًا إذا (!eventTime.isValid()) { رمي خطأ جديد ("إدخال التاريخ/الوقت غير صالح")؛ }
// 2. احسب الوقت المستهدف // أمر بالغ الأهمية: يجب علينا الاستنساخ، وإلا سيتغير "eventTime" إلى الأبد! const targetTime = eventsTime.clone().tz(targetTimeZone);
العودة { محلي: eventsTime.format(timeFormat)، الهدف: targetTime.format(timeFormat)، }; }
جدول ثابت = getEventTimes( "2026-03-05T15:00-05:00"، "أمريكا/نيويورك"، "أوروبا/لندن"، );
console.log(schedule.local); // 5 مارس 2026، الساعة 3:00:00 مساءً بالتوقيت الشرقي
console.log(schedule.target); // 5 مارس 2026، الساعة 8:00:00 مساءً بتوقيت جرينتش
في هذا المثال، نستخدم تنسيق التاريخ المتوقع ISO 8601، والذي تم دمجه بشكل مفيد في Moment. نحن نستخدم أيضًا تحليلًا صارمًا، مما يعني أن Moment لن تحاول التخمين باستخدام سلسلة تاريخ لا تتطابق مع التنسيق. إذا تم تمرير سلسلة تاريخ غير ISO، فسيؤدي ذلك إلى كائن تاريخ غير صالح، وسنقوم بإلقاء خطأ. يبدو التنفيذ الزمني مشابهًا، لكن به بعض الاختلافات الرئيسية.
وظيفة getEventTimes(inputString, userTimeZone, targetTimeZone) { // 1. قم بتحليل الإدخال مباشرة إلى لحظة، ثم قم بإنشائه // ZonedDateTime في منطقة المستخدم. const Instant = Temporal.Instant.from(inputString); const eventsTime = Instant.toZonedDateTimeISO(userTimeZone);
// 2. تحويل إلى المنطقة المستهدفة // يؤدي هذا تلقائيًا إلى إرجاع كائن جديد؛ "eventTime" آمن. const targetTime = eventsTime.withTimeZone(targetTimeZone);
// 3. التنسيق باستخدام Intl (مدمج) خيارات ثابتة = { السنة: 'رقمية'، الشهر: "قصير"، اليوم: "رقمي"، الساعة: 'رقمية'، الدقيقة: "مكونة من رقمين"، الثاني: "رقمان"، اسم المنطقة الزمنية: "قصير" };
العودة { محلي: eventsTime.toLocaleString(navigator.language، options)، الهدف: targetTime.toLocaleString(navigator.language، options) }; }
جدول ثابت = getEventTimes( "2026-03-05T15:00-05:00"، "أمريكا/نيويورك"، "أوروبا/لندن"، );
console.log(schedule.local); // 5 مارس 2026، الساعة 3:00:00 مساءً بالتوقيت الشرقي
console.log(schedule.target); // 5 مارس 2026، الساعة 8:00:00 مساءً بتوقيت جرينتش
باستخدام Moment، علينا أن نحدد بوضوح سلسلة تنسيق لسلاسل التاريخ الناتجة. بغض النظر عن موقع المستخدم أو مكانه، سيتم تنسيق أوقات الحدث دائمًا على النحو التالي: 5 مارس 2026، الساعة 3:00:00مساءً بتوقيت شرق الولايات المتحدة. كما أننا لا نحتاج إلى طرح استثناء بشكل صريح. إذا تم تمرير سلسلة غير صالحة إلى Temporal.Instant.from، فسيطرح Temporal الاستثناء لنا. شيء واحد يجب ملاحظته هو أنه حتى مع التحليل الصارم، فإن إصدار Moment لا يزال أكثر تساهلاً. يتطلب Temporal إزاحة المنطقة الزمنية في نهاية السلسلة. يجب عليك أيضًا ملاحظة أنه نظرًا لأننا نستخدم navigator.language، فلن يتم تشغيل هذا الرمز إلا في بيئة المتصفح، حيث لم يتم تعريف navigator في بيئة Node.js. يستخدم التنفيذ المؤقت اللغة المحلية الحالية للمتصفح (navigator.language)، لذلك سيحصل المستخدم تلقائيًا على أوقات الأحداث المنسقة بتنسيق التوقيت المحلي الخاص به. باللغة الإنجليزية بالولايات المتحدة، هذا هو 5 مارس 2026، الساعة 3:00:00 مساءً بالتوقيت الشرقي. ومع ذلك، إذا كان المستخدم في لندن، على سبيل المثال، فسيتم تنسيق أوقات الحدث على النحو التالي: 5 مارس 2026، الساعة 15:00:00 بتوقيت جرينتش-5. ملخص
العمل لحظة.js زمني الوقت الحالي لحظة () Temporal.Now.zonedDateTimeISO() تحليل ISO لحظة (شارع) Temporal.Instant.from(str) أضف الوقت .add(7, 'days') (يتحول) .add({ أيام: 7 }) (كائن جديد) الفرق .diff(أخرى، 'ساعات') .منذ (أخرى).ساعات المنطقة الزمنية .tz('المنطقة/الاسم') .withTimeZone('المنطقة/الاسم')
للوهلة الأولى، قد يكون الفرق مختلفًا قليلاً (وفي حالة Temporal، أحيانًا يكون أكثر تفصيلاً وأكثر صرامة)، ولكن هناك العديد من المزايا الرئيسية لاستخدام Temporal على Moment.js:
كونك أكثر وضوحًا يعني عددًا أقل من المفاجآت والأخطاء غير المقصودة. قد تبدو اللحظة أكثر تساهلاً، ولكنها تنطوي على "التخمين"، مما قد يؤدي أحيانًا إلى تواريخ غير صحيحة. إذا أعطيت شيئًا مؤقتًا غير صالح، فسيؤدي ذلك إلى حدوث خطأ. إذا تم تشغيل الرمز، فأنت تعلم أن لديك تاريخًا صالحًا. يمكن أن يضيف Moment حجمًا كبيرًا إلى حزمة التطبيق، خاصة إذا كنت تستخدم حزمة moment-timezone. لا يضيف Temporal أي شيء (بمجرد شحنه إلى متصفحاتك المستهدفة). تمنحك الثبات الثقة بأنك لن تفقد البيانات أو تستبدلها أبدًا عند إجراء تحويلات وعمليات التاريخ. تمثيلات مختلفة للوقت (Instant، وPlainDateTime، وZonedDateTime) وفقًا لمتطلباتك، حيث تكون Moment دائمًا عبارة عن غلاف حول طابع زمني UTC. يستخدم Temporal واجهات برمجة التطبيقات الدولية لتنسيق التاريخ، مما يعني أنه يمكنك الحصول على تنسيق مدرك للغة دون الحاجة إلى تحديد الرموز المميزة بشكل صريح.
ملاحظات على Polyfill كما ذكرنا سابقًا، هناك polyfill مؤقت متاح، يتم توزيعه كحزمة npm باسم @js-temporal/polyfill. إذا كنت تريد استخدام Temporal اليوم، فستحتاج إلى هذا polyfill لدعم المتصفحات مثل Safari التي لم تقم بشحن واجهة برمجة التطبيقات بعد. الخبر السيئ في هذا هو أنه سيضيف إلى حجم الحزمة الخاصة بك. والخبر السار هو أنه لا يزال يضيف أقل بكثير من المنطقة الزمنية اللحظية أو اللحظية. فيما يلي مقارنة لأحجام الحزم كما ورد في موقع Bundlephobia.com، وهو موقع يقدم معلومات عن أحجام حزم npm (انقر على اسم كل حزمة لرؤية تحليل Bundlephobia):
الحزمة مصغر مصغر ومضغوط بصيغة gzip @js-temporal/polyfill 154.1 كيلو بايت 44.1 كيلو بايت لحظة 294.4 كيلو بايت 75.4 كيلو بايت المنطقة الزمنية 1 ميجا بايت 114.2 كيلو بايت
واجهت عملية polyfill تاريخيًا بعض مشكلات الأداء المتعلقة باستخدام الذاكرة، وفي وقت كتابة هذا التقرير، كانت تعتبر في حالة ألفا. ولهذا السبب، قد لا ترغب في استخدامه في الإنتاج حتى يصل إلى حالة أكثر نضجًا. والخبر السار الآخر هو أنه من المأمول ألا تكون هناك حاجة إلى polyfill لفترة أطول (إلا إذا كنت بحاجة إلى دعم المتصفحات الأقدم بالطبع). في وقت كتابة هذا التقرير، تم شحن Temporal إلى متصفحات Chrome وEdge وFirefox. إنه ليس جاهزًا تمامًا في Safari حتى الآن، على الرغم من أنه يبدو أنه متاح مع علامة وقت التشغيل في أحدث معاينة تقنية.