يبدو الوقت بسيطاً حتى تحاول كتابة برنامج يتعامل معه بشكل صحيح. حدث مجدول لـ "الساعة 3 مساءً" يعني أشياء مختلفة في طوكيو ولندن ونيويورك. التوقيت الصيفي ينقل الساعات للأمام أو الخلف — لكن ليس في كل مكان، وليس في نفس التواريخ. طابع زمني يبدو صحيحاً في بيئتك المحلية يتعطل في الإنتاج لأن الخادم في منطقة زمنية مختلفة.
المناطق الزمنية واحدة من أكثر المواضيع إرباكاً بشكل موثوق في تطوير البرمجيات. تشرح هذه المقالة كيف تعمل، ومن أين يأتي التعقيد، وكيف تتجنب الأخطاء الأكثر شيوعاً.
لماذا توجد المناطق الزمنية
تدور الأرض 360 درجة في 24 ساعة، مما يعني أن الشمس تكون في أعلى نقطة لها في لحظات مختلفة حسب خط الطول. قبل القرن التاسع عشر، كانت كل مدينة تضبط ساعاتها على التوقيت الشمسي المحلي — الظهيرة كانت عندما تكون الشمس فوق الرأس. نجح هذا حتى ربطت السكك الحديدية المدن البعيدة واحتاج جدول القطار إلى ساعة واحدة متسقة.
في عام 1884، اجتمع مندوبون من 25 دولة في مؤتمر خط الطول الدولي في واشنطن العاصمة واتفقوا على تقسيم العالم إلى 24 منطقة زمنية قياسية، كل منها منزاحة عن خط الطول الرئيسي (صفر درجة) المار بغرينتش، إنجلترا.
في الواقع، حدود المناطق الزمنية تتبع الحدود السياسية، وليس خطوط الطول المنتظمة. الصين تمتد عبر خمس مناطق جغرافية لكنها تستخدم توقيتاً رسمياً واحداً (UTC+8). الهند تستخدم UTC+5:30 — انزياح نصف ساعة. نيبال تستخدم UTC+5:45. خريطة المناطق الزمنية الفعلية فوضوية.
UTC مقابل GMT
GMT (توقيت غرينتش) هو متوسط التوقيت الشمسي في المرصد الملكي في غرينتش. كان المرجع الزمني العالمي لأكثر من قرن.
UTC (التوقيت العالمي المنسق) حل محل GMT كمعيار دولي في 1972. يعتمد UTC على الساعات الذرية بدلاً من الرصد الفلكي، مما يجعله أكثر دقة بكثير. لأغراض عملية، يظهر UTC وGMT نفس الوقت، لكن UTC هو المرجع التقني الصحيح.
لماذا "UTC" وليس "CUT"؟ الاختصار هو حل وسط بين الإنجليزية "Coordinated Universal Time" (CUT) والفرنسية "Temps Universel Coordonné" (TUC). لم يحصل أي طرف على اختصاره المفضل، فاختير UTC كبديل محايد لغوياً.
التوقيت الصيفي: فوضى منظمة
تلتزم نحو 70 دولة بـ التوقيت الصيفي (DST)، حيث تُقدَّم الساعات ساعة واحدة في الربيع وتُؤخَّر في الخريف. الهدف هو مواءمة ساعات اليقظة مع ضوء النهار. النتيجة هي مصدر أخطاء نصف سنوي.
التعقيدات الرئيسية:
- ليس عالمياً. معظم أفريقيا وآسيا وأمريكا الجنوبية لا تلتزم بالتوقيت الصيفي. داخل الولايات المتحدة، أريزونا وهاواي لا تطبقانه.
- تواريخ مختلفة. الاتحاد الأوروبي ينتقل في آخر أحد من مارس وأكتوبر. الولايات المتحدة تنتقل في ثاني أحد من مارس وأول أحد من نوفمبر. يكونان غير متزامنين لعدة أسابيع كل عام.
- أوقات ملتبسة. عندما تُؤخَّر الساعات، تحدث الساعة من 1:00 صباحاً إلى 2:00 صباحاً مرتين. طابع زمني "1:30 صباحاً" في ذلك اليوم ملتبس.
- أوقات محذوفة. عندما تُقدَّم الساعات، الساعة من 2:00 صباحاً إلى 3:00 صباحاً لا توجد. اجتماع مجدول في 2:30 صباحاً في ذلك اليوم لا يحدث أبداً.
- تغييرات سياسية. يمكن للحكومات (وتفعل) تغيير قواعد التوقيت الصيفي بإشعار قصير. اعتمدت روسيا توقيتاً صيفياً دائماً في 2011، ثم انتقلت إلى توقيت قياسي دائم في 2014. غيّر المغرب قواعد التوقيت الصيفي عدة مرات.
ISO 8601: تنسيق التاريخ العالمي
لتجنب الالتباس، يحدد المعيار الدولي ISO 8601 تنسيقاً واضحاً للتاريخ والوقت:
2026-03-29T14:30:00Z
2026-03-29T14:30:00+02:00
2026-03-29T14:30:00-05:00
- الحرف
Tيفصل التاريخ عن الوقت. Zتعني UTC (منطقة "زولو" الزمنية في المصطلحات العسكرية).+02:00أو-05:00هو الانزياح عن UTC.
هذا التنسيق غير ملتبس، قابل للترتيب كنص عادي، ومفهوم عالمياً من مكتبات تحليل التواريخ. عند الشك، استخدم ISO 8601.
طوابع Unix الزمنية
طابع Unix الزمني (يسمى أيضاً وقت الحقبة أو وقت POSIX) هو عدد الثواني المنقضية منذ 1 يناير 1970، 00:00:00 UTC — لحظة تُعرف بـ حقبة Unix.
| قابل للقراءة البشرية | طابع Unix الزمني |
|---|---|
| 1970-01-01 00:00:00 UTC | 0 |
| 2000-01-01 00:00:00 UTC | 946684800 |
| 2026-03-29 12:00:00 UTC | 1774987200 |
طوابع Unix الزمنية ليس لها منطقة زمنية — فهي دائماً بتوقيت UTC. هذا يجعلها مثالية لتخزين الأوقات ومقارنتها في البرمجيات. تحوّل إلى المنطقة الزمنية المحلية فقط في طبقة العرض.
مشكلة عام 2038: الأنظمة التي تخزن طوابع Unix الزمنية كعدد صحيح بإشارة 32 بت ستفيض في 19 يناير 2038 الساعة 03:14:07 UTC. القيمة القصوى (2,147,483,647) تتحول إلى رقم سالب يُفسَّر كديسمبر 1901. معظم الأنظمة الحديثة تستخدم أعداداً صحيحة 64 بت، والتي لن تفيض لمدة 292 مليار سنة أخرى.
قاعدة بيانات IANA للمناطق الزمنية
لا تحتاج البرمجيات فقط لانزياحات UTC — بل تحتاج معرفة التاريخ الكامل والقواعد المستقبلية لكل منطقة، بما في ذلك انتقالات التوقيت الصيفي والتغييرات السياسية والشذوذات التاريخية. هذه المعلومات موجودة في قاعدة بيانات IANA للمناطق الزمنية (تسمى أيضاً قاعدة بيانات Olson أو tzdata).
تستخدم معرّفات مثل America/New_York وEurope/Paris وAsia/Tokyo. كل إدخال يُرمّز التاريخ الكامل لانزياحات UTC وقواعد التوقيت الصيفي لذلك الموقع.
لهذا يجب عليك ألا تخزن منطقة زمنية أبداً كانزياح ثابت مثل "+02:00". الانزياح يخبرك بالفرق الحالي عن UTC لكن لا يقول شيئاً عن قواعد التوقيت الصيفي. Europe/Paris هي UTC+1 في الشتاء وUTC+2 في الصيف. معرّف IANA يلتقط كليهما.
الأخطاء الشائعة في البرمجيات
- تخزين التوقيت المحلي بدون منطقة زمنية. قيمة مثل
2026-03-29 14:30:00لا معنى لها بدون معرفة المنطقة الزمنية المقصودة. خزّن دائماً UTC أو أضف الانزياح. - افتراض أن انزياح UTC يساوي المنطقة الزمنية. UTC+2 في مارس قد يكون UTC+3 في يوليو (إذا كانت المنطقة تلتزم بالتوقيت الصيفي). خزّن معرّف IANA، وليس الانزياح.
- تجاهل انتقالات التوقيت الصيفي في الجدولة. مهمة يومية في 2:30 صباحاً ستُتخطى مرة في السنة وتعمل مرتين مرة في السنة إذا لم تتعامل مع التوقيت الصيفي.
- افتراض أن الأيام 24 ساعة. في أيام انتقال التوقيت الصيفي، اليوم 23 أو 25 ساعة. حساب "غداً في نفس الوقت" بإضافة 86,400 ثانية سيكون خاطئاً بساعة.
- استخدام
Dateفي JavaScript بسذاجة.new Date("2026-03-29")يُحلل كـ UTC في بعض المحركات وكتوقيت محلي في أخرى. كن دائماً صريحاً حول المنطقة الزمنية.
أفضل الممارسات للمطورين
- خزّن الأوقات بتوقيت UTC. حوّل إلى المنطقة الزمنية المحلية للمستخدم فقط في طبقة العرض.
- استخدم معرّفات IANA للمناطق الزمنية (
America/New_York)، وليس الانزياحات الثابتة (-05:00). - استخدم ISO 8601 للتسلسل. غير ملتبس وقابل للتحليل عالمياً.
- استخدم مكتبة تواريخ ناضجة. في JavaScript، استخدم
Intl.DateTimeFormatأو مكتبة مثلdate-fns-tz. في Python، استخدمzoneinfo(3.9+) أوpytz. في Java، استخدمjava.time.ZonedDateTime. - حدّث
tzdataباستمرار. الحكومات تغير قواعد التوقيت الصيفي. نظام تشغيلك وبيئة تشغيل لغتك يحتاجان بيانات مناطق زمنية محدثة. - اختبر بمناطق زمنية متعددة. لا تفترض أن خادمك ومستخدميك يتشاركون نفس المنطقة.
للمزيد
الوقت معقد بشكل خادع، لكن القواعد موثقة جيداً والأدوات ناضجة. المفتاح هو احترام التعقيد بدلاً من افتراض عدم وجوده.
- تعبيرات Cron مبسّطة — جدولة المهام عبر المناطق الزمنية
- مولد التجزئة واختبار Regex — أدوات مطورين أخرى على ToolK
