مقدمة: لماذا الوقت هو صداع حقيقي
\n\nفي أي مشروع جاد بلغة Rust، سواء كان خادم ويب باستخدام Actix، أو محلل سجلات، أو نظام مراقبة، عاجلاً أم آجلاً يطرح السؤال: كيف نعمل بشكل صحيح مع المناطق الزمنية في Rust. قد يبدو الأمر بسيطاً؟ خذ timestamp، اعرضه على الشاشة - وانتهى الأمر. لكن الواقع قاسٍ: منطقة زمنية واحدة منسية تحول السجلات إلى فوضى، وتبدأ قاعدة البيانات في الكذب.
\n\nفي هذه المقالة، سنستعرض كيف يحل نظام Rust البيئي مشكلة الوقت. ستتعرف لماذا أصبح chrono المعيار الفعلي، وكيف لا تفقد صوابك مع UTC و Local، وكيف تتعامل مع المناطق الزمنية الغريبة مثل "Asia/Yekaterinburg" دون ألم. هيا بنا!
لماذا المكتبة القياسية لـ Rust غير كافية؟
\n\nفي std::time يوجد SystemTime و Instant و Duration. هذا يكفي لقياسات الأداء والمؤقتات البسيطة. ولكن عندما يتعلق الأمر بـ العمل مع المناطق الزمنية في Rust، تفشل المكتبة القياسية: لا يوجد فيها تحليل لسلاسل مثل "2024-03-15T10:30:00+05:00"، ولا معلومات عن المناطق الزمنية، ولا تحويل من UTC إلى الوقت المحلي.
هنا يأتي دور الكريت chrono. إنه سكين سويسري للتواريخ والأوقات في Rust. لنقم بتثبيته في Cargo.toml:
[dependencies]\nchrono = { version = "0.4", features = ["serde"] }\n\nالعلامة serde ضرورية للتسلسل/إلغاء التسلسل - ستكون مفيدة إذا كنت تعمل مع JSON API.
أساسيات chrono: UTC، Local والوقت الساذج
\n\nفي chrono هناك ثلاثة أنواع رئيسية لتمثيل لحظة زمنية:
\n\n- \n
DateTime<Utc>— الوقت بتوقيت UTC. المعيار الذهبي للخوادم. \n DateTime<Local>— الوقت المحلي للنظام. مناسب للسجلات على سطح المكتب. \n NaiveDateTime— وقت "ساذج" بدون منطقة زمنية. خطير، لكنه ضروري أحياناً. \n
لنرى كيفية الحصول على الوقت الحالي في مناطق مختلفة:
\n\nuse chrono::{Utc, Local, DateTime};\n\nfn main() {\n let utc_now: DateTime<Utc> = Utc::now();\n println!("الآن بتوقيت UTC: {}", utc_now);\n\n let local_now: DateTime<Local> = Local::now();\n println!("الآن محلياً: {}", local_now);\n}\n\nشغّل هذا الكود - وسترى الفرق. لاحظ: DateTime هو نوع عام يتم تحديده بالمنطقة الزمنية. هذا يعني أن المترجم لن يسمح لك بإضافة وقت من UTC و Local عن طريق الخطأ دون تحويل صريح. سلامة الأنواع تحرس الوقت!
التحويل بين المناطق الزمنية
\n\nالمهمة الأكثر شيوعاً هي تحويل UTC إلى الوقت المحلي للمستخدم. لنفترض أن خادمك يخزن كل شيء بتوقيت UTC، والعميل موجود في المنطقة الزمنية Asia/Yekaterinburg (UTC+5). كيف تفعل ذلك؟
\n\nاستخدم الدالة with_timezone:
use chrono::{Utc, Local, TimeZone, DateTime};\n\nfn main() {\n let utc_time: DateTime<Utc> = Utc::now();\n \n // تحويل إلى الوقت المحلي للنظام\n let local_time: DateTime<Local> = utc_time.with_timezone(&Local);\n println!("UTC: {} -> Local: {}", utc_time, local_time);\n \n // إذا كنت بحاجة إلى منطقة محددة - استخدم FixedOffset\n let ekb_offset = chrono::FixedOffset::east_opt(5 * 3600).unwrap();\n let ekb_time: DateTime<FixedOffset> = utc_time.with_timezone(&ekb_offset);\n println!("UTC: {} -> EKB: {}", utc_time, ekb_time);\n}\n\nلاحظ: FixedOffset::east_opt يعيد Option، لأن أي إزاحة ليست صالحة (مثلاً، 25 ساعة مبالغ فيها). تعامل دائماً مع None.
ماذا لو كان العمل مع المناطق الزمنية في Rust أكثر تعقيداً من مجرد إزاحة ثابتة؟ على سبيل المثال، هل تحتاج لمراعاة التوقيت الصيفي؟ هنا يأتي الكريت
المدونات
توصيات الكتب
اقرأ أيضًا