מבוא לג'ודה-טיים

1. הקדמה

Joda-Time היא ספריית עיבוד התאריכים והשעות הנפוצה ביותר, לפני שחרורו של Java 8. מטרתו הייתה להציע ממשק API אינטואיטיבי לעיבוד תאריך ושעה וכן לטפל בבעיות העיצוב שהיו קיימות ב- Java Date / Time API.

המושגים המרכזיים המיושמים בספרייה זו הוצגו בליבת JDK עם שחרור גרסת Java 8. ה- API של תאריך ושעה חדש נמצא ב- java.time חבילה (JSR-310). סקירה של תכונות אלה ניתן למצוא במאמר זה.

לאחר שחרורו של Java 8, מחברים מחשיבים את הפרויקט כגמור ברובם וממליצים להשתמש במידת האפשר ב- API של Java 8.

2. מדוע להשתמש בג'ודה-טיים?

ממשק ה- API של תאריך / שעה, לפני Java 8, הציג בעיות עיצוב מרובות.

בין הבעיות היא העובדה כי תַאֲרִיך ו SimpleDateFormatter שיעורים אינם בטוחים בחוטים. כדי לטפל בבעיה זו, Joda-Time משתמש בשיעורים בלתי ניתנים לשינוי לטיפול בתאריך ובשעה.

ה תַאֲרִיך המחלקה אינה מייצגת תאריך בפועל, אלא במקום זאת היא מציינת רגע בזמן בדיוק באלפיות השנייה. השנה ב תַאֲרִיך מתחיל משנת 1900, בעוד שרוב פעולות התאריך בדרך כלל משתמשות בעידן העידן שמתחיל מ -1 בינואר 1970.

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

ג'ודה-טיים מציעה גם כן תמיכה בשמונה מערכות לוח שנהבעוד שג'אווה מציעה 2 בלבד: גרגוריאנית - java.util.GorregianCalendar ויפנית - java.util.JapaneseImperialCalendar.

3. התקנה

כדי לכלול את הפונקציונליות של ספריית Joda-Time, עלינו להוסיף את התלות הבאה מ Maven Central:

 joda-time joda-time 2.10 

4. סקירה כללית של הספרייה

ג'ודה-טיים מדגמנת את מושג תאריך ושעה באמצעות השיעורים ב org.joda.time חֲבִילָה.

בין השיעורים הנפוצים ביותר הם:

  • LocalDate - מייצג תאריך ללא זמן
  • זמן מקומי - מייצג את הזמן ללא אזור הזמן
  • LocalDateTime - מייצג את התאריך והשעה ללא אזור זמן
  • רֶגַע - מייצג נקודת זמן מדויקת באלפיות השנייה מתקופת ג'אווה של 1970-01-01T00: 00: 00Z
  • מֶשֶׁך - מייצג את משך המילישניות בין 2 נקודות זמן
  • פרק זמן - דומה ל מֶשֶׁך, אך מאפשר גישה למרכיבים בודדים של אובייקט התאריך והשעה, כמו שנים, חודש, ימים וכו '.
  • הַפסָקָה - מייצג את מרווח הזמן בין שני רגעים

תכונות חשובות אחרות הן מנתחי תאריכים ומעצבים. אלה ניתן למצוא ב org.joda.time.format חֲבִילָה.

ה מערכת לוח שנה ואזור זמן ניתן למצוא שיעורים ספציפיים ב org.joda.time.chrono ו org.joda.time.tz חבילות.

בואו נסתכל על כמה דוגמאות בהן אנו משתמשים בתכונות המפתח של Joda-Time לטיפול בתאריך ובשעה.

5. ייצוג תאריך ושעה

5.1. תאריך ושעה נוכחיים

התאריך הנוכחי, ללא מידע על הזמן, ניתן להשיג באמצעות עַכשָׁיו() שיטה מ ה LocalDate מעמד:

LocalDate currentDate = LocalDate.now ();

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

LocalTime currentTime = LocalTime.now ();

להשיג א ייצוג של התאריך והשעה הנוכחיים מבלי להתחשב באזור הזמן, אנו יכולים להשתמש בו LocalDateTime:

LocalDateTime currentDateAndTime = LocalDateTime.now ();

עכשיו, באמצעות currentDateAndTime, אנו יכולים להמיר אותו לסוגים האחרים של אובייקטים המדגמים תאריך ושעה.

אנחנו יכולים להשיג א תאריך שעה אובייקט (הלוקח בחשבון את אזור הזמן) באמצעות השיטה toDateTime (). כאשר הזמן אינו נחוץ אנו יכולים להמיר אותו ל- a LocalDate בשיטה toLocalDate ()וכאשר אנו זקוקים רק לזמן בו אנו יכולים להשתמש toLocalTime () להשיג א זמן מקומי לְהִתְנַגֵד:

