العمل المتقدم مع التواريخ والوقت في C#: من النظرية إلى المهام الواقعية
العمل مع التواريخ والوقت هو أحد أكثر المهام شيوعًا وفي نفس الوقت خادعة في التطوير. في المستوى المبتدئ، نقوم ببساطة بإنشاء DateTime.Now وعرضه في وحدة التحكم. ولكن عندما يتجاوز المشروع الإطارات البسيطة، تظهر التعقيدات: التوقيت الصيفي، المناطق الزمنية المختلفة، الدقة العالية في الحسابات، أو الحاجة إلى العمل مع التواريخ بدون منطقة زمنية. في هذه المقالة، سنستعرض التقنيات المتقدمة للعمل مع التواريخ والوقت في C# (.NET) التي ستساعدك على كتابة كود موثوق وقابل للتنبؤ.
1. DateTime وDateTimeOffset وTimeSpan: اختيار الأداة الصحيحة
يستخدم العديد من المطورين DateTime بشكل افتراضي دون التفكير في قيوده. في المستوى المتقدم، من المهم فهم الفرق بين الأنواع الثلاثة الرئيسية.
DateTime
يخزن التاريخ والوقت. مشكلته الرئيسية هي الغموض. الخاصية Kind (Local, Utc, Unspecified) لا تُحدد دائمًا بشكل صريح، مما يؤدي إلى أخطاء أثناء التسلسل أو المقارنة.
DateTimeOffset
يخزن التاريخ والوقت والإزاحة بالنسبة لـ UTC. هذا هو النوع الموصى به لتخزين لحظات زمنية، لأنه يحدد بشكل لا لبس فيه نقطة على الخط الزمني. على سبيل المثال، 2025-03-15T14:00:00+03:00 هي دائمًا لحظة محددة، بغض النظر عن المنطقة الزمنية للمستخدم.
TimeSpan
يمثل فترة زمنية، وليس لحظة محددة. يُستخدم في العمليات الحسابية: الفرق بين التواريخ، المهلات، مدة العمليات.
// مثال: DateTime مقابل DateTimeOffsetDateTime localNow = DateTime.Now; // Kind = LocalDateTime utcNow = DateTime.UtcNow; // Kind = Utc
DateTimeOffset preciseNow = DateTimeOffset.Now; // دائمًا مع تحديد الإزاحة
// المقارنة: DateTimeOffset أكثر وضوحًاConsole.WriteLine(preciseNow.Offset); // +03:00 أو -05:00 إلخ.نصيحة: للمشاريع الجديدة، استخدم DateTimeOffset لتخزين اللحظات الزمنية، TimeSpan للفترات، و DateTime فقط عند الضرورة القصوى (مثل التوافق مع الكود القديم).
2. التحليل والتنسيق: كيف تتجنب FormatException
تحليل التواريخ من السلاسل النصية هو مصدر للعديد من الأخطاء، خاصة إذا كانت السلاسل تأتي من المستخدمين أو من ثقافات مختلفة.
التحليل المعتمد على الثقافة
استخدم CultureInfo.InvariantCulture لتبادل البيانات الداخلي (مثل JSON، API). للإدخال من المستخدم، ضع في اعتبارك ثقافة المستخدم.
// تحليل مع مراعاة الثقافةstring dateString = "15.03.2025";var ruCulture = new CultureInfo("ru-RU");DateTime parsedDate = DateTime.Parse(dateString, ruCulture);
// تحليل ثابت (موصى به لـ API)string isoString = "2025-03-15T14:00:00Z";DateTimeOffset parsedIso = DateTimeOffset.Parse(isoString, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);TryParseExact للموثوقية
إذا كان تنسيق السلسلة معروفًا، استخدم TryParseExact مع تحديد التنسيق بشكل صريح. هذا يمنع الاستثناءات غير المتوقعة.
string input = "2025-03-15 14:30";string format = "yyyy-MM-dd HH:mm";if (DateTime.TryParseExact(input, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result)){ Console.WriteLine($"تم بنجاح: {result}");}else{ Console.WriteLine("خطأ في التحليل");}التنسيق المخصص
المحددات القياسية (d, D, t, T) جيدة، ولكن للتحكم الدقيق استخدم سلاسل تنسيق مخصصة.
DateTime now = DateTime.Now;Console.WriteLine(now.ToString("yyyy-MM-dd HH:mm:ss.fff")); // 2025-03-15 14:30:45.123Console.WriteLine(now.ToString("dd MMMM yyyy, dddd")); // 15 مارس 2025، السبت