منذ إصدار Java 8 في عام 2014 ، لم يعد java.util.date القديم هو الخيار الوحيد لتواريخ التشغيل والوقت في Java.
في الواقع ، تم انتقاد واجهات برمجة التطبيقات ذات الصلة من التاريخ والوقت في جافا من قبل العالم. ليس فقط ليس فقط لأن تقسيم التصميم الخاص به غير واضح ، ولكن في كثير من الأحيان يمكنه التعامل مع كل من التواريخ والوقت ، وهو أمر محير للغاية. كما أنه يتم تخزين التعيينات العددية لسنوات معينة وشهور وتواريخ ضد البشر ، مثل: 0 يتوافق مع شهر يناير ، 11 يناير يتوافق مع شهر ديسمبر ، 118 يتوافق مع عام 2018 (1900 + 118) ، إلخ.
في كثير من الأحيان ، عندما نحصل على قيمة سنة وشهر معينة ، نحتاج إلى القيام بعمليات مقابلة للحصول على معلومات دقيقة لمدة عام وشهر وتاريخ. حتى Java 8 ، استعارنا التصميم الممتاز لمكتبة Joda Open المصدر الطرف الثالث ، وأعادنا تصميم API للتاريخ والوقت. بالمقارنة مع السابق ، يمكن القول أنه أسهل مائة مرة في الاستخدام. توجد جميع واجهات API ذات الصلة في الحزمة java.time.
واجهة التاريخ والوقت القديمة
التاريخ الذي يمثل معلومات الوقت
تستخدم جميع أجهزة الكمبيوتر في العالم عددًا صحيحًا من النوع الطويل ، وقيمة هذا عدد صحيح هي عدد المللي ثانية بالنسبة إلى GMT في المملكة المتحدة (0: 0: 00 ، 1 يناير 1970). على سبيل المثال:
الفراغ الثابت العام (سلسلة [] args) {// 1 يناير 1970 00:00:00 بتوقيت جرينتش. تاريخ التاريخ = تاريخ جديد (1000) ؛ system.out.println (التاريخ) ؛}نتيجة الإخراج:
// 1970-1-1 8: 00: 01thu Jan 01 08:00:01 CST 1970
قد يتساءل الكثير من الناس ، 1000 تعني ثانية واحدة قبل الوقت القياسي ، فلماذا يمر الوقت ثماني ساعات أخرى؟
هذا له علاقة بـ "المنطقة الزمنية". إذا كنت موجودًا في Greenwich ، فستكون النتيجة كما هو متوقع ، لكننا موجودون في منطقة شرق الصين الثامنة ، والوقت قبل ثماني ساعات ، وبالتالي فإن القيم الأساسية القائمة على مناطق زمنية مختلفة مختلفة.
لقد لعبت فئة التاريخ بالفعل العديد من الأدوار من قبل. يمكن أن نرى من رمز المصدر الخاص به أن هناك طرقًا يمكنها تشغيل الوقت ، والأساليب التي يمكن أن تعمل العام والشهر واليوم ، وحتى إدارة المناطق الزمنية. يمكن القول أنه يكفي الحصول عليها في التاريخ والوقت المتعلقة بالوقت وحدها.
لكن هذا هو العالم. إذا كنت تهتم كثيرًا ، فلن تتمكن بطبيعة الحال من تغطية كل شيء. تصميم العديد من الطرق في التاريخ ليس معقولًا جدًا. لقد قلنا ذلك أيضًا من قبل ، بل إنه معادٍ للإنسان قليلاً. لذلك ، تم التخلي عن ما يقرب من 80 ٪ من الطرق في فئة التاريخ الحالية وتم تمييزها.
يتمثل تحديد المواقع الحالية لشركة Sun للتاريخ في لحظة فقط ، لذلك يجب أن يدور موقعها الداخلي حول المللي ثانية من هذا الصحيح ، ولم يعد يركز على مختلف المناطق الزمنية السنوية والمعلومات الأخرى.
يتيح التاريخ إنشاء كائن من خلال مُنشئين:
عابر خاص طويل الطويل ؛ التاريخ العام () {this (System.CurrentTimeMillis ()) ؛} التاريخ العام (تاريخ طويل) {fasttime = date ؛}تخزن السمة Fasttime هنا عدد المللي ثانية المقابلة للوقت. لا يزال المُنشئان بسيطان للغاية. إذا تم استدعاء مُنشئ المعلمة ، فسيقوم الجهاز الظاهري بتعيين FastTime مع القيمة الزمنية الحالية للنظام.
هناك بعض الطرق الأخرى التي لم يتم التخلص منها:
هناك طريقتان آخرتان تتم إضافتهما حديثًا إلى JDK1.8 بعد ذلك ، وتستخدم لتحويل واجهات جديدة إلى Java 8 ، والتي سيتم تقديمها لاحقًا.
التقويم الذي يصف الملمس
يتم استخدام التقويم لتمثيل معلومات التاريخ مثل السنة والشهر واليوم وما إلى ذلك. إنه فئة مجردة ، لذلك يتم الحصول على كائن مثيله بشكل عام من خلال أساليب المصنع الأربعة التالية.
التقويم الثابت العام getInstance () التقويم الثابت العام getInstance (منطقة الزمن) التقويم الثابت العام getinstance (alocale alocale) getinstance (منطقة المنطقة الزمنية ، alocale المحلية)
في الواقع ، سيتم في النهاية استدعاء الطريقة الداخلية نفسها:
تقويم ثابت خاص CreateCalendar (منطقة الزمن ، ALOCALE)
تتطلب هذه الطريقة معلمتين ، والآخر هو المنطقة الزمنية والآخر هو البلد واللغة. بمعنى أن إنشاء مثيل تقويمي يتطلب على الأقل هاتين معلومات المعلمة ، وإلا سيتم استخدام المنطقة الزمنية الافتراضية للنظام أو معلومات اللغة.
نظرًا لأن المناطق الزمنية المختلفة واللغات الوطنية تنتج بشكل مختلف للوقت والسنة والشهر واليوم ، فإن هذا أيضًا سبب لابد مثيل التقويم في المعلومات الزمنية والبلد. انظر مثال:
public static void main (string [] args) {calendar calendar = calendar.getInstance () ؛ System.out.println (Calendar.getTime ()) ؛ Calendar Calendar1 = calendar.getInstance (timezone.gettimezone ("gmt") ، locale.english) ؛ System.out.println (Calendar1.get (Calendar.year) + ":" + Calendar1.get (Calendar.hour) + ":" + Calendar1.get (Calendar.Minute)) ؛ }نتيجة الإخراج:
السبت 21 أبريل 10:32:20 CST 20182018: 2: 32
كما ترون ، فإن الناتج الأول هو الوقت الحالي للمنطقة الزمنية الافتراضية لنظامنا والبلد ، والمثال التقويم الثاني الذي حددناه أنه يقع في المنطقة الزمنية Greenwich (المنطقة الزمنية 0) ، والنتيجة واضحة أيضًا ، مع اختلاف ثماني ساعات ، لأننا موجودون في الشرق الثامن ، أي قبل ثماني ساعات من المنطقة الزمنية 0.
قد يتساءل بعض الأشخاص عن سبب تعقيد إخراج مثيل التقويم الثاني مع الصق ، بدلاً من استدعاء طريقة GetTime موجزة مباشرة مثل مثيل التقويم الأول؟
يتضمن ذلك التنفيذ الداخلي للتقويم ، دعنا نلقي نظرة معًا:
وقت طويل محمي ؛ تاريخ النهائي العام getTime () {إرجاع تاريخ جديد (getTimeInMillis ()) ؛}مثل التاريخ ، يحتفظ التقويم بمعلومات زمنية في الداخل ، وتقوم طريقة GetTime بالفعل بإنشاء كائن تاريخ بناءً على هذا الوقت والعودة.
بشكل عام ، عندما نقوم بإنشاء مثيل تقويمي ، لن نمر في معلومات زمنية ، لذلك عندما يتم تهيئة المثيل ، سيحسب البرنامج رقم ميلي ثانية بناءً على المنطقة الزمنية الافتراضية للنظام والوقت الحالي وتعيينه إلى الوقت.
لذلك ، داخل جميع مثيلات التقويم التي لم يتم تعديل قيمة سمة الوقت التي يتم تعديلها يدويًا ، فإن القيمة الزمنية هي القيمة الزمنية للمنطقة الزمنية الافتراضية في ذلك الوقت. بمعنى آخر ، تتجاهل نتيجة الإخراج لـ GetTime معلومات المنطقة الزمنية المقابلة للمثال الحالي. يعد هذا أيضًا عيبًا في تصميم التقويم ، لأن هذا سيؤدي إلى تعتمد قيمة إخراج GetTime للحالتين التقويميتين فقط على وقت تشغيل النظام عند تهيئة المثيل.
يحدد التقويم أيضًا العديد من الثوابت الثابتة وبعض المصفوفات السمة:
عصر int النهائي العام الثابت = 0 ؛ العام الثابت النهائي العام = 1 ؛ الشهر الثابت النهائي العام ؛
يتم تخزين جميع المعلومات ذات الصلة حول التواريخ في صفيف السمات ، وغالبًا ما تمثل قيم هذه الثوابت الثابتة قيمة فهرس. من خلال طريقة GET ، نمر في فهرس السمة وإرجاع قيمة السمة. على سبيل المثال:
التقويم mycalendar = calendar.getInstance () ؛ int year = mycalendar.get (calendar.year) ؛
طريقة GET هنا هي في الواقع لاتخاذ الحقول مباشرة [1] كقيمة الإرجاع. يتم حساب صفيف سمة الحقول وتعيينه بواسطة النظام وفقًا للمنطقة الزمنية واللغة عند تهيئة مثيل التقويم. لاحظ أنه سيتم حسابه بناءً على المنطقة الزمنية التي حددتها ، على عكس الوقت ، والتي تعتمد دائمًا على المنطقة الزمنية الافتراضية للنظام.
أنا شخصياً أعتقد أن تصميم التقويم له جوانب أنيقة وغير معقولة. بعد كل شيء ، إنها "عتيقة" وسيتم استبدالها في النهاية.
DateFormat تحويل تنسيق
كما نرى من أحد أمثلةنا السابقة ، من المزعج للغاية أن يتم إخراج معلومات تاريخ الإخراج بتنسيق متوقع للتقويم ويجب تقسيمه يدويًا. يتم استخدام DateFormat لدينا للتعامل مع التحويل بين السلاسل المنسقة وأخصائيات البيانات.
مثل التقويم ، DateFormat هو أيضا فئة مجردة. نحن بحاجة إلى إنشاء كائن مثيله من خلال أساليب المصنع. هناك أساسا أساليب المصنع التالية:
// فقط وقت المعالجة وقت التحويل العام الثابت الثابت في DateFormat getTimeInstance () // فقط تحويل تاريخ العملية العامة الثابتة الثابتة getDateInstance () // يمكنك التعامل مع كل من الوقت والتاريخ النهائي الثابت في DateFormat getDateTimeInstance ()
بالطبع ، كل منهم لديه أساليب التحميل الزائد الخاصة بهم ، وسنرى التفاصيل لاحقًا.
هناك نوعان من الطرق لـ DateFormat و Format و Parse.
تنسيق السلسلة النهائية العامة (تاريخ التاريخ) تحليل التاريخ العام (مصدر السلسلة)
يتم استخدام طريقة التنسيق لتنسيق كائن تاريخ كسلسلة ، ويتم استخدام طريقة التحليل لاستبدال سلسلة منسقة بكائن تاريخ. على سبيل المثال:
public static void main (string [] args) {calendar calendar = calendar.getInstance () ؛ DateFormat DateFormat = dateFormat.getDateTimeInstance () ؛ System.out.println (DateFormat.Format (Calendar.getTime ())) ؛}نتيجة الإخراج:
2018-4-21 16:58:09
من الواضح أن مثيل DateFormat الذي تم إنشاؤه في المصنع لا يمكنه تخصيص محتوى تنسيق الإخراج ، أي أن تنسيق سلسلة الإخراج ثابت ولا يمكنه تلبية الاحتياجات الخاصة في بعض الحالات. بشكل عام ، سوف نستخدم مباشرة واحدة من فئات التنفيذ الخاصة به ، SimpleDateFormat.
يتيح لك SimplEdateFormat تمرير معلمة نمط عند إنشاء مثيل لتخصيص تنسيق الإخراج لأحرف التاريخ. على سبيل المثال:
public static void main (string [] args) {dateformat dateFormat = new SimpleToThformat ("Yyyyy Year Mm Month Day") ؛ System.out.println (DateFormat.Format (New Date ())) ؛}نتيجة الإخراج:
21 أبريل 2018
في،
بالطبع ، من المريح للغاية تحويل تواريخ السلسلة. يُسمح بالأوضاع المخصصة ، ولكن يجب أن تلتزم بالأنماط التي تحددها بنفسك ، وإلا فلن يتمكن البرنامج من تحليله بنجاح. على سبيل المثال:
Public Static Void Main (String [] args) {String str = "Saturday ، April 21 ، 2018" ؛ DateFormat sdateformat = جديد spiStformat ("Yyyy Year M Month DD DAY HH POINT MM POINT E") ؛ sdateformat.parse (str) ؛ system.out.println (sdateformat.getCalendar (). getTime ()) ؛}نتيجة الإخراج:
السبت 21 أبريل 17:17:00 CST 2018
من الواضح أن البرنامج يتم تحليل سلسلةنا بشكل صحيح وتحويلها إلى كائن تقويمي مخزّن داخل DateFormat.
بشكل عام ، تمكنت التاريخ والتقويم و DateFormat من التعامل مع مشكلات الوقت والتاريخ العام ، ولكن حتما ، لا يزالون مرهقة ويصعب استخدامها.
نظرًا لقيود المساحة ، سنقارن عن واجهة برمجة تطبيقات Java 8 الجديدة في المقالة التالية ، وسوف تجد أنه يحتوي على تصميم أكثر أناقة وتشغيلًا بسيطًا.