Java8之日期和時間(四)
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
一樣,是不變型別,不但執行緒安全,而且不能修改。
java.util.Date
是一個“萬能介面”,它包含日期、時間,還有毫秒數,如果你只想用java.util.Date
LocalDate
和LocalTime
,LocalDate
無法包含時間,LocalTime
無法包含日期。當然,LocalDateTime
才能同時包含日期和時間。新介面更好用的原因是考慮到了日期時間的操作,經常發生往前推或往後推幾天的情況。用java.util.Date
配合Calendar
要寫好多程式碼,而且一般的開發人員還不一定能寫對。
LocalDate、 LocalTime、LocalDateTime 類的例項是分別表示使用ISO-8601日曆系統的日期、時間、日期和時間。它們提供了簡單的日期或時間,並不包含當前的時間資訊。也不包含與時區相關的資訊。
1. LocalDate
看看新的LocalDate
怎麼用:
// 取當前日期:
LocalDate today = LocalDate.now(); // -> 2014-12-24
// 根據年月日取日期,12月就是12:
LocalDate crischristmas = LocalDate.of(2014, 12, 25); // -> 2014-12-25
// 根據字串取:
LocalDate endOfFeb = LocalDate.parse("2014-02-28"); // 嚴格按照ISO yyyy-MM-dd驗證,02寫成2都不行,當然也有一個過載方法允許自己定義格式
LocalDate.parse("2014-02-29" ); // 無效日期無法通過:DateTimeParseException: Invalid date
日期轉換經常遇到,比如:
// 取本月第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
2. LocalTime
LocalTime
只包含時間,以前用java.util.Date
怎麼才能只表示時間呢?答案是,假裝忽略日期。
LocalTime
包含毫秒:
LocalTime now = LocalTime.now(); // 11:09:09.240
你可能想清除毫秒數:
LocalTime now = LocalTime.now().withNano(0)); // 11:09:09
構造時間也很簡單:
LocalTime zero = LocalTime.of(0, 0, 0); // 00:00:00
LocalTime mid = LocalTime.parse("12:00:00"); // 12:00:00
時間也是按照ISO格式識別,但可以識別以下3種格式:
- 12:00
- 12:01:02
- 12:01:02.345
JDBC
最新JDBC對映將把資料庫的日期型別和Java 8的新型別關聯起來:
SQL -> Java
--------------------------
date -> LocalDate
time -> LocalTime
timestamp -> LocalDateTime
再也不會出現對映到java.util.Date
其中日期或時間某些部分為0
的情況了。
3.LocalDateTime
LocalDateTime類是Java 8中日期時間功能裡,用於表示當地的日期與時間的類,它的值是無時區屬性的。你可以將其視為Java 8中LocalDate與LocalTime兩個類的結合。LocalDateTime類的值是不可變的,所以其計算方法會返回一個新的LocalDateTime例項。
建立一個LocatDateTime例項
可以通過LocalDateTime的靜態工廠方法來建立LocalDateTime例項。以下舉例使用now()方法建立: LocalDateTime localDateTime = LocalDateTime.now();
另一種方式是使用指定的年月日、時分秒、納秒來新建物件: LocalDateTime localDateTime2 = LocalDateTime.of(2015, 11, 26, 13, 55, 36, 123);
示例:
@Test
public void test1(){
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
LocalDateTime ld2 = LocalDateTime.of(2016, 11, 21, 10, 10, 10);
System.out.println(ld2);
LocalDateTime ldt3 = ld2.plusYears(20);
System.out.println(ldt3);
LocalDateTime ldt4 = ld2.minusMonths(2);
System.out.println(ldt4);
System.out.println(ldt.getYear());
System.out.println(ldt.getMonthValue());
System.out.println(ldt.getDayOfMonth());
System.out.println(ldt.getHour());
System.out.println(ldt.getMinute());
System.out.println(ldt.getSecond());
}
4.Instant : 時間戳
用於“時間戳”的運算。它是以Unix元年(傳統的設定為UTC時區1970年1月1日午夜時分)開始所經歷的描述進行運算
@Test
public void test2(){
Instant ins = Instant.now(); //預設使用 UTC 時區
System.out.println(ins);
OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
System.out.println(odt);
System.out.println(ins.getNano());
Instant ins2 = Instant.ofEpochSecond(5);
System.out.println(ins2);
}
5.Duration 和 Period
Duration:用於計算兩個“時間”間隔
Period:用於計算兩個“日期”間隔
//Duration : 用於計算兩個“時間”間隔
//Period : 用於計算兩個“日期”間隔
@Test
public void test3(){
Instant ins1 = Instant.now();
System.out.println("--------------------");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
Instant ins2 = Instant.now();
Duration duration=Duration.between(ins1, ins2);
System.out.println( duration);
System.out.println( duration.getNano());
System.out.println( duration.getSeconds());
System.out.println( duration.getUnits());
System.out.println("----------------------------------");
LocalDate ld1 = LocalDate.now();
LocalDate ld2 = LocalDate.of(2011, 1, 1);
Period pe = Period.between(ld2, ld1);
System.out.println(pe.getYears());
System.out.println(pe.getMonths());
System.out.println(pe.getDays());
}
6.日期的操縱
TemporalAdjuster :時間校正器。有時我們可能需要獲取例如:將日期調整到“下個週日”等操作。
TemporalAdjusters: 該類通過靜態方法提供了大量的常用TemporalAdjuster 的實現
TemporalAdjuster : 時間校正器
@Test
public void test4(){
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
LocalDateTime ldt2 = ldt.withDayOfMonth(10);
System.out.println(ldt2);
LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(ldt3);
//自定義:下一個工作日
LocalDateTime ldt5 = ldt.with((l) -> {
LocalDateTime ldt4 = (LocalDateTime) l;
DayOfWeek dow = ldt4.getDayOfWeek();
if(dow.equals(DayOfWeek.FRIDAY)){
return ldt4.plusDays(3);
}else if(dow.equals(DayOfWeek.SATURDAY)){
return ldt4.plusDays(2);
}else{
return ldt4.plusDays(1);
}
});
System.out.println(ldt5);
}
7.解析與格式化
java.time.format.DateTimeFormatter 類:該類提供了三種
格式化方法:
預定義的標準格式
語言環境相關的格式
自定義的格式
@Test
public void test5(){
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");
LocalDateTime ldt = LocalDateTime.now();
String strDate = ldt.format(dtf);
System.out.println(strDate);
LocalDateTime newLdt = ldt.parse(strDate, dtf);
System.out.println(newLdt);
}
8.時區的處理
Java8 中加入了對時區的支援,帶時區的時間為分別為:ZonedDate、 ZonedTime、 ZonedDateTime
其中每個時區都對應著 ID,地區ID都為 “{區域}/{城市}”的格式
例如 : Asia/Shanghai 等
ZoneId:該類中包含了所有的時區資訊
getAvailableZoneIds() : 可以獲取所有時區時區資訊
of(id) : 用指定的時區資訊獲取 ZoneId 物件
@Test
public void test7(){
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(ldt);
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("US/Pacific"));
System.out.println(zdt);
}
https://www.cnblogs.com/exmyth/p/6425878.html