Java 日期時間處理

來源:互聯網
上載者:User

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含義上同.
/** * Created by jifang on 15/12/30. */public class DateTest {    @Test    public void test() {        Date dateBefore = new Date();        Date dateAfter = new Date(System.currentTimeMillis() + 1);        System.out.println("before: " + dateBefore.getTime());        System.out.println("after: " + dateAfter.getTime());        System.out.println(dateBefore.before(dateAfter));        System.out.println(dateAfter.after(dateBefore));        dateBefore.setTime(System.currentTimeMillis());        System.out.println(dateBefore.getTime());        System.out.println(dateBefore.before(dateAfter));    }}
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自由轉換.
public class CalendarTest {    @Test    public void test() {        Calendar calendar = Calendar.getInstance();        Date date = calendar.getTime();        Calendar newCalendar = Calendar.getInstance();        newCalendar.setTime(date);        System.out.println(calendar.get(Calendar.DATE));    }}
Calendar類提供了大量訪問/修改日期/時間的方法, 常用的方法如下:
Method Description
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時才會重新計算日曆時間.
public int get(int field){    complete();    return internalGet(field);}
public long getTimeInMillis() {    if (!isTimeSet) {        updateTime();    }    return time;}

測試

public class CalendarTest {    @Test    public void test() {        Calendar calendar = Calendar.getInstance();        calendar.set(2011, Calendar.JULY, 31);        calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);        // 將下面注釋放開, 再測試        // System.out.println(calendar.get(Calendar.MONTH) + 1 + "月" + calendar.get(Calendar.DATE) + "日");        calendar.set(Calendar.DATE, 5);        System.out.println(calendar.get(Calendar.MONTH) + 1 + "月" + calendar.get(Calendar.DATE) + "日");    }}
日期格式化

完成字串與日期對象的轉化(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不是Regex,而是一個日期模板字串.

/** * Created by jifang on 15/12/30. */public class FormatTest {    @Test    public void client() throws ParseException {        DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");        // Date -> String        Date date = new Date(System.currentTimeMillis());        System.out.println(format.format(date));        // String -> Date        String 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我們還可以根據我們的需求有其他的定製形式:

    @Test    public void client() throws ParseException {        DateFormat format = new SimpleDateFormat("yy年MM月dd日 hh時mm分ss秒");        // Date -> String        Date date = new Date(System.currentTimeMillis());        System.out.println(format.format(date));        // String -> Date        String timeString = "15年12月30日 09時00分29秒";        Date newDate = format.parse(timeString);        System.out.println(newDate);    }

可以看出SimpleDateFormat把日期格式化成怎樣的字串以及能把怎樣的字串解析成Date, 完全取決於建立對象時指定的pattern參數,其他的pattern參數以及SimpleDateFormat的方法可以參考JDK文檔.

資料庫儲存時間實戰

由於時間儲存會涉及到跨時區的問題(同一個UTC時間在各個時區顯示的是不同的數值).因此,在我們向資料庫中插入時間是需要小心謹慎,不能簡單單單的使用資料庫提供的TIMESTAMP或是DATETIME 類型,比較推薦的是選用一個整數類型(如BIGINT64位與Java的Long類型相同),來儲存從`1970-01-01 00:00:00到時間點所經過的毫秒數(具體原因詳見:如何正確地處理時間).

這樣做的優點是:讀取時間時(一個Long類型整數),只需要按照使用者的時區格式化為字串就能正確地顯示出來. 當然這樣做也存在缺陷,那就是當我們開發人員/DB直接查看資料庫時,看到的只是一串數字,並不能清楚的知曉其對應的時間日期.

上面講完了資料庫該如何儲存時間值,下面我們再聊一聊時間[存入/讀出]資料庫的轉化問題:

從Date轉換成Long 很簡單:
Date date = new Date();long time = date.getTime();
從Long轉換成一個時間的String我們需要SimpleDateFormat的一個方法:
// Formats an object to produce a string.| Object -> StringString format(Object obj);
// 當然pattern字串可以指定為其他值String time = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(System.currentTimeMillis());
配置單例Formatter

由於在一個項目中時間格式化和解析的格式一般只有一種(我們應該不希望格式化之後的time到最後反而解析不出來),因此我們沒有必要每次使用時都new出一個Formatter來,這樣不光會造成效能下降還有可能造成時間形式不統一而出錯.因此,我們可以在Sring的容器中裝載一個Formatter Bean,使用時@Autowired就可以了:

@Autowiredprivate DateFormat dateFormatter;...String time = dateFormatter.format(System.currentTimeMillis());

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.