JAVA JDK8新特性:時間相關API

背景

Java 8 推出了全新的日期時間API,在教程中我們將通過一些簡單的實例來學習如何使用新API。Java處理日期、日曆和時間的方式一直爲社區所詬病,將 java.util.Date設定爲可變類型,以及SimpleDateFormat的非線程安全使其應用非常受限。Java也意識到需要一個更好的 API來滿足社區中已經習慣了使用JodaTime API的人們。全新API的衆多好處之一就是,明確了日期時間概念,例如:瞬時(instant)、 長短(duration)、日期、時間、時區和週期。同時繼承了Joda庫按人類語言和計算機各自解析的時間處理方式。不同於老版本,新API基於ISO標準日曆系統,java.time包下的所有類都是不可變類型而且線程安全。

JDK1.8新的時間API

  • java.time - 包含值對象的基礎包
  • java.time.chrono - 提供不同日曆系統的訪問
  • java.time.format - 格式化和解析時間和日期
  • java.time.temporal - 包含底層框架和擴展特性
  • java.time.zone - 包含時區支持的類

下面是新版API中java.time包裏的一些子類:

  • LocalDate - 用來表示日期(年、月、日)
  • LocalTime - 用來表示時間(時、分、秒)
  • LocalDateTime - 用來表示日期時間(年、月、日、時、分、秒),但不包含時差和時區信息。
  • DateTimeFormatter - 用來格式化日期.
  • Instant - 瞬時實例。
  • ZonedDateTime - 最完整的日期時間,包含時區和相對UTC或格林威治的時差。
  • OffsetDateTime - 實際上組合了LocalDateTime類和ZoneOffset類。用來表示包含和格林威治或UTC時差的完整日期(年、月、日)和時間(時、分、秒、納秒)信息。

新API還引入了ZoneOffSet和ZoneId類,使得解決時區問題更爲簡便。

LocalDateTime、LocalDate、LocalTime常用方法

(1)從默認時區的系統時鐘獲取當前時間

LocalTime localtime  = LocalTime.now();
LocalDate localdate  = LocalDate.now();
LocalDateTime localdatetime  = LocalDateTime.now();

(2)從指定時區的系統時鐘獲取當前時間

LocalDate localdatenewyourk = LocalDate.now(ZoneId.of("America/New_York"));
LocalDateTime localdatetimenewyourk  = LocalDateTime.now(ZoneId.of("America/New_York"));
LocalTime localtimenewyourk = LocalTime.now(ZoneId.of("America/New_York"));

(3)of() 設置指定的年月日時分秒  體現不偏移性

LocalTime localtimeof  = LocalTime.of(1, 30);
LocalDate localdateof  = LocalDate.of(2019, 1, 20);
LocalDateTime localdatetimeof  = LocalDateTime.of(localdate, localtime);

(4) getXxx() 獲取時間的年、月、日、時、分、秒

System.out.println(localdatetimeof.getDayOfYear());
System.out.println(localdatetimeof.getDayOfMonth());
System.out.println(localdateof.getYear());
System.out.println(localdateof.getMonth());
System.out.println(localtimeof.getHour());
System.out.println(localtimeof.getMinute());

(5)isXXX() 判斷功能

System.out.println(localdateof.isLeapYear());//是否是閏年
System.out.println(localdatetimeof.isBefore(localdatetime)); 
System.out.println(localdateof.isAfter(localdateof));
System.out.println(localtimeof.equals(localtime));

(6)比較功能

//而compareTo顯示比較年份,如果年份不同,直接返回年份的差值。如果年份相同,再比較月份,如果如果月份不相同,返回月份的差值。最如果月份也相同才返回日期的差值。
System.out.println(localdatetimeof.compareTo(localdatetime)); //0

(7)獲取對象表示的年有多少天、獲取對象表示的月有多少天

System.out.println(localdateof.lengthOfMonth());//判斷這個月有多少天
System.out.println(localdateof.lengthOfYear());//該對象表示的年份有多少天(365或者366)

(8)withXXX() 設置年月日時分秒 體現不可變性

System.out.println(localdatetimeof.withHour(3));
System.out.println(localdate.withYear(1991));
System.out.println(localtime.withMinute(30));

(9)plusXXX() 當前時間做加法, minusXX()當前的時間做減法

System.out.println(localdatetime.plusDays(1));
System.out.println(localdate.plusYears(2));
System.out.println(localtime.plusHours(3));

(10)不同時間類型相互間轉換

System.out.println(localdatetime.toLocalTime());//LocalDateTime轉LocalTime
System.out.println(localdatetime.toLocalDate());//LocalDateTime轉LocalDate	
System.out.println(localdate.atTime(localtime));//LocalDate轉LocalDateTime
System.out.println(localtime.atDate(localdate));//LocalDate轉LocalDateTime

(11)LocalDate、LocalTime、LocalDateTime轉Instant:沒有方法可以直接轉Instant,只能前轉ZonedDateTime再轉Instant

Instant localDateTimeInstant = localdatetime.atZone(ZoneId.systemDefault()).toInstant();
System.out.println(localDateTimeInstant);//2019-07-02T16:17:46.131+08:00[Asia/Shanghai]

Instant:時間戳

含義:從1970-01-01 00:00:00到當前時間的毫秒值

(1)創建Instant實例

Instant ins = Instant.now();
System.out.println(ins);//2019-07-02T07:05:06.462Z

//源碼
public static Instant now() {
    return Clock.systemUTC().instant();
}

