מבוא ל- Java 8 תאריך / שעה API

1. סקירה כללית

Java 8 הציגה ממשקי API חדשים עבור תַאֲרִיך ו זְמַן כדי לטפל בחסרונות של המבוגרים java.util.Date ו java.util.Calendar.

כחלק ממאמר זה, נתחיל עם הבעיות הקיימות תַאֲרִיך ו לוּחַ שָׁנָה ממשקי API ובואו נדון כיצד ה- Java 8 החדש תַאֲרִיך ו זְמַן ממשקי API מטפלים בהם.

נבחן גם כמה משיעורי הליבה של פרויקט Java 8 החדש שהם חלק מה- java.time חבילה כמו LocalDate, LocalTime, LocalDateTime, ZonedDateTime, תקופה, משך זמן וממשקי ה- API הנתמכים שלהם.

2. סוגיות עם הקיים תַאֲרִיך/זְמַן ממשקי API

  • בטיחות חוטים - ה תַאֲרִיך ו לוּחַ שָׁנָה שיעורים אינם בטוחים בשרשור, מה שמותיר למפתחים להתמודד עם כאב הראש של בעיות ניתוק לבוא במקביל ולכתוב קוד נוסף לטיפול בבטיחות התבריגות. להפך החדש תַאֲרִיך ו זְמַן ממשקי API שהוכנסו ב- Java 8 אינם ניתנים לשינוי ובטוחים בשרשור, ובכך מורידים את כאב הראש הזה במקביל למפתחים.
  • APIs תכנון וקלות הבנה - ה תַאֲרִיך ו לוּחַ שָׁנָה ממשקי API מעוצבים בצורה גרועה עם שיטות לא מספקות לביצוע פעולות יומיומיות. החדש תאריך שעה ממשקי API הם ממוקדי ISO ועוקבים אחר מודלים תחומים עקביים עבור תאריך, שעה, משך תקופות. ישנם מגוון רחב של שיטות שימוש התומכות בפעולות הנפוצות ביותר.
  • ZonedDate ו זְמַן - המפתחים נאלצו לכתוב לוגיקה נוספת בכדי לטפל בהיגיון אזור הזמן עם ממשקי ה- API הישנים, ואילו בעזרת ממשקי ה- API החדשים, ניתן לבצע טיפול עם אזור הזמן עם מְקוֹמִי ו ZonedDate/זְמַן ממשקי API.

3. שימוש LocalDate, זמן מקומי ו LocalDateTime

השיעורים הנפוצים ביותר הם LocalDate, זמן מקומי ו LocalDateTime. כפי ששמם מציין, הם מייצגים את התאריך / שעה המקומי מהקשר הצופה.

שיעורים אלה משמשים בעיקר כאשר לא נדרש להגדיר במפורש את אזור הזמן בהקשר. במסגרת סעיף זה, נסקור את ממשקי ה- API הנפוצים ביותר.

3.1. עובד עם LocalDate

ה LocalDate מייצג תאריך בפורמט ISO (yyyy-MM-dd) ללא זמן.

ניתן להשתמש בו לאחסון תאריכים כמו ימי הולדת וימי תשלום.

ניתן ליצור מופע של תאריך נוכחי משעון המערכת להלן:

LocalDate localDate = LocalDate.now ();

ה LocalDate המייצג יום, חודש ושנה ספציפיים ניתן להשיג באמצעות "שֶׁלאו באמצעות שיטת "לְנַתֵחַ" שיטה. לדוגמא קטעי הקוד שלהלן מייצגים את ה- LocalDate ליום 20 בפברואר 2015:

LocalDate.of (2015, 02, 20); LocalDate.parse ("20/02/2015");

ה LocalDate מספק שיטות שימוש שונות להשגת מידע מגוון. בואו נציץ במהירות בכמה משיטות ה- API הללו.

