التعامل المتقدم مع التواريخ والأوقات في Java: من الأساسيات إلى الاحترافية
\n\nالتعامل مع التواريخ والأوقات هو أحد المهام الأساسية لأي تطبيق مؤسسي. في Java، كان المعيار لفترة طويلة هو java.util.Date و java.util.Calendar الضخمان، لكن مع إصدار Java 8 تغير الوضع جذريًا. حيث قدم java.time API (JSR-310) للمطورين أدوات قوية وآمنة للخيوط وبديهية. في هذه المقالة، سنستعرض التقنيات المتقدمة للتعامل مع التواريخ والأوقات التي ستفيد كل مطور Java.
1. أساسيات java.time API: LocalDate، LocalTime، LocalDateTime
\n\nالخطوة الأولى نحو العمل الاحترافي هي فهم الفئات الأساسية الثلاث التي حلت محل النظائر القديمة:
\n\n- \n
- LocalDate — تاريخ بدون وقت (سنة، شهر، يوم). \n
- LocalTime — وقت بدون تاريخ (ساعات، دقائق، ثوانٍ، نانوثانية). \n
- LocalDateTime — دمج التاريخ والوقت دون ربط بمنطقة زمنية. \n
// الحصول على التاريخ والوقت الحاليين\nLocalDate today = LocalDate.now(); // 2025-03-21\nLocalTime now = LocalTime.now(); // 14:30:15.123\nLocalDateTime current = LocalDateTime.now(); // 2025-03-21T14:30:15.123\n\n// إنشاء تاريخ محدد\nLocalDate birthDate = LocalDate.of(1990, Month.JUNE, 15);\nLocalTime meetingTime = LocalTime.of(10, 30, 0);\n\n// التلاعب بالتواريخ\nLocalDate nextWeek = today.plusWeeks(1);\nLocalDate lastMonth = today.minusMonths(1);\n\nهذه الفئات هي غير قابلة للتغيير — أي عملية تُرجع كائنًا جديدًا. وهذا يضمن أمان الخيوط وقابلية توقع الكود.
\n\n2. التعامل مع المناطق الزمنية: ZonedDateTime و ZoneId
\n\nلا يمكن للتطبيقات العالمية تجاهل المناطق الزمنية. لهذا، توفر java.time الفئة ZonedDateTime.
// الوقت الحالي بالتوقيت العالمي (UTC)\nZonedDateTime utcNow = ZonedDateTime.now(ZoneOffset.UTC);\n\n// الوقت في منطقة زمنية محددة\nZoneId moscowZone = ZoneId.of("Europe/Moscow");\nZonedDateTime moscowTime = ZonedDateTime.now(moscowZone);\n\n// التحويل بين المناطق\nZonedDateTime nyTime = moscowTime.withZoneSameInstant(ZoneId.of("America/New_York"));\n\n// الحصول على الإزاحة\nZoneOffset offset = moscowTime.getOffset(); // +03:00\n\nنصيحة محترف: قم دائمًا بتخزين التواريخ بالتوقيت العالمي (UTC) على الخادم، وقم بتحويلها إلى المنطقة الزمنية المحلية فقط على مستوى العرض (UI). هذا سيوفر عليك مشاكل التوقيت الصيفي/الشتوي.
\n\n3. تحليل وتنسيق التواريخ: DateTimeFormatter
\n\nمن أكثر المهام شيوعًا تحويل سلسلة نصية إلى تاريخ والعكس. يوفر DateTimeFormatter إمكانيات مرنة.
التنسيق الأساسي
\n\nDateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");\nLocalDateTime dateTime = LocalDateTime.parse("21.03.2025 14:30:00", formatter);\nString formatted = dateTime.format(formatter); // "21.03.2025 14:30:00"\n\nالأنماط المتقدمة
\n\n// ISO-8601\nDateTimeFormatter isoFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;\nString isoDate = dateTime.format(isoFormatter); // "2025-03-21T14:30:00"\n\n// التنسيق المترجم\nDateTimeFormatter italianFormatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.ITALY);\nString italianDate = dateTime.format(italianFormatter); // "21 marzo 2025"\n\n// تنسيق مخصص مع حقول نصية\nDateTimeFormatter customFormatter = new DateTimeFormatterBuilder()\n .appendValue(ChronoField.YEAR)\n .appendLiteral(" سنة، ")\n .appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL)\n .appendLiteral(" ")\n .appendValue(ChronoField.DAY_OF_MONTH)\n .toFormatter();\nString custom = dateTime.format(customFormatter); // "2025 سنة، مارس 21"\n\nمن المهم تذكر: DateTimeFormatter أيضًا غير قابل للتغيير وآمن للخيوط.