DateTime dateTime = currentDateAndTime.toDateTime (); LocalDate localDate = currentDateAndTime.toLocalDate (); LocalTime localTime = currentDateAndTime.toLocalTime ();

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

LocalDate currentDate = LocalDate.now (DateTimeZone.forID ("אמריקה / שיקגו"));

כמו כן, Joda-Time מציע אינטגרציה מצוינת עם ה- Java Date and Time API. הקבלנים מקבלים א java.util.Date אובייקט וגם, אנו יכולים להשתמש ב- toDate () שיטה להחזרת א java.util.Date לְהִתְנַגֵד:

LocalDateTime currentDateTimeFromJavaDate = LocalDateTime חדש (תאריך חדש ()); תאריך currentJavaDate = currentDateTimeFromJavaDate.toDate ();

5.2. תאריך ושעה מותאמים אישית

כדי לייצג תאריך ושעה מותאמים אישית, Joda-Time מספק לנו כמה בונים. אנו יכולים לציין את האובייקטים הבאים:

  • an רֶגַע
  • ג'אווה תַאֲרִיך לְהִתְנַגֵד
  • א חוּט ייצוג התאריך והשעה באמצעות פורמט ISO
  • חלקים מהתאריך והשעה: שנה, חודש, יום, שעה, דקה, שנייה, אלפית השנייה
תאריך oneMinuteAgoDate = תאריך חדש (System.currentTimeMillis () - (60 * 1000)); OneMinutesAgoInstant מיידי = מיידי חדש (oneMinuteAgoDate); DateTime customDateTimeFromInstant = DateTime חדש (oneMinutesAgoInstant); DateTime customDateTimeFromJavaDate = DateTime חדש (oneMinuteAgoDate); DateTime customDateTimeFromString = DateTime חדש ("2018-05-05T10: 11: 12.123"); DateTime customDateTimeFromParts = DateTime חדש (2018, 5, 5, 10, 11, 12, 123); 

דרך נוספת בה אנו יכולים להגדיר תאריך ושעה מותאמים אישית היא על ידי ניתוח נתון חוּט ייצוג של תאריך ושעה בפורמט ISO:

DateTime parsedDateTime = DateTime.parse ("2018-05-05T10: 11: 12.123");

אנו יכולים גם לנתח ייצוגים מותאמים אישית של תאריך ושעה על ידי הגדרת מותאם אישית DateTimeFormatter:

DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern ("MM / dd / yyyy HH: mm: ss"); DateTime parsedDateTimeUsingFormatter = DateTime.parse ("05/05/2018 10:11:12", dateTimeFormatter);

6. עבודה עם תאריך ושעה

6.1. באמצעות רֶגַע

An רֶגַע מייצג את מספר האלפיות השנייה החל מ 01-01 1970T00: 00: 00Z עד רגע נתון בזמן. לדוגמא, ניתן להשיג את רגע הזמן הנוכחי באמצעות קונסטרוקטור ברירת המחדל או השיטה עַכשָׁיו():

מיידי מיידי = מיידי חדש (); Instant.now ();

כדי ליצור רֶגַע לרגע זמן מותאם אישית אנו יכולים להשתמש באחד הבונים או להשתמש בשיטות ofEpochMilli () ו ofEpochSecond ():

InstantFromEpochMilli מיידי = Instant.ofEpochMilli (milliesFromEpochTime); InstantFromEpocSeconds מיידי = Instant.ofEpochSecond (secondsFromEpochTime);

הקבלנים מקבלים א חוּט המייצג תאריך ושעה בפורמט ISO, Java תַאֲרִיך או א ארוך ערך המייצג את מספר האלפיות השנייה החל מה 01-01 1970T00: 00: 00Z:

InstantFromString מיידי = Instant חדש ("2018-05-05T10: 11: 12"); InstantFromDate מיידי = Instant חדש (oneMinuteAgoDate); InstantFromTimestamp מיידי = Instant חדש (System.currentTimeMillis () - (60 * 1000));

כאשר תאריך ושעה מיוצגים כ- חוּט יש לנו אפשרות לנתח את חוּט באמצעות הפורמט הרצוי:

Instant parsedInstant = Instant.parse ("05/05/2018 10:11:12", dateTimeFormatter);

עכשיו כשאנחנו יודעים מה רֶגַע מייצג ואיך נוכל ליצור אחד כזה, בואו נראה איך אפשר להשתמש בו.