קטע הקוד הבא מקבל את התאריך המקומי הנוכחי ומוסיף יום אחד:

LocalDate מחר = LocalDate.now (). PlusDays (1);

דוגמה זו משיגה את התאריך הנוכחי ומחסרת חודש אחד. שים לב כיצד הוא מקבל enum כיחידת הזמן:

LocalDate previousMonthSameDay = LocalDate.now (). מינוס (1, ChronoUnit.MONTHS);

בשתי דוגמאות הקוד הבאות אנו מנתחים את התאריך "2016-06-12" ומקבלים את יום השבוע ואת יום החודש בהתאמה. שימו לב לערכי ההחזרה, הראשון הוא אובייקט המייצג את ה- יום בשבוע ואילו השנייה ב- int המייצג את הערך הסדיר של החודש:

יום ראשון DayOfWeek = LocalDate.parse ("2016-06-12"). GetDayOfWeek (); int שתים עשרה = LocalDate.parse ("2016-06-12"). getDayOfMonth ();

אנו יכולים לבדוק אם מתרחש תאריך בשנה מעוברת. בדוגמה זו אנו בודקים אם התאריך הנוכחי מתרחש הוא שנה מעוברת:

leapYear בוליאני = LocalDate.now (). isLeapYear ();

הקשר בין תאריך לאחר יכול להיקבע שיתרחש לפני או אחרי תאריך אחר:

בוליאני notBefore = LocalDate.parse ("2016-06-12") .isBefore (LocalDate.parse ("2016-06-11")); בוליאני isAfter = LocalDate.parse ("2016-06-12") .isAfter (LocalDate.parse ("2016-06-11"));

ניתן לקבל גבולות תאריך מתאריך נתון. בשתי הדוגמאות הבאות אנו מקבלים את LocalDateTime המייצג את תחילת היום (2016-06-12T00: 00) של התאריך הנתון ואת LocalDate המייצג את תחילת החודש (2016-06-01) בהתאמה:

LocalDateTime beginningOfDay = LocalDate.parse ("12-06-2016). AtStartOfDay (); LocalDate firstDayOfMonth = LocalDate.parse ("2016-06-12"). עם (TemporalAdjusters.firstDayOfMonth ());

עכשיו בואו נסתכל על האופן בו אנו עובדים עם הזמן המקומי.

3.2. עובד עם זמן מקומי

ה זמן מקומי מייצג זמן ללא תאריך.

דומה ל LocalDate מופע של זמן מקומי ניתן ליצור משעון המערכת או על ידי שימוש בשיטת "parse" ו- "of". מבט מהיר על כמה ממשקי ה- API הנפוצים להלן.

מופע של זרם זמן מקומי ניתן ליצור משעון המערכת כמפורט להלן:

LocalTime now = LocalTime.now ();

במדגם הקוד שלהלן, אנו יוצרים a זמן מקומי המייצג 06:30 בבוקר על ידי ניתוח ייצוג מחרוזות:

LocalTime sixThirty = LocalTime.parse ("06:30");

ניתן להשתמש בשיטת Factory "of" ליצירת זמן מקומי. לדוגמא הקוד שלמטה יוצר זמן מקומי המייצג 06:30 בבוקר בשיטת המפעל:

LocalTime sixThirty = LocalTime.of (6, 30);

הדוגמה הבאה יוצרת א זמן מקומי על ידי ניתוח מחרוזת ומוסיף לו שעה באמצעות ה- API "פלוס". התוצאה תהיה זמן מקומי המייצג 07:30:

LocalTime sevenThirty = LocalTime.parse ("06:30"). פלוס (1, ChronoUnit.HOURS);

קיימות שיטות גטר שונות בהן ניתן להשתמש כדי לקבל יחידות זמן ספציפיות כמו שעה, דקות ושניות כמו להלן:

int six = LocalTime.parse ("06:30"). getHour ();

אנחנו יכולים גם לבדוק אם זמן ספציפי הוא לפני או אחרי זמן ספציפי אחר. מדגם הקוד שלהלן משווה בין שניים זמן מקומי שהתוצאה תהיה נכונה לגביו:

בוליאני isbefore = LocalTime.parse ("06:30"). isBefore (LocalTime.parse ("07:30"));

ניתן להשיג את הזמן המקסימלי, הדקות והצהריים ביום על ידי קבועים ב זמן מקומי מעמד. זה מאוד שימושי בעת ביצוע שאילתות בסיס נתונים לאיתור רשומות בפרק זמן נתון. לדוגמה, הקוד שלהלן מייצג 23: 59: 59.99:

LocalTime maxTime = LocalTime.MAX

עכשיו בואו נצלול LocalDateTime.

3.3. עובד עם LocalDateTime

ה LocalDateTime משמש לייצוג שילוב של תאריך ושעה.

זהו הכיתה הנפוצה ביותר כאשר אנו זקוקים לשילוב של תאריך ושעה. הכיתה מציעה מגוון של ממשקי API ואנו נבחן כמה מהמשתמשים הנפוצים ביותר.

מופע של LocalDateTime ניתן להשיג משעון המערכת בדומה ל- LocalDate ו זמן מקומי:

LocalDateTime.now ();

דוגמאות הקוד שלהלן מסבירות כיצד ליצור מופע בשיטות "of" ו"ניתוח "במפעל. התוצאה תהיה LocalDateTime מופע המייצג 20 בפברואר 2015, 06:30:

LocalDateTime.of (2015, חודש פברואר, 20, 06, 30);
LocalDateTime.parse ("2015-02-20T06: 30: 00");

ישנם ממשקי API של כלי תמיכה התומכים בחיסור וחיסור של יחידות זמן ספציפיות כמו ימים, חודשים, שנה ודקות. דוגמאות הקוד שלהלן מדגימות את השימוש בשיטות "פלוס" ו- "מינוס". ממשקי API אלה מתנהגים בדיוק כמו עמיתיהם LocalDate ו זמן מקומי:

localDateTime.plusDays (1);
localDateTime.minusHours (2);

ניתן להשיג שיטות גטר לחילוץ יחידות ספציפיות הדומות לשיעורי התאריך והשעה. בהינתן המקרה הנ"ל של LocalDateTime, דוגמת הקוד שלהלן תחזור בחודש פברואר:

localDateTime.getMonth ();

4. שימוש ZonedDateTime ממשק API

Java 8 מספק ZonedDateTime כאשר אנו צריכים להתמודד עם תאריך ושעה ספציפיים לאזור הזמן. ה ZoneId הוא מזהה המשמש לייצוג אזורים שונים. ישנם כ 40 אזורי זמן שונים ואת ZoneId משמשים לייצוגם כדלקמן.

בקטע הקוד הזה אנו יוצרים אֵזוֹר לפריז:

ZoneId zoneId = ZoneId.of ("אירופה / פריז"); 

קבוצה של כל מזהי האזור ניתן להשיג כמפורט להלן:

הגדר allZoneIds = ZoneId.getAvailableZoneIds ();

ה LocalDateTime ניתן להמיר לאזור ספציפי:

ZonedDateTime zonedDateTime = ZonedDateTime.of (localDateTime, zoneId);

ה ZonedDateTime מספק לְנַתֵחַ שיטה לקבלת זמן תאריך ספציפי לאזור:

ZonedDateTime.parse ("2015-05-03T10: 15: 30 + 01: 00 [Europe / Paris]");

דרך נוספת לעבוד עם אזור זמן היא באמצעות OffsetDateTime. ה OffsetDateTime הוא ייצוג בלתי-משתנה של תאריך-שעה עם קיזוז. מחלקה זו מאחסן את כל שדות התאריך והשעה, בדיוק של ננו שניות, כמו גם את הקיזוז מ- UTC / גריניץ '.

ה OffSetDateTime ניתן ליצור מופע למטה באמצעות ZoneOffset. כאן אנו יוצרים a LocalDateTime המייצג את השעה 06:30 בבוקר ב -20 בפברואר 2015:

LocalDateTime localDateTime = LocalDateTime.of (2015, חודש. FEBRUARY, 20, 06, 30);

לאחר מכן אנו מוסיפים שעתיים לזמן על ידי יצירת a ZoneOffset והגדרה ל localDateTime למשל:

Offset ZoneOffset = ZoneOffset.of ("+ 02:00"); OffsetDateTime offSetByTwo = OffsetDateTime .of (localDateTime, offset);

כעת יש לנו localDateTime של 2015-02-20 06:30 +02: 00. עכשיו נעבור לאופן שינוי ערכי תאריך ושעה באמצעות ה- פרק זמן ו מֶשֶׁך שיעורים.

5. שימוש פרק זמן ו מֶשֶׁך

ה פרק זמן הכיתה מייצגת כמות זמן במונחים של שנים, חודשים וימים ואת מֶשֶׁך class מייצג כמות זמן במונחים של שניות ושניות ננו.

5.1. עובד עם פרק זמן

ה פרק זמן נעשה שימוש נרחב בכיתה לשינוי ערכים של תאריך נתון או כדי להשיג את ההבדל בין שני תאריכים:

LocalDate initialDate = LocalDate.parse ("10/10/2007");

ה תַאֲרִיך ניתן לתפעל באמצעות פרק זמן כפי שמוצג בקטע הקוד הבא:

LocalDate finalDate = initialDate.plus (Period.ofDays (5));

ה פרק זמן בכיתה ישנן שיטות גטר שונות כגון getYears, getMonths ו getDays לקבל ערכים מ- פרק זמן לְהִתְנַגֵד. דוגמת הקוד שלהלן מחזירה int ערך של 5 כאשר אנו מנסים להשיג הבדל מבחינת הימים:

int five = Period.between (initialDate, finalDate) .getDays ();

ה פרק זמן בין שני תאריכים ניתן להשיג ביחידה ספציפית כגון ימים או חודש או שנים, באמצעות ChronoUnit.between:

long five = ChronoUnit.DAYS.between (initialDate, finalDate);

דוגמת קוד זו מחזירה חמישה ימים. בואו נמשיך להסתכל על ה- מֶשֶׁך מעמד.

5.2. עובד עם מֶשֶׁך

דומה ל פרק זמן, ה שיעור משך הוא שימוש להתמודדות זְמַן. בקוד הבא אנו יוצרים a זמן מקומי של 6:30 בבוקר ואז הוסף משך 30 שניות כדי לבצע זמן מקומי של 06:30:30 בבוקר:

LocalTime initialTime = LocalTime.of (6, 30, 0); LocalTime finalTime = initialTime.plus (Duration.ofSeconds (30));

ה מֶשֶׁך בין שני מקרים ניתן להשיג כ- מֶשֶׁך או כיחידה ספציפית. בקטע הקוד הראשון אנו משתמשים ב- בֵּין() שיטת ה- מֶשֶׁך בכיתה כדי למצוא את הפרש הזמן בין זמן אחרון ו initialTime והחזירו את ההפרש בשניות:

ארוך שלושים = Duration.between (initialTime, finalTime) .getSeconds ();

בדוגמה השנייה אנו משתמשים ב- בֵּין() שיטת ה- ChronoUnit בכיתה לביצוע אותה פעולה:

ארוך שלושים = ChronoUnit.SECONDS.between (initialTime, finalTime);

כעת נבדוק כיצד להמיר קיים תַאֲרִיך ו לוּחַ שָׁנָה לחדש תַאֲרִיך/זְמַן.

6. תאימות עם תַאֲרִיך ו לוּחַ שָׁנָה

Java 8 הוסיפה את toInstant () שיטה המסייעת להמיר את הקיים תַאֲרִיך ו לוּחַ שָׁנָה מופע ל- API החדש של Date Time כמו בקטע הקוד הבא:

LocalDateTime.ofInstant (date.toInstant (), ZoneId.systemDefault ()); LocalDateTime.ofInstant (calendar.toInstant (), ZoneId.systemDefault ());

ה LocalDateTime ניתן לבנות משנות עידן כמפורט להלן. התוצאה של הקוד שלמטה תהיה LocalDateTime המייצג 2016-06-13T11: 34: 50:

LocalDateTime.ofEpochSecond (1465817690, 0, ZoneOffset.UTC);

עכשיו בוא נעבור ל תַאֲרִיך ו זְמַן עיצוב.

7. תַאֲרִיך ו זְמַן עיצוב

Java 8 מספק ממשקי API לעיצוב קל של תַאֲרִיך ו זְמַן:

LocalDateTime localDateTime = LocalDateTime.of (2015, חודש. ינואר, 25, 6, 30);

הקוד שלמטה מעביר פורמט תאריך ISO לעיצוב התאריך המקומי. התוצאה תהיה 25/01/2015:

מחרוזת localDateString = localDateTime.format (DateTimeFormatter.ISO_DATE);

ה DateTimeFormatter מספק אפשרויות עיצוב סטנדרטיות שונות. ניתן לספק דפוסים מותאמים אישית גם לשיטת הפורמט, כמו למטה, שיחזיר א LocalDate בתאריך 25/01/2015:

localDateTime.format (DateTimeFormatter.ofPattern ("yyyy / MM / dd"));

אנו יכולים לעבור בסגנון עיצוב כ- קצר, ארוך אוֹ בינוני כחלק מאפשרות העיצוב. דוגמת הקוד שלהלן תתן פלט המייצג LocalDateTime ב -25 בינואר 2015, 06:30:00:

localDateTime .format (DateTimeFormatter.ofLocalizedDateTime (FormatStyle.MEDIUM)) .withLocale (Locale.UK);

הבה נבחן חלופות הזמינות ל- Java 8 Core תַאֲרִיך/זְמַן ממשקי API.

8. Backport ואפשרויות חלופיות

8.1. שימוש ב- Project Threeten

לארגונים הנמצאים בדרך למעבר לג'אווה 8 מג'אווה 7 או ג'אווה 6 ורוצים להשתמש ב- API של תאריך ושעה, פרויקט שלוש מספק יכולת חזרה. מפתחים יכולים להשתמש בשיעורים הקיימים בפרויקט זה כדי להשיג פונקציונליות זהה לזו של Java 8 החדשה תַאֲרִיך ו זְמַן API וברגע שהם עוברים לג'אווה 8, ניתן להחליף את החבילות. חפץ לפרויקט השלוש עשרה נמצא במאגר המרכזי של maven:

 org.threeten threetenbp 1.3.1 

8.2. ספריית ג'ודה-טיים

אלטרנטיבה נוספת עבור Java 8 תַאֲרִיך ו זְמַן הספרייה היא ספריית Joda-Time. למעשה ג'אווה 8 תאריך שעה ממשקי API הובילו במשותף על ידי מחבר ספריית Joda-Time (סטיבן קולבורן) ואורקל. ספרייה זו מספקת כמעט את כל היכולות הנתמכות ב- Java 8 תאריך שעה פּרוֹיֶקט. ניתן למצוא את החפץ במרכז maven על ידי הכללת התלות הבאה של pom בפרויקט שלך:

 joda-time joda-time 2.9.4 

9. מסקנה

Java 8 מספק קבוצה עשירה של ממשקי API עם עיצוב API עקבי לפיתוח קל יותר.

את דוגמאות הקוד למאמר לעיל ניתן למצוא במאגר git Java 8 Date / Time.