المناطق الزمنية في C++: كيف تتوقف عن الخلط بين المناطق الزمنية

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا الوقت هو مشكلة (وكيف يمكن لـ C++ المساعدة)

\n

تخيل: خادمك يعالج طلبات من نيويورك ولندن وطوكيو. أنت تسجل وقت إنشاء الطلب بصيغة UTC، ثم تعرض للمستخدم: "تم إنشاء طلبك في 03:15". بالنسبة لساكن نيويورك، هذا يعني 22:15 من اليوم السابق، وبالنسبة لساكن لندن 04:15 صباحًا، بينما ساكن طوكيو سيستيقظ من الإشعار في منتصف الليل. مشكلة كلاسيكية تحول سجلًا بسيطًا إلى لغز.

\n

في C++، لم تكن هناك طريقة قياسية جيدة للعمل مع المناطق الزمنية لفترة طويلة. كان المطورون إما يعانون مع time_t و struct tm، أو يستخدمون مكتبات ثقيلة مثل Boost.DateTime. لكن مع قدوم C++20، تغير الوضع جذريًا. أصبحت مكتبة std::chrono تحتوي على دعم كامل للمناطق الزمنية. وعلى الرغم من أن العديد من المترجمات لا تزال تلحق بالمعيار، سنشرح كيف يمكنك اليوم كتابة كود نظيف وقابل للنقل للعمل مع المناطق الزمنية في C++.

\n

في هذه المقالة، سأريكم كيف تحولون الفوضى الناتجة عن المناطق الزمنية في C++ إلى نظام منظم. ستتعلمون العمل مع std::chrono::tzdb، وتحويل UTC إلى الوقت المحلي، ومراعاة التوقيت الصيفي، وتجنب الأخطاء الشائعة.

\n\n

الأساسيات: ما هي المنطقة الزمنية في C++ من وجهة نظر chrono

\n

في C++20، المنطقة الزمنية ليست مجرد إزاحة بالساعات بالنسبة لـ UTC. إنها كائن كامل يعرف تاريخ تغييرات الوقت في المنطقة: متى تم تقديم الساعات، ومتى تم إلغاء التوقيت الصيفي، وما هي القواعد المطبقة. يتم تخزين كل هذه المعلومات في قاعدة بيانات المناطق الزمنية (tzdb) المضمنة في المكتبة القياسية.

\n\n

الأنواع الرئيسية للعمل مع المناطق الزمنية

\n

لتجنب الارتباك، تذكر ثلاثة أنواع رئيسية:

\n
    \n
  • std::chrono::time_zone — يمثل منطقة زمنية محددة (مثل "America/New_York").
  • \n
  • std::chrono::zoned_time — اقتران "منطقة زمنية + لحظة زمنية". هذا هو النوع الأكثر ملاءمة لتخزين وعرض الوقت مع مراعاة المنطقة.
  • \n
  • std::chrono::time_zone_link — أسماء بديلة للمناطق (مثل "US/Eastern" قد يكون رابطًا لـ "America/New_York").
  • \n
\n\n

الحصول على قائمة بجميع المناطق الزمنية

\n

لنبدأ بشيء بسيط: عرض جميع المناطق الزمنية المتاحة. هذا مفيد عندما تتيح للمستخدم اختيار منطقته الزمنية.

\n\n
#include <iostream>\n#include <chrono>\n#include <string>\n\nint main() {\n    // الوصول إلى قاعدة بيانات المناطق الزمنية\n    const auto& tzdb = std::chrono::get_tzdb();\n    \n    // عرض أسماء جميع المناطق\n    std::cout << "المناطق الزمنية المتاحة (" << tzdb.zones.size() << "):\\n";\n    for (const auto& zone : tzdb.zones) {\n        std::cout << zone.name() << '\\n';\n    }\n    return 0;\n}
\n\n

لاحظ: get_tzdb() تُرجع مرجعًا ثابتًا. يتم تحميل قاعدة البيانات مرة واحدة عند أول استدعاء ويتم تخزينها مؤقتًا. هذا يعني أنه يمكنك استدعاء هذه الدالة بأمان في أجزاء مختلفة من البرنامج — سيكون الحمل الإضافي فقط عند أول استدعاء.

\n\n

تحويل الوقت بين المناطق الزمنية في C++

\n

الآن ننتقل إلى الأهم — التحويل. لنفترض أن لديك وقتًا بصيغة UTC، وتريد عرضه للمستخدم بمنطقته المحلية. أو العكس: المستخدم يدخل تاريخًا بوقته المحلي، وتحتاج إلى حفظه بصيغة UTC.

\n\n

من UTC إلى الوقت المحلي

\n

السيناريو: تلقى الخادم وقت حدث بصيغة UTC (مثل 2024-12-01 15:30:00 UTC). يجب عرضه لمنطقة "Europe/Moscow".

\n\n
#include <iostream>\n#include <chrono>\n#include <format> // C++20 للتنسيق\n\nint main() {\n    using namespace std::chrono;\n    \n    // 1. إنشاء لحظة زمنية بصيغة UTC\n    // 2024-12-01 15:30:00 UTC\n    auto tp = sys_days{December / 1 / 2024} + 15h + 30min;\n                

المدونات

توصيات الكتب