العمل مع التواريخ والوقت في Swift: تقنيات متقدمة

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

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

ابدأ الدورة

العمل المتقدم مع التواريخ والوقت في Swift: من الأساسيات إلى التحسين

\n

العمل مع التواريخ والوقت هو أحد أكثر المهام شيوعًا وصعوبة في تطوير iOS/macOS. البساطة الظاهرية لواجهة API الخاصة بـ Foundation (Date، DateFormatter، Calendar) تؤدي غالبًا إلى أخطاء تتعلق بالمناطق الزمنية، الترجمة أو الأداء. في هذه المقالة، سنستعرض التقنيات المتقدمة للعمل مع التواريخ في Swift: من التحليل الصحيح إلى الحسابات عالية الأداء التي ستكون مفيدة في مشاريع الإنتاج.

\n\n

1. DateFormatter: الضبط الدقيق والتخزين المؤقت

\n

الخطأ الأكثر شيوعًا للمبتدئين هو إنشاء كائن DateFormatter جديد داخل حلقة أو دالة تُستدعى بشكل متكرر. إنشاء DateFormatter هو عملية مكلفة (أبطأ حتى 1000 مرة من إعادة استخدامه).

\n\n
// ❌ سيء: إنشاء formatter في كل مرة\nfunc parseDate(from string: String) -> Date? {\n    let formatter = DateFormatter()\n    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"\n    formatter.locale = Locale(identifier: "ru_RU")\n    formatter.timeZone = TimeZone(secondsFromGMT: 0)\n    return formatter.date(from: string)\n}\n\n// ✅ جيد: تخزين formatter مؤقتًا\nprivate let isoDateFormatter: DateFormatter = {\n    let f = DateFormatter()\n    f.dateFormat = "yyyy-MM-dd HH:mm:ss"\n    f.locale = Locale(identifier: "ru_RU")\n    f.timeZone = TimeZone(secondsFromGMT: 0)\n    return f\n}()\n\nfunc parseDateFast(from string: String) -> Date? {\n    return isoDateFormatter.date(from: string)\n}
\n\n

نصيحة متقدمة: للعمل مع التنسيقات الثابتة (مثل ISO 8601) استخدم ISO8601DateFormatter - فهو أسرع من DateFormatter القياسي. للتنسيقات المخصصة التي تتطلب أداءً عاليًا، فكر في استخدام DateFormatter مع thread-local storage:

\n\n
extension DateFormatter {\n    static let threadLocal: ThreadLocal<DateFormatter> = ThreadLocal {\n        let f = DateFormatter()\n        f.dateFormat = "dd.MM.yyyy"\n        f.locale = Locale(identifier: "ru_RU")\n        return f\n    }\n}
\n\n

2. Calendar و DateComponents: حسابات بدون أخطاء

\n

للعمليات الحسابية على التواريخ (إضافة يوم، إيجاد بداية الشهر) استخدم Calendar، وليس الجمع اليدوي للثواني. الإضافة اليدوية لـ 86400 ثانية (24*60*60) تتعطل عند الانتقال إلى التوقيت الصيفي.

\n\n
let calendar = Calendar.current\nlet now = Date()\n\n// ✅ إضافة يوم واحد بأمان\nif let tomorrow = calendar.date(byAdding: .day, value: 1, to: now) {\n    print("غدًا: \\(tomorrow)")\n}\n\n// ✅ إيجاد بداية الشهر الحالي\nlet startOfMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: now))!\n\n// ✅ الحصول على المكونات مع مراعاة الترجمة\nlet components = calendar.dateComponents([.weekday, .weekOfYear], from: now)\nprint("يوم الأسبوع: \\(components.weekday ?? 0)") // 1 = الأحد في الولايات المتحدة، 2 = الاثنين في روسيا
\n\n

نصيحة متقدمة: للحسابات عالية التحميل (مثل توليد شبكة التقويم) قم بتخزين Calendar و TimeZone مؤقتًا. تجنب استخدام Calendar.current داخل الحلقات - فهو يستدعي إعدادات النظام في كل مرة.

\n\n

3. الترجمة والتنسيق للمستخدم

\n

لا تعرض أبدًا التاريخ الخام للمستخدم. استخدم DateFormatter مع الأنماط المحددة مسبقًا (.short، .medium، .long، .full) و RelativeDateTimeFormatter للتواريخ النسبية القابلة للقراءة ("أمس"، "منذ 3 أيام").

\n\n
// التاريخ المطلق مع مراعاة لغة المستخدم\nlet userFormatter = DateFormatter()\nuserFormatter.dateStyle = .long\nuserFormatter.timeStyle = .short\nprint(userFormatter.string(from: Date())) // "15 يونيو 2025، 14:30" (لـ ar_SA)\n\n// التاريخ النسبي (iOS 13+)\nlet relativeFormatter = RelativeDateTimeFormatter()\nrelat                

المدونات

توصيات الكتب