מדריך ל- SimpleDateFormat

1. הקדמה

במדריך זה ניקח סיור מעמיק ב SimpleDateFormat מעמד.

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

2. מיידיות פשוטה

ראשית, בואו נסתכל כיצד לייצר חדש SimpleDateFormat לְהִתְנַגֵד.

ישנם 4 בונים אפשריים - אך בהתאם לשם, בואו נשמור על הדברים פשוטים. כל מה שאנחנו צריכים כדי להתחיל הוא חוּט ייצוג של דפוס תאריך שאנחנו רוצים.

נתחיל בתבנית תאריכים מופרדת מקף ככה:

"dd-MM-yyyy"

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

מעצב SimpleDateFormat = SimpleDateFormat חדש ("dd-MM-yyyy"); assertEquals ("24-05-1977", formatter.format (תאריך חדש (233345223232L)); 

בקוד לעיל, מעצב ממיר אלפיות השנייה long לתאריך הניתן לקריאה אנושית - ה- 24 במאי 1977.

2.1. שיטות מפעל

למרות ש SimpleDateFormat הוא כיתה שימושית לבנות במהירות מעצב תאריכים, אנו ממליצים להשתמש בשיטות המפעל ב- פורמט תאריך מעמדgetDateFormat (), getDateTimeFormat (), getTimeFormat ().

הדוגמה שלעיל נראית מעט שונה כאשר משתמשים בשיטות המפעל הבאות:

מעצב DateFormat = DateFormat.getDateInstance (DateFormat.SHORT); assertEquals ("5/24/77", formatter.format (תאריך חדש (233345223232L));

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

2.2. חוט-בטיחות

JavaDoc עבור SimpleDateFormat קובע במפורש:

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

כך SimpleDateFormat מקרים אינם בטוחים בחוטיםועלינו להשתמש בהם בזהירות בסביבות מקבילות.

הגישה הטובה ביותר לפתרון בעיה זוהוא להשתמש בהם בשילוב עם א ThreadLocal. בדרך זו, כל חוט מסתיים עם שלו SimpleDateFormat למשל, וחוסר השיתוף הופך את התוכנית לבטוחה בשרשור:

מעצב סופי פרטי ThreadLocal = ThreadLocal .withInitial (() -> SimpleDateFormat חדש ("dd-MM-yyyy"));

הטיעון ל עם ההתחלה השיטה היא ספקית של SimpleDateFormat מקרים. בכל פעם שה- ThreadLocal צריך ליצור מופע, הוא ישתמש בספק זה.

אז נוכל להשתמש במעצב באמצעות ה- ThreadLocal למשל:

formatter.get (). פורמט (תאריך)

ה ThreadLocal.get () שיטת האתחול של SimpleDateFormat בהתחלה לשרשור הנוכחי ואז עושה שימוש חוזר במופע הזה.

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

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

  • באמצעות מסונכרן בלוקים או ReentrantLockס
  • יצירת מקרים לזרוק SimpleDateFormat לפי דרישה

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

כדאי להזכיר את זה, מאז Java 8, חדש DateTimeFormatter הכיתה הוצגה. החדש DateTimeFormatter הכיתה היא בלתי משתנה ובטוח בחוטים. אם אנו עובדים עם Java 8 ואילך, באמצעות החדש DateTimeFormatter מומלץ בכיתה.

3. ניתוח תאריכים

SimpleDateFormat ו פורמט תאריך לא רק לאפשר לנו לעצב תאריכים - אלא אנחנו יכולים גם להפוך את הפעולה. משתמש ב לְנַתֵחַ שיטה, אנחנו יכולים קלט את חוּט ייצוג של תאריך והחזרת ה- תַאֲרִיך שווה ערך לאובייקט:

מעצב SimpleDateFormat = SimpleDateFormat חדש ("dd-MM-yyyy"); תאריך myDate = תאריך חדש (233276400000L); תאריך parsedDate = formatter.parse ("24-05-1977"); assertEquals (myDate.getTime (), parsedDate.getTime ());

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

4. דפוסי תאריך-שעה

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

מִכְתָברכיב תאריךדוגמא
Mחוֹדֶשׁ12; דצמבר
yשָׁנָה94
דיְוֹם23; שני
השָׁעָה03
Mדַקָה57

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

"MM"

ואז התוצאה שלנו תופיע כקוד המספר - 06. עם זאת, אם נוסיף M נוסף למחרוזת התאריך שלנו:

"MMM"

ואז התאריך המעוצב שהתקבל מופיע כמילה יוני.

5. יישום מקומות

ה SimpleDateFormat גם בכיתה תומך במגוון רחב של מקומות אשר מוגדר כאשר קוראים לבנאי.

בואו לממש זאת על ידי עיצוב תאריך בצרפתית. נקים א SimpleDateFormat חפץ תוך אספקה אזור. צרפת לבנאי.

SimpleDateFormat franceDateFormatter = SimpleDateFormat חדש ("EEEEE dd-MMMMMMM-yyyy", Locale.FRANCE); תאריך myWednesday = תאריך חדש (1539341312904L); assertTrue (franceDateFormatter.format (myWednesday) .startsWith ("vendredi"));

על ידי אספקת תאריך נתון, יום רביעי אחר הצהריים, אנו יכולים לקבוע כי שלנו franceDateFormatter עיצב נכון את התאריך. התאריך החדש מתחיל כראוי עם ונדרדי -צרפתית ליום רביעי!

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

6. שינוי אזורי זמן

מאז SimpleDateFormat מרחיב את פורמט תאריך בכיתה, אנחנו יכולים גם לתפעל את אזור הזמן באמצעות setTimeZone שיטה. בואו נסתכל על זה בפעולה:

תאריך עכשיו = תאריך חדש (); SimpleDateFormat simpleDateFormat = SimpleDateFormat חדש ("EEEE dd-MMM-yy HH: mm: ssZ"); simpleDateFormat.setTimeZone (TimeZone.getTimeZone ("אירופה / לונדון")); logger.info (simpleDateFormat.format (עכשיו)); simpleDateFormat.setTimeZone (TimeZone.getTimeZone ("אמריקה / ניו_יורק")); logger.info (simpleDateFormat.format (עכשיו));

בדוגמה שלעיל אנו מספקים את אותו הדבר תַאֲרִיך לשני אזורי זמן שונים באותו SimpleDateFormat לְהִתְנַגֵד. הוספנו גם את דמות 'Z' עד סוף התבנית חוּט כדי לציין את ההבדלים באזור הזמן. התפוקה מה- פוּרמָט לאחר מכן נרשמת שיטת המשתמש.

בהרצה להכות נוכל לראות את הזמנים הנוכחיים ביחס לשני אזורי הזמן:

מידע: יום שישי 12-אוקטובר -18 12: 46: 14 + 0100 מידע: יום שישי 12-אוקטובר -18 07: 46: 14-0400

7. סיכום

במדריך זה, צללנו לעומק את המורכבויות של SimpleDateFormat.

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

שיחקנו איתו שינוי המקומות של הפלט מחרוזת לפני שנסיים סוף סוף באמצעות אזורי זמן.

כמו תמיד ניתן למצוא את קוד המקור השלם ב- GitHub.