الوقت شيء نسبي. خاصة في الكود
تخيل: أنت تكتب تطبيقًا لحجز تذاكر الطيران. مستخدم من نيويورك يختار رحلة في الساعة 14:00 بالتوقيت المحلي، والخادم في لندن يحفظ ذلك كـ DateTime.Now. ما الذي سيحدث بشكل خاطئ؟ كل شيء تمامًا. في أفضل الأحوال - تذكرة قبل ثلاث ساعات، في أسوأ الأحوال - سيفوت المستخدم الرحلة ويترك تقييمًا غاضبًا.
العمل مع المناطق الزمنية في C# هو الموضوع الذي يؤجله العديد من المطورين "لوقت لاحق". لكنه بالضبط ما يفصل الكود الهواة عن الكود الاحترافي. اليوم سنفهم كيف نجعل تطبيقك صديقًا للمناطق الزمنية، دون أن نفقد صوابنا بسبب التوقيت الصيفي ودون أن نخسر أي مستخدم.
DateTime مقابل DateTimeOffset: أول معركة مع الواقع
كثير من المبتدئين في C# يستخدمون DateTime لكل شيء. وهذا طبيعي طالما لم تواجه مستخدمين عالميين. المشكلة أن DateTime بحد ذاته لا يعرف في أي منطقة زمنية هو. إنه مجرد "لحظة زمنية" بدون سياق.
// سيء: وقت بدون سياقDateTime localTime = DateTime.Now; // 14:00 - لكن أين؟DateTime utcTime = DateTime.UtcNow; // أفضل، لكنه لا يزال غير مثالي
// جيد: وقت مع إزاحةDateTimeOffset withOffset = DateTimeOffset.Now; // 14:00 +03:00Console.WriteLine(withOffset); // 06.04.2025 14:00:00 +03:00DateTimeOffset هو خطوتك الأولى نحو إدارة واعية للوقت. فهو لا يخزن التاريخ والوقت فحسب، بل يخزن أيضًا الإزاحة بالنسبة لـ UTC. هذا ينقذ الموقف عندما تحتاج إلى نقل البيانات بين الأنظمة أو ببساطة إظهار الوقت المحلي الصحيح للمستخدم.
متى يكون DateTime ضروريًا على أي حال؟
بصراحة؟ تقريبًا أبدًا لتخزين اللحظات الزمنية. إذا كنت تكتب كودًا لتطبيق سطح مكتب محلي - يمكنك ذلك. ولكن بمجرد ظهور قاعدة بيانات أو API أو عدة مستخدمين - انتقل إلى DateTimeOffset أو DateTime مع تحديد صريح لـ DateTimeKind.Utc.
TimeZoneInfo: أطلس المناطق الزمنية الشخصي الخاص بك
في .NET هناك فئة قوية TimeZoneInfo. تتيح لك العمل مع أي مناطق زمنية معروفة لنظام التشغيل. وهناك المئات منها - من UTC+0 القياسي إلى المناطق الغريبة مثل "Lord Howe Island" بإزاحة 30 دقيقة.
// الحصول على قائمة بجميع المناطق المتاحةReadOnlyCollection<TimeZoneInfo> allZones = TimeZoneInfo.GetSystemTimeZones();foreach (var zone in allZones.Take(5)){ Console.WriteLine($"{zone.Id}: {zone.DisplayName}");}// الإخراج (مثال):// UTC: (UTC) Coordinated Universal Time// Russian Standard Time: (UTC+03:00) Moscow, St. Petersburg// Eastern Standard Time: (UTC-05:00) Eastern Time (US & Canada)تحويل الوقت بين المناطق
لنفترض أن مستخدمًا من موسكو يريد معرفة متى سيبدأ الندوة عبر الإنترنت بتوقيت لندن. إليك كيفية القيام بذلك بشكل صحيح:
// الوقت الأصلي - بتوقيت موسكوDateTime moscowTime = new DateTime(2025, 6, 15, 18, 0, 0);TimeZoneInfo moscowZone = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");TimeZoneInfo londonZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
// التحويلDateTime londonTime = TimeZoneInfo.ConvertTime(moscowTime, moscowZone, londonZone);Console.WriteLine($"في موسكو: {moscowTime}, في لندن: {londonTime}");// في موسكو: 15.06.2025 18:00:00, في لندن: 15.06.2025 16:00:00لاحظ: نحن نحدد بوضوح المنطقتين الأصلية والهدف. هذا يزيل الغموض. TimeZoneInfo.ConvertTime سيراعي الفرق في الوقت بنفسه، بما في ذلك التوقيت الصيفي/الشتوي.
التوقيت الصيفي (DST): العدو الرئيسي للمطور
مرتين في السنة يصاب العالم بالجنون. في مارس يتم تقديم الساعات، في أكتوبر - تأخيرها. وإذا كان تطبيقك غير مستعد لـ DST، سيرى المستخدمون إما ساعة "إضافية" أو ساعة مفقودة. C# يتعامل مع هذا تلقائيًا