العمل المتقدم مع التواريخ والأوقات في Rust: chrono و time

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

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

ابدأ الدورة

العمل المتقدم مع التواريخ والأوقات في Rust

\n\n

في التطوير الحديث باستخدام Rust، يتجاوز العمل مع التواريخ والأوقات بكثير مجرد الحصول على اللحظة الحالية. عند إنشاء أنظمة عالية التحميل، أو تطبيقات مالية، أو خدمات موزعة، يلزم حساب دقيق للمناطق الزمنية، وتحليل فعال، وتسلسل، وحسابات زمنية معقدة. في هذه المقالة، سنستعرض التقنيات المتقدمة للعمل مع التواريخ والأوقات باستخدام الكريتات chrono و time.

\n\n

1. مكتبة chrono: أساس العمل المتقدم

\n\n

كريت chrono هو المعيار الفعلي للعمل مع التواريخ والأوقات في Rust. يوفر تجريدين رئيسيين: NaiveDateTime (تاريخ-وقت بدون منطقة زمنية) و DateTime<Tz> (تاريخ-وقت مرتبط بمنطقة زمنية).

\n\n

مثال: العمل مع المناطق الزمنية

\n\n
use chrono::{DateTime, Utc, Local, FixedOffset, NaiveDateTime};\nuse chrono::format::ParseError;\n\nfn main() -> Result<(), ParseError> {\n    // الوقت الحالي في UTC\n    let utc_now: DateTime<Utc> = Utc::now();\n    println!("UTC now: {}", utc_now);\n\n    // الوقت المحلي الحالي\n    let local_now: DateTime<Local> = Local::now();\n    println!("Local now: {}", local_now);\n\n    // التحويل إلى منطقة زمنية أخرى (موسكو، UTC+3)\n    let moscow_offset = FixedOffset::east_opt(3 * 3600).unwrap();\n    let moscow_time = utc_now.with_timezone(&moscow_offset);\n    println!("Moscow time: {}", moscow_time);\n\n    // تحليل سلسلة نصية مع منطقة زمنية\n    let parsed = DateTime::parse_from_rfc3339("2024-03-15T14:30:00+05:00")?;\n    println!("Parsed with offset: {}", parsed);\n\n    Ok(())\n}
\n\n

هام: استخدم Utc للتخزين في قواعد البيانات و API، وقم بالتحويل إلى المناطق المحلية فقط على مستوى العرض.

\n\n

2. الحسابات الزمنية المعقدة والفواصل الزمنية

\n\n

تدعم مكتبة chrono العمليات الحسابية على التواريخ باستخدام النوع Duration والعمليات الأكثر تعقيدًا عبر trait TimeDelta. للعمل مع الفواصل والفترات الزمنية (مثل "الشهر التالي")، استخدم Months و Weeks.

\n\n

مثال: الحسابات مع التواريخ

\n\n
use chrono::{NaiveDate, Duration, Months, Datelike, Weekday};\n\nfn main() {\n    let start = NaiveDate::from_ymd_opt(2024, 1, 15).unwrap();\n\n    // إضافة أيام\n    let plus_10_days = start + Duration::days(10);\n    println!("+10 days: {}", plus_10_days);\n\n    // إضافة أشهر (تراعي اختلاف أطوال الأشهر)\n    let plus_2_months = start.checked_add_months(Months::new(2)).unwrap();\n    println!("+2 months: {}", plus_2_months);\n\n    // البحث عن يوم الاثنين التالي\n    let next_monday = start.iter_days()\n        .skip(1)\n        .find(|d| d.weekday() == Weekday::Mon)\n        .unwrap();\n    println!("Next Monday: {}", next_monday);\n\n    // الفرق بين التواريخ بالأيام\n    let end = NaiveDate::from_ymd_opt(2024, 12, 31).unwrap();\n    let days_diff = end.signed_duration_since(start).num_days();\n    println!("Days between: {}", days_diff);\n}
\n\n

نصيحة: للحسابات المالية، استخدم checked_add_months بدلاً من مجرد جمع الأيام، لمعالجة نهايات الأشهر بشكل صحيح (مثل 31 يناير + شهر واحد = 28/29 فبراير).

\n\n

3. التسلسل وتحليل التواريخ باستخدام serde

\n\n

عند العمل مع JSON أو YAML أو قواعد البيانات، يعد التسلسل الصحيح للتواريخ أمرًا بالغ الأهمية. يتكامل كريت chrono مع serde عبر الميزة serde. للتنسيقات المخصصة، استخدم السمات #[serde(with = "...")].

\n\n

مثال: التسلسل بتنسيق ISO 8601 والتنسيقات المخصصة

\n\n
use chrono::{DateTime, Utc, NaiveDateTime};\nuse serde::{Serialize, Deserialize};\n\n#[derive(Debug, Serialize, Deserialize)]                

المدونات

توصيات الكتب