להשוות ל רֶגַע חפצים שאנחנו יכולים להשתמש בהם בהשוואה ל() כי זה מיישם את ניתן להשוות ממשק, אך גם אנו יכולים להשתמש בשיטות ה- Joda-Time API המסופקות ב- קריא מיידי ממשק אשר רֶגַע מיישם גם:

assertTrue (instantNow.compareTo (oneMinuteAgoInstant)> 0); assertTrue (instantNow.isAfter (oneMinuteAgoInstant)); assertTrue (oneMinuteAgoInstant.isBefore (instantNow)); assertTrue (oneMinuteAgoInstant.isBeforeNow ()); assertFalse (oneMinuteAgoInstant.isEqual (instantNow));

תכונה מועילה נוספת היא רֶגַע ניתן להמיר ל- תאריך שעה אובייקט או אירוע Java תַאֲרִיך:

DateTime dateTimeFromInstant = instant.toDateTime (); תאריך javaDateFromInstant = instant.toDate ();

כאשר אנו זקוקים לגישה לחלקים של תאריך ושעה, כמו השנה, השעה וכן הלאה, אנו יכולים להשתמש ב- לקבל() שיטה ולציין a DateTimeField:

int שנה = instant.get (DateTimeFieldType.year ()); int חודש = instant.get (DateTimeFieldType.monthOfYear ()); int day = instant.get (DateTimeFieldType.dayOfMonth ()); int שעה = instant.get (DateTimeFieldType.hourOfDay ());

עכשיו כשסיקרנו את רֶגַע בואו נראה כמה דוגמאות כיצד נוכל להשתמש מֶשֶׁך, פרק זמן ו הַפסָקָה.

6.2. באמצעות מֶשֶׁך, פרק זמן ו הַפסָקָה

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

longTimestamp ארוך = System.currentTimeMillis (); oneHourAgo ארוך = חותמת הזמן הנוכחית - 24 * 60 * 1000; משך משך = משך חדש (oneHourAgo, חותמת הזמן הנוכחית); Instant.now (). פלוס (משך זמן);

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

duration DurationInDays = duration.getStandardDays (); משך זמן ארוךInHours = duration.getStandardHours (); duration longInMinutes = duration.getStandardMinutes (); duration longInSeconds = duration.getStandardSeconds (); duration longInMilli = duration.getMillis ();

