أوقات المناطق هي كذب (وكيفية التعامل معها في الكود)

نُشرت في

تبدو مناطق الوقت بسيطة على خريطة، لكنها ليست كذلك. إليك السبب في أن تُعطل البرمجيات — ونموذج التفكير الصحيح لمعالجة الوقت في الكود.

أوقات المناطق الزمنية هي كذب (وكيفية التعامل معها في الكود) 1
إعلان · حذف؟

تُفتح خريطة. ترى قطعًا عمودية. "الوقت المعياري UTC-5 هو وقت الشرق، والوقت المعياري UTC+1 هو وقت أوروبا الوسطى." بسيط، صحيح؟

خاطئ. مناطق الأوقات هي بناء سياسي، وليس حقيقة جغرافية — وتمييز هذا سيُنقذك من بعض الأخطاء الأسوأ في تطوير البرمجيات.

لماذا مناطق الأوقات هي فوضى حقيقية

إليك ما يُديره بيئة نظام التشغيل الخاصة بك من تلقائيًا:

  • الوقت المُخصص للساعات (DST) — لا يُطبق في كل الدول، تتغير القوانين في الدول المختلفة، ويحدث التحول في أوقات مختلفة حسب المكان. تغيرت الولايات المتحدة في عام 2007. ألغت مصر الـ DST في عام 2011، ثم أعادت تطبيقه، ثم ألغته مرة أخرى.
  • الانحرافات التي تصل إلى نصف ساعة أو ربع ساعة — توجد الهند (UTC+5:30)، نيبال (UTC+5:45)، وأجزاء من أستراليا (UTC+9:30). افتراضك أن الانحرافات تكون بساعات كاملة هو خاطئ.
  • التعديلات التاريخية — انتقلت روسيا من UTC+4 إلى UTC+3 في عام 2014. تجنب ساموا يومًا كاملًا (30 ديسمبر 2011) للانتقال من جانب خط التاريخ الدولي إلى الجانب الآخر. عند التعامل مع تواريخ تاريخية، قد يكون الانحراف الصحيح مختلفًا تمامًا عن اليوم الحالي.
  • الوقت غير المحدد — عند عودة الساعات، يحدث 1:30 صباحًا مرتين. عند التقدم إلى الساعات، لا يوجد 2:30 صباحًا تمامًا. إذا كنت تُخزن "3 نوفمبر 2024 في 1:45 صباحًا في الشرق" دون انحراف UTC، فإنك تمتلك تواريخ غير محددة.

هذا ليس مجرد معلومات مُهمة. كل حالة من هذه الحالات أسببت أخطاء حقيقية في التطبيقات المنتجة — مثل تجاهل المهام التقويمية، تطبيق مبالغ، أو تلف أنظمة التخطيط.

القاعدة الوحيدة التي تحل معظم المشكلات

تُخزن وتُعالج بالوقت المعياري (UTC). تُحوّل إلى الوقت المحلي فقط عند عرضه.

هذه ليست معلومة مثيرة للجدل. هي رأي متفق عليه من كل قاعدة بيانات رئيسية، وجميع معايير الواجهات، وجميع فرق أنظمة التوزيع. إذا كانت عمود قاعدة البيانات تُخزن 2024-11-03 06:45:00 بشكل معياري (UTC)، فإنك تعرف بدقة ما هو لحظة الزمن الممثلة — بغض النظر عن مكان خادمك، أو وقت المنطقة الذي يقع فيه المستخدم، أو ما إذا كان حدث التغيير في وقت الصيف في ذلك اليوم.

عندما تُخزن 2024-11-03 01:45:00 بدون انحراف معياري (UTC)، فقدت المعلومات. أنشأت تواريخ تُعني بساعتين مختلفتين.

كيفية التعامل مع مناطق الأوقات في JavaScript

النظام المدمج في JavaScript Date يُخزن الوقت كمليون مللي ثانية منذ بداية النظام (1 يناير 1970 UTC) — وهذا جيد. المشكلة هي أن واجهته غير واضحة ومتناقضة.

ما يجب تجنبه