通過查看源代碼發現Instant.now()使用的是UTC時間Clock.systemUTC().instant()。LocalDate、LocalDateTime 的now()方法使用的是系統默認時區 不存在Instant.now()的時間問題。

解決方法:格式化時指定下時區即可

System.out.println(Instant.now().atZone(ZoneId.systemDefault()));//2019-07-02T16:12:44.683+08:00[Asia/Shanghai]
		

(2)Instant獲取long類型的10位秒數、13位毫秒數

System.out.println("秒數:" + ins.getEpochSecond());
System.out.println("毫秒數:" + ins.toEpochMilli());

(3)字符串轉Instant

String timestr = "2019-07-02T08:17:46.070Z";
System.out.println("String轉Instant:" + ins.parse(timestr));//String轉Instant:2019-07-02T08:17:46.070Z

(4)設置偏移量

OffsetDateTime time=ins.atOffset(ZoneOffset.ofHours(8));
System.out.println("偏移8小時後的時間是:" + time);//2019-07-02T16:41:05.196+08:00

其他很多方法功能,Instant對象的比較,時間的加減、時間的設置與LocaldateTime方法功能一樣,不詳細介紹了

TemporalAdjuster:時間校正器(接口)

(1)使用TemporalAdjusters自帶的常量來設置日期

static TemporalAdjuster	dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek)//返回月度調整器中的星期幾,該日期將在同一個月內按順序的星期幾返回新的日期。
static TemporalAdjuster	firstDayOfMonth()//返回“第一個月的”調整器,它返回設置爲當月的第一天的新日期。
static TemporalAdjuster	firstDayOfNextMonth()//返回“下一個月的第一天”調整器,它將新的日期設置爲下個月的第一天。
static TemporalAdjuster	firstDayOfNextYear()//返回“明年的第一天”調整器,返回設置爲下一年的第一天的新日期。
static TemporalAdjuster	firstDayOfYear()//返回“一年的第一天”調整器,其返回設置爲當前第一天的新日期。
static TemporalAdjuster	firstInMonth(DayOfWeek dayOfWeek)//返回月初調整器,它在同一個月內返回與第一個匹配的星期幾的新日期。
static TemporalAdjuster	lastDayOfMonth()//返回“最後一個月的”調整器,該日期設置爲當前月份的最後一天。
static TemporalAdjuster	lastDayOfYear()//返回“最後一天的”調整器,其返回設置爲當前年份的最後一天的新日期。
static TemporalAdjuster	lastInMonth(DayOfWeek dayOfWeek)//返回最近一個月的調整器,它返回與最後一個匹配的星期幾相同月份的新日期。
static TemporalAdjuster	next(DayOfWeek dayOfWeek)//返回下一個星期的調整器,該調整器將日期調整爲在調整日期之後的指定日期的第一次出現。
static TemporalAdjuster	nextOrSame(DayOfWeek dayOfWeek)//返回下一個或相同的星期幾調整器,該調整器將日期調整爲在調整日期之後指定的星期幾的第一次出現,除非它已在當天在同一對象被返回。
static TemporalAdjuster	ofDateAdjuster(UnaryOperator<LocalDate> dateBasedAdjuster)//獲取一個包含日期調整器的 TemporalAdjuster 。
static TemporalAdjuster	previous(DayOfWeek dayOfWeek)//返回上一個星期的調整器,該調整器將日期調整爲在調整日期之前的指定日期的第一次出現。
static TemporalAdjuster	previousOrSame(DayOfWeek dayOfWeek)//返回之前或相同的日期調整器,該調整器將日期調整爲在調整日期之前的指定日期的第一次出現,除非已在當天返回相同的對象。
LocalDate localdatewith =localdate.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(localdatewith);//2019-07-01

(2)使用TemporalAdjusters的next方法來指定日期

LocalDate date = localdate.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println("下一個週末的日期是:" + date);//2019-07-07

DateTimerFormatter:解析和格式化日期或時間(Format的子類)

LocalDate、LocalTime、LocalDateTime日期類型轉字符串的兩種方法

(1)自定義格式化日期時間

DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:ss:mm");
LocalDateTime now = LocalDateTime.now();
String format1 = dateFormat.format(now);
System.out.println("LocalDateTime轉String:"format1);//2019-07-02 17:53:56

(2)使用日期類中的format 方法傳入一個日期格式化類對象   

System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));//2019-07-02T18:15:49.771
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE));//2019-07-02
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_TIME));//18:15:49.771
System.out.println(now.format(DateTimeFormatter.ISO_DATE ));//2019-07-02
System.out.println(now.format(DateTimeFormatter.ISO_TIME));//18:15:49.771

 ZoneID:世界時區類

常用方法

(1)獲取世界各個地方的時區的集合

Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();

(2)獲取系統默認時區的ID

ZoneId zd = ZoneId.systemDefault();
System.out.println("系統默認時區" + zd);//Asia/Shanghai
System.out.println("系統默認時區" + zd.getId());//Asia/Shanghai

ZonedDateTime VS LocalDateTime

ZonedDateTime與LocalDateTime都會去讀取當前系統設置的時區,只不過ZonedDateTime多了一個時區的概念

LocalDateTime localdatetime = LocalDateTime.now();
ZonedDateTime zoneddatetime = ZonedDateTime.now();
System.out.println("當前系統localdatetime:" + localdatetime);//2019-07-02T18:42:32.812
System.out.println("當前系統zoneddatetime:" + zoneddatetime);//2019-07-02T18:42:32.813+08:00[Asia/Shanghai]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章