java.util.Date
是一個“萬能接口”,它包含日期、時間,還有毫秒數,如果你只想用java.util.Date
存儲日期,或者只存儲時間,那麼,只有你知道哪些部分的數據是有用的,哪些部分的數據是不能用的。
1.1 Date的構造方法
Date 是我們使用的最多的一個日期類,Date提供的構造方法在官方API中有一下幾種:
Date 類提供了多種構造方法,但是目前有很多方法都已經不建議使用
public Date() { this(System.currentTimeMillis()); } public Date(long date) { fastTime = date; } @Deprecated public Date(int year, int month, int date) { this(year, month, date, 0, 0, 0); } @Deprecated public Date(int year, int month, int date, int hrs, int min) { this(year, month, date, hrs, min, 0); } @Deprecated public Date(int year, int month, int date, int hrs, int min, int sec) @Deprecated public Date(String s) { this(parse(s)); }
目前我們可以通過使用:
Date date0 = new Date(); Date date1 = new Date(time);
這兩種方法創建對象的不同主要是通過指定的時間戳不同,通過設置Date 中的 fastTime 進行設置Date 對象的時間。
除了使用構造方法獲取實例,Date 還可以通過 Instant 來創建一個Date 實例:
Instant instant = Instant.now(); Date date = Date.from(instant);
Instant 是Java 8 提供的新特性:
1.2 Date的常用方法
Date 類中,提供了常用的獲取:年,月,日,時,分,秒等方法:
Date date = new Date(); int dates = date.getDate(); int year = date.getYear(); int month = date.getMonth(); int day = date.getDay(); int hours = date.getHours(); int min = date.getMinutes(); int second = date.getSeconds(); long time = date.getTime(); int times = date.getTimezoneOffset();
輸出結果:
dates: 14 year: 116 month: 11 day: 3 hours: 15 min: 8 second: 29 time: 1481699309422 times: -480
讀者可能會發現,這裡的年份並不是我們想要的,這裡主要是因為代碼方法實現:
我們可以看到,這裡的getYear 並不是獲取當前年份,而是獲取到和1900年的差值,這裡主要是因為JDK老版本遺留下來的問題,對於Date 中獲取年月日的方法,現在已經不建議使用了。
Date類中也提供了一些設置日期的方法:
與上面的get方法是一一對應的,但是現在也同樣不建議使用了。
1.3 Date的總結
經過我們上述的分析,我們發現,Date 類如今很多方法已經沒有什麼用處了,確實,如今時間的處理並不直接在Date 類中進行,而是通過Calendar,或者LocalDate 來進行,我們再日常使用中,更多的是要來做一個記錄日期的實例。
介紹一下Date 與 Calendar 的區別
Date用於記錄某一個含日期的、精確到毫秒的時間。重點在代表一剎那的時間本身。
Calendar用於將某一日期放到歷法中的互動——時間和年、月、日、星期、上午、下午、夏令時等這些歷法規定互相作用關系和互動。Calendar本身代表公歷的一個簡化縮水版,姑且叫“計算機歷”。
完整的公歷是格裡高利歷,Java SE中以GregorianCalendar類來提供相關的歷法功能。
2.1 Calendar 的構造方法
我們可以看到,Calendar 中的構造方法被封裝在包中,我們無法直接通過構造方法來創建一個新的實例對象,我們只能通過調用 Calendar中的靜態方法 Calendar.getInstance()方法獲取一個實例對象。
我們看一下官方API 中提供了哪些方法獲取Calendar 對象:
這是官方文檔給出的獲取去對象實例的方法,我們可以看到,我們可以通過指定TimeZone 和 Locale 來獲取特定的 Calendar 對象,這也卻分了每個地區的時間日歷,方便開發者使用
除了通過getInstance() 方法獲取實例以外,Java 1.8 提供了一個內部類:
我們可以通過創建一個Builder 的實體,然後通過調用Build 方法獲取一個 Calendar 實例。
在Builder 中,Builder 類提供了設置年月日的方法,可以通過設置時間,來獲取特定的Calendar 對象。
Calendar.Builder builder =new Calendar.Builder(); Calendar calendar1 = builder.build(); Date date = calendar.getTime();
這裡總結一下:
Calendar 提供的獲取實例的方法主要有兩種途徑:
1、調用Calendar.getInstance()方法
2、創建內部類Builder 的實例,通過調用其 build()方法創建 Calendar 實例
對於第一種方法,只能先獲取當前時間的Calendar,然後再通過調用相應的set 方法設置年月日等,而如果使用內部類Builder 方法,可以通過setInstant 方法設置我們所期望的時間。
2.2 Calendar 的常用方法
我們最常用的方法有:
Calendar calendar = Calendar.getInstance(); Date date = calendar.getTime();
通過Calendar 方法獲取一個Date 的實例。
Calendar 方法獲取年月日的方法:
int year =calendar.get(Calendar.YEAR); int month=calendar.get(Calendar.MONTH)+1; int day =calendar.get(Calendar.DAY_OF_MONTH); int hour =calendar.get(Calendar.HOUR_OF_DAY); int minute =calendar.get(Calendar.MINUTE); int seconds =calendar.get(Calendar.SECOND);
我們可以看到Calendar 裡面獲取年月日不像上面 Date 類中的通過訪問各個方法來獲取。
Calendar 在初始化的時候,就已經將年月日劃分好,並且存入fields 變量中。我們只需要傳入���個位置編號,就可以獲取我們需要的信息
除了獲取以外,Calendar 也提供了相應的set 方法:
通過重新傳入參數,設置Calendar 的時間
Calendar 獲取當前月份,當前星期的最大\小天數
System.out.println(calendar.getActualMaximum(Calendar.DAY_OF_WEEK)); System.out.println(calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); System.out.println(calendar.getActualMinimum(Calendar.DAY_OF_WEEK)); System.out.println(calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
提供了Before 和After 兩個方法,用於判斷當前時間與對比時間先後:
提供了add 方法進行日期的加減
calendar.add(10,10);
2.3 Calendar 的總結
從上面的分析我們可以看到,Calendar 類 主要是用於作為日歷的對象,可以銅鼓哦設置地區時間,區分每個地區的日期,Calendar 提供的方法也沒有很多對時間進行的一些操作。
Java 8新增了LocalDate
和LocalTime
接口,為什麼要搞一套全新的處理日期和時間的API?因為舊的java.util.Date
實在是太難用了。
java.util.Date
月份從0
開始,一月是0
,十二月是11
,變態吧!java.time.LocalDate
月份和星期都改成了enum
,就不可能再用錯了。
java.util.Date
和SimpleDateFormatter
都不是線程安全的,而LocalDate
和LocalTime
和最基本的String
一樣,是不變類型,不但線程安全,而且不能修改。
3.1 LocalDate/LocalTime 的構造方法
3.1.1 LocalDate 的構造方法:
LocalDate 並沒有提供公開的構造方法,只提供了一個封裝的構造方法供內部使用。
private LocalDate(int year, int month, int dayOfMonth) { this.year = year; this.month = (short) month; this.day = (short) dayOfMonth; }
LocalDate 提供了三種創建實例的方法:
//獲取當前時間的LocalDate LocalDate localDate = LocalDate.now(); //獲取指定年、月、日 的 LocalDate LocalDate ofDate = LocalDate.of(2016,12,31); //通過解析字符串獲取 LocalDate,如果格式不對會拋出 DateTimeParseException LocalDate parseDate = LocalDate.parse("2016-12-31-");
3.1.2 LocalTime 的構造方法:
LocalTime 與LcoalDate 一樣,提供了一個封裝的構造方法:
private LocalTime(int hour, int minute, int second, int nanoOfSecond) { this.hour = (byte) hour; this.minute = (byte) minute; this.second = (byte) second; this.nano = nanoOfSecond; }
LocalTime 提供了三種創建方法:
LocalTime localTime = LocalTime.now().withNano(0); LocalTime ofTime = LocalTime.of(16,30,25); LocalTime parseTime = LocalTime.parse("12:00:01");
3.2 LocalDate/LocalTime 的常用方法
獲取當天的起始時間:atStartOfDay()
LocalDate localDate = LocalDate.now(); LocalDateTime date = localDate.atStartOfDay(); 輸出: 2016-12-14T00:00
設置當前日期的時間:atTime()
LocalDate localDate = LocalDate.now(); LocalDateTime date = localDate.atTime(16,25,30); 輸出: 2016-12-14T16:25:30
格式轉換:format()
常用的獲取年、月、日 等方法
int year = localDate.getYear(); int month = localDate.getMonthValue(); int day = localDate.getDayOfMonth();
獲取改變月份的LocalDate :withMonth()
LocalDate localDate = LocalDate.now(); LocalDate d = localDate.withMonth(10);
其他常用的日期轉換:
// 取本月第1天: LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2014-12-01 // 取本月第2天: LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2014-12-02 // 取本月最後一天,再也不用計算是28,29,30還是31: LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2014-12-31 // 取下一天: LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // 變成了2015-01-01 // 取2015年1月第一個周一,這個計算用Calendar要死掉很多腦細胞: LocalDate firstMondayOf2015 = LocalDate.parse("2015-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2015-01-05
3.3 LocalDate/LocalTime 的總結
在新的Java 8中,日期和時間被明確劃分為LocalDate
和LocalTime
,LocalDate
無法包含時間,LocalTime
無法包含日期。當然,LocalDateTime
才能同時包含日期和時間。
新接口更好用的原因是考慮到了日期時間的操作,經常發生往前推或往後推幾天的情況。用java.util.Date
配合Calendar
要寫好多代碼,而且一般的開發人員還不一定能寫對。