Java التاريخ والوقت
⚡ ملخص ذكي
Java يجمع التعامل مع التاريخ والوقت بين فئتي java.util.Date و SimpleDateFormat القديمتين وواجهة برمجة تطبيقات java.time الحديثة التي تم تقديمها في Java 8، مما يمنح المطورين أنواعًا غير قابلة للتغيير وآمنة للاستخدام في بيئة متعددة الخيوط من أجل عمل دقيق في التقويم.

تحديد التواريخ والأوقات في Java يُعدّ جزءًا روتينيًا من بناء منطق الجدولة، وتسجيل الطوابع الزمنية، والتقارير، وسجلات التدقيق. قبل كتابة أي كود، من المفيد معرفة المعايير التي تُشكّل التاريخ:
- استخدم عام (برقمين أو أربعة أرقام).
- استخدم شهر (كرقمين، أو كأول ثلاثة أحرف من الشهر، أو كاسم الشهر الكامل).
- استخدم تاريخ (رقم اليوم الفعلي من الشهر).
- استخدم يوم (اسم اليوم في التاريخ المحدد، مثل الأحد، الاثنين، الثلاثاء).
Java يكشف عن العديد من المعايير الأخرى التي تصف لحظة ما على الخط الزمني، بما في ذلك الحقبة الزمنية، والأسبوع في السنة، والمنطقة الزمنية، والفرق الزمني. وتغطي الأقسام التالية كلًا منها بأمثلة قابلة للتنفيذ.
عرض التاريخ في Java
Java ويوفر Date الطبقة في java.util تحتوي هذه الحزمة على فئة تخزن لحظة زمنية محددة بدقة تصل إلى أجزاء من الثانية، وتوفر دوال مساعدة لطباعة تلك اللحظة ومقارنتها وتنسيقها. للحصول على التاريخ والوقت الحاليين، قم بإنشاء نسخة من الفئة باستخدام مُنشئها الافتراضي.
import java.util.Date; class Date_Ex1 { public static void main(String args[]) { // Instantiate a Date object by invoking its constructor Date objDate = new Date(); // Display the Date and Time using toString() System.out.println(objDate.toString()); } }
الإخراج:
Wed Nov 29 06:36:22 UTC 2017
يعرض المثال التاريخ بتنسيق toString الافتراضي. لعرض نفس اللحظة بنمط مختلف، عليك أولاً فهم أحرف التنسيق التي Java يستخدم.
SimpleDateFormat: تحليل التواريخ وتنسيقها
استخدم SimpleDateFormat الطبقة في java.text يحول أ Date تحويل الكائن إلى سلسلة منسقة، ثم تحليل السلسلة المنسقة مرة أخرى إلى Dateيستخدم هذا النظام حروفًا نمطية تُشير إلى عنصر التاريخ أو الوقت. يسرد الجدول أدناه جميع الحروف المدعومة:
| OMG | مكون التاريخ أو الوقت | مثال |
|---|---|---|
| G | مُحدّد العصر | AD |
| y | السنة | 2026 |
| M | الشهر في السنة | يوليو أو يوليو أو 07 |
| w | أسبوع في السنة | 27 |
| W | أسبوع في الشهر | 2 |
| D | اليوم في السنة | 189 |
| d | اليوم في الشهر | 10 |
| F | يوم من الأسبوع في الشهر | 2 |
| E | اسم اليوم في الأسبوع | الثلاثاء أو الثلاثاء |
| u | عدد أيام الأسبوع (1 = Monday7 = الأحد) | 1 |
| a | علامة صباحية أو مسائية | PM |
| H | ساعة في اليوم (0-23) | 0 |
| k | ساعة في اليوم (1-24) | 24 |
| K | الساعة صباحًا أو مساءً (0-11) | 0 |
| h | الساعة صباحًا أو مساءً (1-12) | 12 |
| m | دقيقة بالساعة | 30 |
| s | الثانية في دقيقة | 55 |
| S | ميلي ثانية واحدة | 978 |
| z | المنطقة الزمنية (الاسم) | الوقت الباسيفيكي القياسي؛ PST؛ GMT-08: 00 |
| Z | المنطقة الزمنية (فرق التوقيت RFC 822) | -0800 |
| X | المنطقة الزمنية (فرق التوقيت وفقًا لمعيار ISO 8601) | -08 أو -0800 أو -08:00 |
لستَ بحاجةٍ إلى حفظ الجدول بأكمله. ارجع إليه كلما أنشأتَ نمطًا جديدًا.
كيفية استخدام تنسيق التاريخ البسيط
SimpleDateFormat هي فئة فرعية من DateFormat يتيح لك ذلك تنسيق وتحليل التواريخ باستخدام الأحرف النمطية المذكورة أعلاه. اجمع الأحرف لوصف السلسلة النصية التي تريد إنتاجها أو قراءتها بدقة.
فمثلا:
- تنسيق التاريخ المطلوب: 2012.10.23 20:20:45 بتوقيت المحيط الهادئنمط التنسيق المناسب هو
yyyy.MM.dd HH:mm:ss zzz. - تنسيق التاريخ المطلوب: 09:30:00 AM 23-May-2012نمط التنسيق المناسب هو
hh:mm:ss a dd-MMM-yyyy.
تلميح: انظر إلى حالة الأحرف. أحرف كبيرة M الشهر، بأحرف صغيرة m دقيقة. أحرف كبيرة H هو نظام الساعة ذو 24 ساعة، بأحرف صغيرة h هو نظام توقيت 12 ساعة. خلطهما ينتج عنه مخرجات خاطئة صامتة.
يقوم البرنامج أدناه بطباعة التاريخ الحالي مرتين، مرة بالتنسيق الافتراضي ومرة أخرى من خلال نمط SimpleDateFormat:
import java.text.SimpleDateFormat; import java.util.Date; class TestDates_Format { public static void main(String args[]) { // Current system date and time is assigned to objDate Date objDate = new Date(); System.out.println(objDate); // Build the target pattern and format the date String strDateFormat = "hh:mm:ss a dd-MMM-yyyy"; SimpleDateFormat objSDF = new SimpleDateFormat(strDateFormat); System.out.println(objSDF.format(objDate)); } }
الإخراج:
Wed Nov 29 06:31:41 UTC 2017 06:31:41 AM 29-Nov-2017
مقارنة التواريخ مثال
الطريقة الأكثر موثوقية لطلب اثنين Date الأشياء هي compareTo() تُعيد هذه الدالة عددًا صحيحًا سالبًا عندما يكون التاريخ المُستدعي أسبق، وصفرًا عندما يكون التاريخان متساويين، وعددًا صحيحًا موجبًا عندما يكون التاريخ المُستدعي أحدث. يُحلل المقتطف البرمجي أدناه سلسلتي تاريخ ويطبع ترتيبهما النسبي:
import java.text.SimpleDateFormat; import java.text.ParseException; import java.util.Date; class TestDates_Compare { public static void main(String args[]) throws ParseException { SimpleDateFormat objSDF = new SimpleDateFormat("dd-MM-yyyy"); Date dt_1 = objSDF.parse("20-08-1981"); Date dt_2 = objSDF.parse("12-10-2012"); System.out.println("Date1 : " + objSDF.format(dt_1)); System.out.println("Date2 : " + objSDF.format(dt_2)); // compareTo returns > 0 when dt_1 is after dt_2 if (dt_1.compareTo(dt_2) > 0) { System.out.println("Date 1 occurs after Date 2"); } // compareTo returns < 0 when dt_1 is before dt_2 else if (dt_1.compareTo(dt_2) < 0) { System.out.println("Date 1 occurs before Date 2"); } // compareTo returns 0 when both dates are equal else { System.out.println("Both are the same date"); } } }
الإخراج:
Date1 : 20-08-1981 Date2 : 12-10-2012 Date 1 occurs before Date 2
ملاحظة: استخدم الكود الأصلي النمط dd-mm-yyyy. صغيرة mm الحرف يشير إلى الدقيقة وليس الشهر، لذا قام المحلل اللغوي بإنتاج قيمة الشهر الخاطئة دون أن يلاحظ المستخدم. الحل المذكور أعلاه يستخدم الأحرف الكبيرة. MM بالنسبة للشهر، وهو الحرف الصحيح في النمط.
Java 8. واجهة برمجة تطبيقات التاريخ والوقت الحديثة (java.time)
Java 8 تم تقديمها java.time حزمة برمجية، واجهة برمجة تطبيقات مُعاد تصميمها مستوحاة من مكتبة Joda-Time. الفئات الجديدة غير قابلة للتغيير، وآمنة للاستخدام في بيئات متعددة الخيوط، وتفصل التقويم البشري عن الجدول الزمني الآلي. أكثر الأنواع شيوعًا هي:
LocalDateلتاريخ بدون وقت أو منطقة زمنية (على سبيل المثال، عيد ميلاد).LocalTimeلعرض الوقت على ساعة حائط بدون تاريخ أو منطقة زمنية.LocalDateTimeلتاريخ ووقت بدون تحديد منطقة زمنية.ZonedDateTimeلتاريخ ووقت محددين ضمن منطقة زمنية معينة.OffsetDateTimeلتاريخ ووقت مع فرق التوقيت عن التوقيت العالمي المنسق ولكن بدون منطقة محددة.Instantبالنسبة للطابع الزمني للجهاز الذي تم قياسه من حقبة يونكس.DurationوPeriodبالنسبة للمبالغ المستندة إلى الوقت والتاريخ.
يعرض المثال أدناه التاريخ والوقت والطابع الزمني والمنطقة الزمنية الحالية باستخدام واجهة برمجة التطبيقات الحديثة:
import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.time.Instant; import java.time.ZoneId; class ModernDateDemo { public static void main(String args[]) { LocalDate today = LocalDate.now(); LocalDateTime now = LocalDateTime.now(); ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Asia/Kolkata")); Instant epoch = Instant.now(); System.out.println("LocalDate : " + today); System.out.println("LocalDateTime : " + now); System.out.println("ZonedDateTime : " + zoned); System.out.println("Instant : " + epoch); } }
لكل نوع طرق تصنيع (now, of, parse) والعمليات غير القابلة للتغيير (plusDays, minusHours, withYear) التي تُعيد قيمة جديدة بدلاً من تغيير الكائن الأصلي.
مُنسِّق التاريخ والوقت: تنسيق التواريخ في الوضع الحديث Java
DateTimeFormatter in java.time.format يستبدل SimpleDateFormatيستخدم نفس نمط الأحرف النمطية، وهو غير قابل للتغيير، ويمكن مشاركته بأمان بين الخيوط دون الحاجة إلى مزامنة إضافية. كما يوفر هذا الصنف ثوابت جاهزة مثل ISO_LOCAL_DATE و ISO_ZONED_DATE_TIME للتنسيقات القياسية.
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; class FormatterDemo { public static void main(String args[]) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter iso = DateTimeFormatter.ISO_LOCAL_DATE_TIME; DateTimeFormatter human = DateTimeFormatter.ofPattern("hh:mm:ss a dd-MMM-yyyy"); System.out.println(now.format(iso)); System.out.println(now.format(human)); LocalDateTime parsed = LocalDateTime.parse("2026-07-04T09:30:00", iso); System.out.println("Parsed back : " + parsed); } }
لمقارنة تاريخين في واجهة برمجة التطبيقات الحديثة، اتصل بـ isBefore, isAfter أو isEqualتُقرأ هذه الأساليب بشكل أوضح من compareTo والعمل مع الجميع java.time فئة.
سلامة الخيط وأفضل الممارسات لـ Java التاريخ والوقت
يبلغ قطر كلاً من java.util.Date و SimpleDateFormat تسبق الحداثة المعاصرة Javaولكل منها عيوبها المعروفة. اتبع الممارسات التالية للحفاظ على معالجة التاريخ بشكل صحيح في كود الإنتاج:
- يُفضّل استخدام java.time بدلاً من Date و Calendar. الأنواع الجديدة غير قابلة للتغيير وآمنة للاستخدام في بيئات متعددة الخيوط، وهي تمثل المجال بدقة أكبر (التواريخ بدون أوقات، والأوقات بدون مناطق زمنية، وما إلى ذلك).
- لا تشارك تنسيق التاريخ البسيط بين سلاسل المحادثات. يخزن هذا الصنف حالة التحليل الداخلية وهو غير آمن للاستخدام في بيئات متعددة الخيوط. قم بتغليفه في
ThreadLocalقم بالمزامنة على المثيل، أو التبديل إلىDateTimeFormatter. - حدد اللغة دائمًا. تتغير أسماء الأشهر والأيام بتغير اللغة الافتراضية لـ JVM، مما يجعل أنماطًا مثل
MMMوEEEغير قابل للنقل. مرر اللغة بشكل صريح (على سبيل المثال،Locale.ENGLISH). - كن واضحاً بشأن المناطق الزمنية.
LocalDateTimeلا يوجد بها منطقة، لذا قم بالتحويل إلىZonedDateTimeorInstantعندما تكون اللحظة الدقيقة مهمة، خاصة بالنسبة للسجلات وأعمدة قواعد البيانات وحمولات الشبكة. - قم بالتحويل بين واجهتي برمجة التطبيقات بعناية. استعمل
date.toInstant(),Date.from(instant)وcalendar.toInstant().atZone(zone)على الحدود بين الكود القديم والكود الحديث. - قم بتخزين الطوابع الزمنية بتوقيت UTC. استمر و transmit التواريخ بتوقيت UTC (و
Instantأو سلسلة ISO 8601) وتحويلها إلى منطقة المستخدم فقط عند العرض.


