Java 中的日期与时间
Java 日期時間
標簽 : Java基礎
Date
java.util.Date對象表示一個精確到毫秒的瞬間; 但由于Date從JDK1.0起就開始存在了,歷史悠久,而且功能強大(既包含日期,也包含時間),所以他的大部分構造器/方法都已Deprecated,因此就不再推薦使用(如果貿然使用的話,可能會出現性能/安全方面的問題);下面我僅介紹它還剩下的為數不多的幾個方法(這些方法的共同點是Date與毫秒值的轉換):
構造器
- Date(): 在底層調用System.currentTimeMillis()作為日期參數.
- Date(long date): 根據指定的long整數(從1970-1-1 00:00:00以來經過的毫秒數)來生成Date對象.
方法
- boolean after(Date when): 測試this日期是否在指定日期when之后;
- boolean before(Date when): 測試this日期是否在指定日期when之前;
- long getTime(): 獲取從1979-01-01 00:00:00 到Date對象之間經過的毫秒值;
- void setTime(long time): 設置時間,time含義上同.
Calendar
由于Date存在缺陷,所以JDK又提供了java.util.Calendar來處理日期和時間.Calendar是一個抽象類,是所有日歷類的模板,因此,我們可以繼承Calendar來實現其他的歷法(比如陰歷);
Java中提供了一種Calendar的默認實現java.util.GregorianCalendar格里高利日歷(其實JDK還默認提供了一款日本歷法java.util.JapaneseImperialCalendar),也就是我們所說的公歷. 使用Calendar.getInstance();獲取的就是默認的GregorianCalendar,getInstance()方法的內部會調用cal = new GregorianCalendar(zone, aLocale);來生成一個格里高利日歷實例.
- Calendar還可以和Date自由轉換.
- Calendar類提供了大量訪問/修改日期/時間的方法, 常用的方法如下:
| void add(int field, int amount) | Adds or subtracts the specified amount of time to the given calendar field, based on the calendar’s rules. |
| int get(int field) | Returns the value of the given calendar field. |
| int getActualMaximum(int field) | Returns the maximum value that the specified calendar field could have, given the time value of this Calendar. |
| int getActualMinimum(int field) | Returns the minimum value that the specified calendar field could have, given the time value of this Calendar. |
| void roll(int field, int amount) | Adds the specified (signed) amount to the specified calendar field without changing larger fields. |
| void set(int field, int value) | Sets the given calendar field to the given value. |
| void set(int year, int month, int date) | Sets the values for the calendar fields YEAR, MONTH, and DAY_OF_MONTH. |
| void set(int year, int month, int date, int hourOfDay, int minute, int second) | Sets the values for the fields YEAR, MONTH, DAY_OF_MONTH, HOUR, MINUTE, and SECOND. |
| void setTimeInMillis(long millis) | Sets this Calendar’s current time from the given long value. |
| long getTimeInMillis() | Returns this Calendar’s time value in milliseconds. |
上面的很多方法都需要一個int類型的field參數, field是Calendar類的類變量, 如:Calendar.DATE Calendar.MONTH Calendar.HOUR Calendar.DAY_OF_WEEK, 但需要指出的是Calendar.MONTH月份的起始值不是1, 而是0(一月:0, 二月:1 …), Calendar.DAY_OF_WEEK代表的星期, 起始值是周日(周日:1, 周一:2 …)(其他細節請參考JDK文檔).
注意:
- 如果Calendar沒有設置相關的值, 就以當前系統時間來設置.
- add(int field, int amount)的功能非常強大, 如果需要增加某字段, 則讓amount為正數, 如果要減少某字段的值, 讓amount為負數. 且當超出他的允許范圍時, 會發生進位.
- roll()的含義與用法和add()的類似,但是當被修改的字段超出它允許的范圍時, 他不會進位.
- set(int field, int value)方法具有延遲修改的功能:他內部設置了一個成員變量,以指示日歷字段field已經被修改,但是該Calendar所代表的時間不會立即修改, 他會直到下次調用get/getTime/getTimeInMillis/add/roll時才會重新計算日歷時間.
- 測試
日期格式化
完成字符串與日期對象的轉化(format/parse)
DateFormat
java.text.DateFormat是一個抽象類, 他提供了如下幾個方法獲取DateFormat對象.
| static DateFormat getDateInstance() | Gets the date formatter with the default formatting style for the default locale. |
| static DateFormat getDateTimeInstance() | Gets the date/time formatter with the default formatting style for the default locale. |
| static DateFormat getTimeInstance() | Gets the time formatter with the default formatting style for the default locale. |
其實上面三個方法還可以指定日期/時間的樣式, 如FULL/LONG/MEDIUM/SHOT, 通過這四個樣式參數可以控制生成的格式化字符串. 但由于在我們的實際開發中很少直接用DateFormat類,因此就不對其做過多的介紹.而我們比較常用的是其子類SimpleDateFormat(其實上面幾個getXxxInstance方法返回的也是SimpleDateFormat實例)
DateFormat dateFormat = DateFormat.getTimeInstance(); System.out.println(dateFormat.getClass().getName());SimpleDateFormat
java.text.SimpleDateFormat可以非常靈活的格式化Date, 也可以用于解析各種格式的日期字符串.創建SimpleDateFormat對象時需要傳入一個pattern字符串,這個pattern不是正則表達式,而是一個日期模板字符串.
/*** Created by jifang on 15/12/30.*/ public class FormatTest {@Testpublic void client() throws ParseException {DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");// Date -> StringDate date = new Date(System.currentTimeMillis());System.out.println(format.format(date));// String -> DateString timeString = "2015-12-30 08:53:21";Date newDate = format.parse(timeString);System.out.println(newDate);} }在時間日期格式化時, 有下面幾個方法是最常用的:
| String format(Date date) | Formats a Date into a date/time string. | Date -> String |
| Date parse(String source) | Parses text from the beginning of the given string to produce a date. | String -> Date |
當然, pattern我們還可以根據我們的需求有其他的定制形式:
@Testpublic void client() throws ParseException {DateFormat format = new SimpleDateFormat("yy年MM月dd日 hh時mm分ss秒");// Date -> StringDate date = new Date(System.currentTimeMillis());System.out.println(format.format(date));// String -> DateString timeString = "15年12月30日 09時00分29秒";Date newDate = format.parse(timeString);System.out.println(newDate);}可以看出SimpleDateFormat把日期格式化成怎樣的字符串以及能把怎樣的字符串解析成Date, 完全取決于創建對象時指定的pattern參數,其他的pattern參數以及SimpleDateFormat的方法可以參考JDK文檔.
實戰
時間存儲
將時間存入DB會涉及到跨時區的問題(同一個UTC時間在各個時區顯示不同的數值).因此,在設計數據庫表結構時需要小心謹慎,不能簡單使用數據庫提供的TIMESTAMP或DATETIME(詳見:廖雪峰博客-如何正確地處理時間),比較推薦的是選用一個整數類型(如BIGINT64位)來存儲從1970-01-01 00:00:00到當前時間所經過毫秒數的一個絕對數值.
- 優點:
讀取的時間(Long整數)只需要按照用戶所在的時區格式化為字符串就能正確地顯示出來. - 缺點
當開發人員、DBA直接查看DB時,只能看到一串數字.
線程安全formatter
時間的格式化和解析格式在一個項目中往往只用一種,因此沒有必要每次使用時都new出一個Formatter來. 但SimpleDateFormat的format()與parse()并非線程安全(詳見: 關于SimpleDateFormat的非線程安全問題及其解決方案), 因此在并發環境中要注意同步或使用ThreadLocal控制:
- DateUtil
總結
以上是生活随笔為你收集整理的Java 中的日期与时间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 选择云备份:应当怎样和云供应商签合同
- 下一篇: Java矩阵类库