Java-Calendar
Calendar 在 Java 中是一個抽象類(Abstract Class),GregorianCalendar 是它的一個具體實現。
Calendar 與 Date 的轉換
Calendar calendar = Calendar.getInstance();
// 從一個 Calendar 對象中獲取 Date 對象
Date date = calendar.getTime();
// 將 Date 對象反應到一個 Calendar 對象中,
// Calendar/GregorianCalendar 沒有構造函數可以接受 Date 對象
// 所以我們必需先獲得一個實例,然后設置 Date 對象
calendar.setTime(date);
格式化:SimpleDateFormat
SimpleDateFormat是非線程安全的。format函數使用了內部變量。
public StringBuffer format(Date date, StringBuffer toAppendTo,FieldPosition pos){// 如此輕易地使用內部變量,肯定不能線程安全// 線程都對pos進行寫操作,必然會影響其他線程的讀操作pos.beginIndex = pos.endIndex = 0;return format(date, toAppendTo, pos.getFieldDelegate());}解決方法
- 定義成局部變量
- 加鎖
- 定義成ThreadLocal變量
?
格式定義:
| Letter? | Date or Time Component? | Presentation? | Examples |
| G? | Era designator? | Text? | AD |
| y? | Year? | Year? | 1996; 96 |
| Y? | Week year? | Year? | 2009; 09 |
| M? | Month in year (context sensitive)? | Month? | July; Jul; 07 |
| L? | Month in year (standalone form)? | Month? | July; Jul; 07 |
| w? | Week in year? | Number? | 27 |
| W? | Week in month? | Number? | 2 |
| D? | Day in year? | Number? | 189 |
| d? | Day in month? | Number? | 10 |
| F? | Day of week in month? | Number? | 2 |
| E? | Day name in week? | Text? | Tuesday; Tue |
| u? | Day number of week (1 = Monday, ..., 7 = Sunday)? | Number? | 1 |
| a? | Am/pm marker? | Text? | PM |
| H? | Hour in day (0-23)? | Number? | 0 |
| k? | Hour in day (1-24)? | Number? | 24 |
| K? | Hour in am/pm (0-11)? | Number? | 0 |
| h? | Hour in am/pm (1-12)? | Number? | 12 |
| m? | Minute in hour? | Number? | 30 |
| s? | Second in minute? | Number? | 55 |
| S? | Millisecond? | Number? | 978 |
| z? | Time zone? | General time zone? | Pacific Standard Time; PST; GMT-08:00 |
| Z? | Time zone? | RFC 822 time zone? | -800 |
| X? | Time zone? | ISO 8601 time zone? | -08; -0800; -08:00 |
?
| "yyyy.MM.dd G 'at' HH:mm:ss z" | 2001.07.04 AD at 12:08:56 PDT |
| "EEE, MMM d, ''yy" | Wed, Jul 4, '01 |
| "h:mm a" | 12:08 PM |
| "hh 'o''clock' a, zzzz" | 12 o'clock PM, Pacific Daylight Time |
| "K:mm a, z" | 0:08 PM, PDT |
| "yyyyy.MMMMM.dd GGG hh:mm aaa" | 02001.July.04 AD 12:08 PM |
| "EEE, d MMM yyyy HH:mm:ss Z" | Wed, 4 Jul 2001 12:08:56 -0700 |
| "yyMMddHHmmssZ" | 010704120856-0700 |
| "yyyy-MM-dd'T'HH:mm:ss.SSSZ" | 2001-07-04T12:08:56.235-0700 |
| "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" | 2001-07-04T12:08:56.235-07:00 |
| "YYYY-'W'ww-u" | 2001-W27-3 |
注意事項
set方法
set(int field, int value) - 是用來設置"年/月/日/小時/分鐘/秒/微秒"等值
set(int year, int month, int date)
set(int year, int month, int date, int hourOfDay, int minute)
- 僅會修改涉及到的時間域,未涉及到的時間域,不做任何更改(例如設置為0)
- 月份起始值從0開始,例如1月要設置為0,2月設置為2。
- 如果時間域溢出,會導致高位時間域改變。例如設置2019.05.31的月份為6月,則日期變為:2019.07.01(6月沒有31日)。
- 使用poll方法,則不會導致高位時間域修改。例如2019.03.31,設置為2月,則不會變為2019.03.03,而是2019.02.28
- set方法是延緩計算的。僅在調用getTime時計算。即設置了月份,日期等,不立即計算。例如2019.03.31設置月份為2月,日期為1日,則是2019.02.01,而不是先變為2019.03.03,再變為2019.03.01.
Calendar 對象的容錯性
當設置Lenient為true時,如果時間域設置超過范圍,則自動調整。
當設置Lenient為false時,如果時間域設置超過范圍,則拋出異常。
序列化
Calendar序列化時,僅保存相對于EPOCH的時間差,反序列化時通過此值計算。
set方法延遲計算,如果set之后立即序列化,則時間差未重新計算。導致值是錯誤,因此序列化前要調用getTime,強制更新時間差。
add() 與 roll() 的區別
add() 的功能非常強大,add 可以對 Calendar 的字段進行計算。如果需要減去值,那么使用負數值就可以了,如 add(field, -value)。
add() 有兩條規則:
- 當被修改的字段超出它可以的范圍時,那么比它大的字段會自動修正。如:
Calendar cal1 = Calendar.getInstance();
cal1.set(2000, 7, 31, 0, 0 , 0); //2000-8-31
cal1.add(Calendar.MONTH, 1); //2000-9-31 => 2000-10-1,對嗎?
System.out.println(cal1.getTime()); //結果是 2000-9-30
- 如果比它小的字段未做改變的(由 Calendar 的實現類決定),那么該小字段會修正到變化最小的值。
以上面的例子,9-31 就會變成 9-30,因為變化最小。
Roll() 的規則只有一條:
- 當被修改的字段超出它可以的范圍時,那么比它大的字段不會被修正。如:
Calendar cal1 = Calendar.getInstance();
cal1.set(1999, 5, 6, 0, 0, 0); //1999-6-6, 周日
cal1.roll(Calendar.WEEK_OF_MONTH, -1); //1999-6-1, 周二
cal1.set(1999, 5, 6, 0, 0, 0); //1999-6-6, 周日
cal1.add(Calendar.WEEK_OF_MONTH, -1); //1999-5-30, 周日
WEEK_OF_MONTH 比 MONTH 字段小,所以 roll 不能修正 MONTH 字段。
?
?
總結
以上是生活随笔為你收集整理的Java-Calendar的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JDK8-time
- 下一篇: JVM-Java内存区域