// BAD: Parsing without explicit timezone
const d = new Date('2024-11-03 01:45:00');
// Interpreted as LOCAL time — behavior varies by environment

// BAD: Storing user-facing strings as dates
const meeting = '3:00 PM Thursday';
// This is meaningless without a timezone

ما يجب استخدامه بدلًا من ذلك

// GOOD: Always use ISO 8601 with explicit UTC offset
const d = new Date('2024-11-03T06:45:00Z'); // Z = UTC

// GOOD: Display in user's local timezone using Intl API
const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'America/New_York',
  dateStyle: 'full',
  timeStyle: 'short',
});
console.log(formatter.format(d)); // "Sunday, November 3, 2024 at 1:45 AM"

إذا كنت تبني أي شيء يتجاوز تنسيق التاريخ البسيط، فاستخدم هي خيار ممتاز آخر. Moment.js هو مكتمل الوظائف لكنه لم يُطور منذ زمن بعيد — انتقل بعيدًا عنه. مكتبة. تمتلك دعمًا متميزًا للمنطقة الزمنية، تتعامل بشكل صحيح مع التحولات في وقت الصيف، وتوضح نية كودك بشكل واضح.

import { DateTime } from 'luxon';

// Parse an ISO string and convert to a specific zone
const utc = DateTime.fromISO('2024-11-03T06:45:00Z');
const eastern = utc.setZone('America/New_York');
console.log(eastern.toLocaleString(DateTime.DATETIME_FULL));
// "November 3, 2024, 1:45 AM EDT"

كيفية التعامل مع مناطق الأوقات في Python

في بيئة بيئة بيثون datetime مودول يميز بين مُبهم (بدون مناطق زمنية) و مُوعِد (مع مناطق زمنية) لـ أوقات المُدخلات. الأوقات المُبهمة هي مُحفز خطر — تجنبها في أي كود يتجاوز حدود مناطق الأوقات.

from datetime import datetime, timezone
import zoneinfo  # Python 3.9+

# BAD: naive datetime (no timezone info)
d = datetime(2024, 11, 3, 1, 45, 0)

# GOOD: always attach a timezone
d_utc = datetime(2024, 11, 3, 6, 45, 0, tzinfo=timezone.utc)

# Convert to a specific timezone
eastern = zoneinfo.ZoneInfo('America/New_York')
d_eastern = d_utc.astimezone(eastern)
print(d_eastern)  # 2024-11-03 01:45:00-05:00

لأقدم إصدارات Python أو احتياجات التخطيط المعقدة، python-dateutil و سهم هي خيارات مُحافظة جيدة. المبدأ الرئيسي يبقى كما هو: العمل بالوقت المعياري (UTC)، والتحويل عند الحدود.

كيفية التعامل مع مناطق الأوقات في قواعد البيانات

معالجة مناطق الأوقات في قواعد البيانات تُسبب أخطاء حتى للمطورين المُتمرسين.

PostgreSQL

يملك PostgreSQL نوعين من تواريخ المُدخلات: timestamp (بدون مناطق زمنية) و timestamptz (مع مناطق زمنية). على الرغم من الاسم، timestamptz لا يخزن الفعلي مناطق الأوقات — بل يحول إلى الوقت المعياري (UTC) عند الكتابة ويحول إلى منطقية الجلسة عند القراءة. هذا هو السلوك الصحيح. استخدم دائمًا timestamptz.

-- BAD
CREATE TABLE events (created_at TIMESTAMP);

-- GOOD
CREATE TABLE events (created_at TIMESTAMPTZ);

-- Querying across timezones
SELECT created_at AT TIME ZONE 'America/New_York' FROM events;

MySQL

في قاعدة بيانات ماريا دب DATETIME التي لا تحتوي على سياق مناطق الأوقات — ما تضعه هو ما تأخذها، دون تحويل. TIMESTAMP يُحوّل إلى الوقت المعياري (UTC) عند الكتابة ويُحوّل إلى منطقية الخادم الحالية عند القراءة — لكنه محدود للفترة بين 1970 و2038 (الانفجار في تواريخ النظام). في الممارسة: استخدم DATETIME أعمدة وتأكد أن تطبيقك يكتب القيم المعيارية (UTC) بشكل صريح.

