العمل المتقدم مع التواريخ والوقت في Swift
العمل مع التواريخ والوقت هو أحد المهام الرئيسية في تطوير iOS/macOS. على المستوى الأساسي، معظم المطورين على دراية بـ Date و DateFormatter و Calendar. ومع ذلك، على المستوى المتقدم، تظهر سيناريوهات معقدة: العمل مع المناطق الزمنية، الأداء العالي عند تحليل مئات التواريخ، العرض الصحيح للوقت النسبي، ومعالجة التنسيقات المخصصة. في هذه المقالة، سنستعرض التقنيات المتقدمة للعمل مع التواريخ في Swift التي ستساعدك على كتابة كود أكثر موثوقية وكفاءة.
1. تحسين تحليل التواريخ: DateFormatter مقابل ISO8601DateFormatter
واحدة من أكثر العمليات شيوعًا هي تحويل سلسلة نصية إلى تاريخ. DateFormatter القياسي مناسب، لكن إنشائه عملية مكلفة. إذا كنت تقوم بتحليل مئات التواريخ في حلقة، فإن كل استدعاء لـ DateFormatter() ينشئ كائنًا جديدًا، مما يؤدي إلى انخفاض الأداء.
المشكلة: إنشاء DateFormatter في حلقة
// ❌ سيء: إنشاء المنسق في حلقةfor dateString in dateStrings { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" if let date = formatter.date(from: dateString) { // معالجة }}الحل: التخزين المؤقت و ISO8601DateFormatter
لتنسيق ISO 8601، استخدم ISO8601DateFormatter - فهو أسرع وأكثر أمانًا للخيوط. للتنسيقات المخصصة، قم بإنشاء المنسق مرة واحدة وأعد استخدامه.
// ✅ جيد: تخزين المنسق مؤقتًاprivate let isoFormatter: ISO8601DateFormatter = { let formatter = ISO8601DateFormatter() formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] return formatter}()
// للتنسيقات المخصصةprivate let customFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "dd.MM.yyyy HH:mm" formatter.locale = Locale(identifier: "ru_RU") formatter.timeZone = TimeZone(secondsFromGMT: 0) return formatter}()
func parseDates(_ strings: [String]) -> [Date] { return strings.compactMap { isoFormatter.date(from: $0) }}هام: DateFormatter ليس آمنًا للخيوط. إذا كنت تعمل مع تعدد الخيوط، استخدم Thread.current أو أنشئ منسقًا منفصلاً لكل خيط.
2. العمل مع المناطق الزمنية و DateComponents
يتطلب العمل المتقدم مع التواريخ مراعاة المناطق الزمنية. Date في Swift هي لحظة زمنية مطلقة (عدد الثواني من 1 يناير 2001). جميع المعلومات حول المنطقة الزمنية موجودة في Calendar و DateFormatter.
استخراج مكونات التاريخ في منطقة زمنية محددة
let date = Date()let calendar = Calendar.currentlet timeZone = TimeZone(identifier: "America/New_York")!
// الحصول على المكونات للمنطقة الزمنية المحددةvar components = calendar.dateComponents(in: timeZone, from: date)components.hour // الساعة في نيويوركcomponents.day // اليوم في نيويورك
// إنشاء تاريخ من المكونات مع تحديد timeZone صراحةvar newComponents = DateComponents()newComponents.year = 2024newComponents.month = 12newComponents.day = 25newComponents.hour = 10newComponents.minute = 30newComponents.timeZone = TimeZone(identifier: "Europe/Moscow")
let christmasDate = calendar.date(from: newComponents)print(christmasDate!) // 2024-12-25 07:30:00 +0000 (UTC)مقارنة التواريخ مع مراعاة التقويم
استخدم compare(_:to:toGranularity:) للمقارنة بدقة تصل إلى اليوم أو الساعة أو الدقيقة:
let date1 = Date()let date2 = Date().addingTimeInterval(3600) // +1 ساعة
let result = calendar.compare(date1, to: date2, toGranularity: .hour)// .orderedSame إذا كانا في نفس الساعة// .orderedAscending إذا كان date1 أقدم<