ההבדל העיקרי בין פרק זמן ו מֶשֶׁך האם זה פרק זמן מוגדר במונחי רכיבי התאריך והשעה שלו (שנים, חודשים, שעות וכו ') ואינו מייצג מספר מדויק של אלפיות השנייה.. כשמשתמש פרק זמן חישובי תאריך ושעה ישקול את אזור הזמן ושמירת הקיץ.

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

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

תקופת תקופה = תקופה חדשה () withMonths (1); LocalDateTime datePlusPeriod = localDateTime.plus (נקודה);

An הַפסָקָהכשמו כן הוא, מייצג את התאריך ורווח הזמן בין שתי נקודות קבועות בזמן המיוצגות על ידי שתיים רֶגַע חפצים:

מרווח זמן = מרווח חדש (oneMinuteAgoInstant, instantNow);

הכיתה שימושית כאשר עלינו לבדוק האם שני מרווחים חופפים או מחשבים את הפער ביניהם. ה חֲפִיפָה() השיטה תחזיר את החפיפה הַפסָקָה אוֹ ריק כאשר הם לא חופפים:

StartInterval1 מיידי = מיידי חדש ("2018-05-05T09: 00: 00.000"); EndInterval1 מיידי = מיידי חדש ("2018-05-05T11: 00: 00.000"); מרווח זמן 1 = מרווח חדש (startInterval1, endInterval1); StartInterval2 מיידי = מיידי חדש ("2018-05-05T10: 00: 00.000"); EndInterval2 מיידי = מיידי חדש ("2018-05-05T11: 00: 00.000"); מרווח זמן 2 = מרווח חדש (startInterval2, endInterval2); Interval overlappingInterval = interval1.overlap (interval2);

ניתן לחשב את ההפרש בין המרווחים באמצעות פער() וכאשר אנו רוצים לדעת האם סוף מרווח שווה לתחילת מרווח אחר אנו יכולים להשתמש ב- סמוך () שיטה:

assertTrue (interval1.abuts (Interval new (Instant new ("2018-05-05T11: 00: 00.000"), Instant new ("2018-05-05T13: 00: 00.000")));

6.3. פעולות תאריך ושעה

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

בוא ניקח LocalDateTime לרגע הנוכחי ונסה לשנות את ערכו:

LocalDateTime currentLocalDateTime = LocalDateTime.now ();

להוסיף יום נוסף ל currentLocalDateTime אנו משתמשים ב- plusDays () שיטה:

LocalDateTime nextDayDateTime = currentLocalDateTime.plusDays (1);

אנחנו יכולים גם להשתמש ועוד() שיטה להוסיף א פרק זמן אוֹ מֶשֶׁך שלנו currentLocalDateTime:

תקופה oneMonth = תקופה חדשה (). WithMonths (1); LocalDateTime nextMonthDateTime = currentLocalDateTime.plus (oneMonth);

השיטות דומות לרכיבי התאריך והשעה האחרים, למשל, plusYears () להוספת שנים נוספות, plusSeconds () להוספת שניות נוספות וכן הלאה.

להפחית יום משלנו currentLocalDateTime אנחנו יכולים להשתמש ב- מינוס ימים () שיטה:

LocalDateTime previousDayLocalDateTime = currentLocalDateTime.minusDays (1);

חוץ מזה, ביצוע חישובים עם תאריך ושעה, אנחנו יכולים גם לקבוע חלקים בודדים של התאריך או השעה. לדוגמא, ניתן להגדיר את השעה ל- 10 באמצעות ה- withHourOfDay () שיטה. שיטות אחרות שמתחילות בקידומת "עם" יכול לשמש לקביעת רכיבים של תאריך או זמן זה:

LocalDateTime currentDateAtHour10 = currentLocalDateTime .withHourOfDay (0) .withMinuteOfHour (0) .withSecondOfMinute (0) .withMillisOfSecond (0);

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

  • toDateTime () - חוזר בתשובה LocalDateTime אל א תאריך שעה לְהִתְנַגֵד
  • toLocalDate () - חוזר בתשובה LocalDateTime אל א LocalDate לְהִתְנַגֵד
  • toLocalTime () - ממיר LocalDateTime לאובייקט LocalTime
  • toDate () - חוזר בתשובה LocalDateTime לג'אווה תַאֲרִיך לְהִתְנַגֵד

7. עבודה עם אזורי זמן

Joda-Time מקלה עלינו לעבוד עם אזורי זמן שונים ושינויים ביניהם. יש לנו את ה DateTimeZone מעמד מופשט המשמש לייצוג כל ההיבטים הנוגעים לאזור זמן.

אזור הזמן המוגדר כברירת מחדל המשמש את Joda-Time נבחר מתוך user.timezone נכס מערכת Java. ממשק ה- API של הספרייה מאפשר לנו לציין, באופן אינדיבידואלי, לכל מחלקה או חישוב באיזה אזור זמן להשתמש. לדוגמא, אנו יכולים ליצור אובייקט LocalDateTime

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

DateTimeZone.setDefault (DateTimeZone.UTC);

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

כדי לראות את כל אזורי הזמן הזמינים אנו יכולים להשתמש בשיטה getAvailableIDs ():

DateTimeZone.getAvailableIDs ()

כאשר עלינו לייצג את התאריך או השעה באזור זמן ספציפי נוכל להשתמש בכל אחת מהשיעורים זמן מקומי, LocalDate, LocalDateTime, תאריך שעה וציין בבנאי את DateTimeZone לְהִתְנַגֵד:

DateTime dateTimeInChicago = DateTime חדש (DateTimeZone.forID ("אמריקה / שיקגו")); DateTime dateTimeInBucharest = DateTime חדש (DateTimeZone.forID ("אירופה / בוקרשט")); LocalDateTime localDateTimeInChicago = LocalDateTime חדש (DateTimeZone.forID ("אמריקה / שיקגו"));

כמו כן, בעת המרה בין אותם שיעורים אנו יכולים לציין את אזור הזמן הרצוי. השיטה toDateTime () מקבל א DateTimeZone חפץ ו toDate () מקבל אובייקט java.util.TimeZone:

DateTime convertDateTime = localDateTimeInChicago.toDateTime (DateTimeZone.forID ("אירופה / בוקרשט")); תאריך convertDate = localDateTimeInChicago.toDate (TimeZone.getTimeZone ("אירופה / בוקרשט"));

8. מסקנה

Joda-Time היא ספרייה נהדרת שהחלה במטרה העיקרית לפתור את הבעיות ב- JDK בנוגע לפעולות תאריך ושעה. עד מהרה זה הפך ל דה פאקטו ספרייה לטיפול בתאריך ובשעה ולאחרונה המושגים העיקריים ממנה הוצגו ב- Java 8.

חשוב לציין שהמחבר שוקל זאת "להיות פרויקט שסיים במידה רבה" וממליץ להעביר את הקוד הקיים לשימוש ביישום Java 8.

קוד המקור של המאמר זמין באתר GitHub.


$config[zx-auto] not found$config[zx-overlay] not found