التخطيط عبر مناطق الأوقات: الفخ المُخفي

تخيل أن مستخدمًا يجد جلسة أسبوعية كل يوم الاثنين في "9 صباحًا في وقت نيويورك". تُخزن المدة التالية كتوقيت معياري (UTC). هذا جيد — حتى أن التغيير في وقت الصيف، والآن يمثل التوقيت المعياري (UTC) 10 صباحًا في نيويورك بدلًا من 9 صباحًا.

الحل: لا تُخزن تواريخ مستقبلية مطلقة للمناسبات المتكررة. تُخزن القاعدة المنطقة المحلية — اسم المنطقة الزمنية + الوقت المحلي — واحسب التوقيت المعياري (UTC) للوقت التالي عند التشغيل. بهذه الطريقة، يُعيد النظام الحساب بشكل صحيح بعد التحولات في وقت الصيف.

-- Store the intent, not the absolute moment
CREATE TABLE recurring_events (
  id SERIAL PRIMARY KEY,
  timezone TEXT NOT NULL,       -- 'America/New_York'
  local_time TIME NOT NULL,     -- '09:00:00'
  recurrence TEXT NOT NULL      -- 'WEEKLY:MONDAY'
);
-- Compute next_occurrence_utc in application code at dispatch time

أسماء مناطق الأوقات من IANA مقابل الانحرافات المعيارية (UTC)

عند تخزين تفضيلات المنطقة الزمنية للمستخدم، تخزن اسم IANA (America/New_York, Europe/London, Asia/Kolkata) — وليس الانحراف المعياري (UTC-5, UTC+1). الانحرافات هي صور مُحددة؛ أما أسماء IANA فهي تُحتوي على تاريخ التغيير الكامل والقواعد المستقبلية.

America/New_York يكون UTC-5 في الشتاء و UTC-4 في الصيف. إذا تخزن UTC-5، فأنت تُدخل الانحراف الخاطئ نصف السنة.

مراجع سريعة: القواعد

  • تُخزن التواريخ المعيارية (UTC) — دائمًا، دون استثناءات في قواعد البيانات أو ردود API.
  • استخدم أسماء مناطق الأوقات من IANA — وليس الانحراف المعياري (UTC) — للاختيارات الخاصة بالمستخدم والجدول المتكرر.
  • لا تحلل أسماء التواريخ دون وجود مناطق زمنية محددة — السلوك المُفترض يعتمد على البيئة.
  • أعد التحويل إلى الوقت المحلي في طبقة العرض — وليس في منطق التطبيق أو استعلامات قاعدة البيانات.
  • لأجل الجداول المتكررة، تُخزن القاعدة — وليس التوقيت المعياري المُحسب مسبقًا — لتفادي تلف المواقف المستقبلية عند التحولات في وقت الصيف.
  • أعد اختبار الحالات الحدية — الساعات عند التحول في وقت الصيف، الأوقات القريبة من خط التاريخ الدولي، والتواريخ التاريخية في المناطق التي تغيرت فيها الانحراف.
هل تريد حذف الإعلانات؟ تخلص من الإعلانات اليوم

تثبيت ملحقاتنا

أضف أدوات IO إلى متصفحك المفضل للوصول الفوري والبحث بشكل أسرع

أضف لـ إضافة كروم أضف لـ امتداد الحافة أضف لـ إضافة فايرفوكس أضف لـ ملحق الأوبرا

وصلت لوحة النتائج!

لوحة النتائج هي طريقة ممتعة لتتبع ألعابك، يتم تخزين جميع البيانات في متصفحك. المزيد من الميزات قريبا!

إعلان · حذف؟
إعلان · حذف؟
إعلان · حذف؟

ركن الأخبار مع أبرز التقنيات

شارك

ساعدنا على الاستمرار في تقديم أدوات مجانية قيمة

اشتري لي قهوة
إعلان · حذف؟