الوقت بالميلي ثانية في Rust: 5 أخطاء قاتلة وكيفية تجنبها

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

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

ابدأ الدورة

الوقت بالميلي ثانية في Rust: لا تقع في هذه المزالق الخمسة

\n\n

«كيف يمكنني الحصول على الوقت الحالي بالميلي ثانية؟» — هذا السؤال من Stack Overflow حصد آلاف المشاهدات. يبدو الأمر بسيطًا، أليس كذلك؟ لكن Rust ليس Python ولا JavaScript. من السهل هنا الخلط بين UNIX timestamp والوقت الرتيب، أو نسيان الاعتماد على المنصة، أو الوقوع في مشاكل الأداء.

\n\n

في هذه المقالة، سنستعرض أهم الأخطاء التي يرتكبها المبتدئون (وليس فقط المبتدئون) عند العمل مع الوقت في Rust. ستتعلم كيفية الحصول على الوقت بالميلي ثانية بشكل صحيح وموثوق وسريع. هيا بنا!

\n\n

الخطأ رقم 1: الوقت الرتيب بدلاً من وقت UNIX

\n\n

المأزق الأكثر شيوعًا هو استخدام std::time::Instant للحصول على «الوقت الحالي». Instant في Rust يقيس الوقت الرتيب — وهو مثالي لقياس الفترات الزمنية، لكنه عديم الفائدة تمامًا إذا كنت بحاجة إلى timestamp (على سبيل المثال، للتسجيل أو الإرسال إلى الخادم).

\n\n
// ❌ خطأ: بهذه الطريقة لا يمكن الحصول على timestamp\nuse std::time::Instant;\n\nlet now = Instant::now();\n// ليس لدى Instant طريقة duration_since(UNIX_EPOCH)!\n// ستحصل على خطأ في الترجمة\n
\n\n

ما هو الحل الصحيح؟ استخدم std::time::SystemTime. هذا النوع يعرف الوقت النظامي ويمكنه العد من UNIX_EPOCH (1 يناير 1970).

\n\n
use std::time::{SystemTime, UNIX_EPOCH};\n\nlet now = SystemTime::now()\n    .duration_since(UNIX_EPOCH)\n    .expect("الzeit عاد إلى الوراء؟");\n    \nlet millis = now.as_millis(); // u128\nprintln!("الوقت الحالي بالميلي ثانية: {}", millis);\n
\n\n

💡 نصيحة: duration_since يُرجع Result، لأنه نظريًا يمكن ضبط وقت النظام قبل عام 1970. في الأنظمة الحديثة، يمكن معالجة هذا الاستثناء بأمان باستخدام expect أو unwrap.

\n\n

الخطأ رقم 2: نسيان الاعتماد على المنصة

\n\n

قد يبدو أن SystemTime::now() هو حل متعدد المنصات. لكن هناك فارق بسيط. في بعض المنصات (مثل نوى Linux القديمة أو الأنظمة المدمجة)، قد يتصرف SystemTime بشكل غير مستقر أو قد لا يدعم الدقة حتى الميلي ثانية.

\n\n

الحجر الخفي الثاني هو التجاوز. من غير المحتمل أن يتجاوز النوع u128 في as_millis() (يكفي لمليارات السنين)، ولكن إذا كنت بحاجة إلى حفظ الوقت في قاعدة بيانات أو إرساله عبر الشبكة — فقد تكون الميلي ثانية في u128 مفاجأة للأنظمة الأخرى.

\n\n
// ✅ تحويل آمن إلى u64 (يكفي حتى ~584 مليون سنة)\nlet millis_u64: u64 = now.as_millis() as u64;\n
\n\n

كيف تتجنب ذلك؟ تحقق دائمًا من التوثيق الخاص بالمنصة المستهدفة. بالنسبة للأنظمة المدمجة، فكر في استخدام crate embassy-time أو std::time بحذر.

\n\n

الخطأ رقم 3: تجاهل crate chrono

\n\n

المكتبة القياسية لـ Rust توفر إمكانيات أساسية. لكن إذا كنت بحاجة إلى العمل مع المناطق الزمنية، التنسيق، أو تحليل التواريخ — لا تخترع العجلة. crate chrono هو المعيار الفعلي للعمل مع التاريخ والوقت في Rust.

\n\n
// أضف إلى Cargo.toml: chrono = "0.4"\nuse chrono::Utc;\n\nlet now = Utc::now();\nlet millis = now.timestamp_millis(); // i64\nprintln!("Chrono timestamp: {}", millis);\n
\n\n

⚠️ هام: timestamp_millis() يُرجع i64، وليس u128. هذا تم للتوافق مع وقت UNIX (يمكن أن يكون سالبًا للتواريخ قبل عام 1970). في معظم الحالات، i64 هو ما تحتاجه.

\n\n

💡 نصيحة: استخدم chrono للتعامل مع التواريخ المعقدة والمناطق الزمنية.

المدونات

توصيات الكتب