JAVA JAVA 8 Date Time DateTime Zone Calnder

Java 8 時間/日期

alan 2018/05/16 23:13:24
1471

Java 8 時間/日期


簡介

Java 8 推出 java.Time 功能,與舊版本的Date/Calnder 差別及敘述使用方法 。

作者

王柏雄


JAVA 8-日期與時間

表示日期和時間
基本概念

 

時刻

所有計算機系統內部都用一個整數表示時刻,這個整數是距離格林尼治標準時間197011000秒的毫秒數,可以理解時刻就是絕對時間,它與時區無關,不同時區對同一時刻的解讀,即年月日時分秒是不一樣的。

時區

時區:同一時刻,世界上各個地區的時間可能是不一樣的,具體時間與時區有關,一共有24個時區,英國格林尼治是0時區,北京是東八區,也就是説格林尼治凌晨1點,北京是早上9點。

年曆

年曆:我們都知道,中國有公曆和農曆之分,公曆和農曆都是年曆,不同的年曆,一年有多少月,每月有多少天,甚至一天有多少小時,這些可能都是不一樣的,我們主要討論公曆。


 

JAVA8 以前的API(java.util.Date)存在的問題:

問題一:

在一開始的時候,Date要承載日期訊息,又要做日期之間的轉換,還要做日期格式的顯示,太多工了。

JDK1.1開始,將三項的職責分開:

  • 使用Date 裝日期跟時間訊息。
  • 使用Calendar 類別做日期和時間的轉換。
  • 使用DateFormat 類別格式化和分析日期字串。
就算分開職責,但還是不夠方便使用。

問題二:呈上題,為什麼不夠方便呢?參數給201811號,怎麼變成3918 21號了?

使用Date設定日期,但年份要-1900,月份要從0-11設定。

   
Date 日期: Fri Feb 01 00:00:00 GMT+08:00 3918
   
可能有人會說要設置日期,應該要用java.util.Calendar,像這樣:
   
Calendar :Thu Feb 01 10:55:00 GMT+08:00 2018
   
年份正常了,月份還是一樣錯誤,一樣要用0~11,不夠直覺。

像這樣的不一致的設定操作,實在不好用。


 問題三:Java.util.Date java.util.Calendar中的所有屬性都是mutable的。
   
   
   
第一次執行: 15696

第二次執行:0 ???

   
在此我們會看到,這樣做第二次運算兩天之間的相差天數是 0 ???
因為第一次的運算相差天數已將原本的值改變了,這樣可變屬性會發生不可預期的問題。 

 

在看到這些Date的問題後,我們來看看JAVA 8新增java.time優點:

 

物件的值不會被改變

java.time套件底下的物件都是Immutable Object,設計師只能夠通過一些類別或是物件方法來產生新的不同數值的物件。也因此這些物件都可以同時在不同的執行緒下被使用(thread-safe)

領域驅動設計

(Domain-driven design)

java.time套件將日期與時間依據不同的使用案例,區分成不同的類別,不像以前的java.util.Date是同時結合了時間與日期和時區的大雜燴。

支援多種曆法

java.time套件除了能支援國際通用的ISO 8601日期與時間的表示方式外,還支援一些non-ISO的曆法(日本常會使用紀年年號),都放置在java.time.chrono套件內。

 

 

Java 8中表示日期和時間的類有多個,主要的有:

 

類別名稱

說明

使用方法

LocalDateTime

表示與時區無關的日期和時間信息,不直接對應時刻,需要通過時區轉換。

LocalDateTime.now();

LocalDateTime.of(2018,5,13,14,13,59);

//2018-05-13T14:13:59

LocalDate

·    表示與時區無關的日期,與LocalDateTime相比,只有日期訊息,沒有時間訊息。

LocalDate.now();

LocalDate.of(2018,5,13);

//2018-05-13

LocalTime

·    表示與時區無關的時間,與LocalDateTime相比,只有時間訊息,沒有日期訊息。

LocalTime.now();

LocalTime.of(21,59);

//21:59

ZoneId

表示時區

ZoneId.of("UTC+8");//北京時區

ZonedDateTime

表示特定時區的日期和時間

ZonedDateTime.now();

ZonedDateTime.of(2015, 11, 30, 23, 45, 59, 1234, zoneId);

// 2015-11-30T23:45:59.000001234+08:00[UTC+08:00]

Instant

表示時刻,不直接對應年月日信息,需要通過時區轉換

Instant.now();

Instant.ofEpochSecond(120, 100000);

 //方法的第一個參數為秒,第二個參數為n秒,表示從1970-01-01 00:00:00開始後兩分鐘的10n秒的時刻。

 

 

 

我們可以透過下面這張圖來快速看一下java.time的一些主要的類別跟格式。

  這些類別提供了相關的方法,這些方法一般都有相同的方法前綴

(導引敘述,其他平行展開的功能,就自已實作囉!)

of:設定日期,例如:LocalDate.of(2015,5,13);

  
日期 :2018-05-13

parse:字串日期轉換,給定轉換樣版,就可以轉換為物件囉!

  
轉換後格式: 2018-05-13
再使用一次格式化: 05/13/2018

get:取得年份,取得月份...等等。

  
取得年:2018
取得月:5
取得日:13

is:判斷日期前後

  
05-13是否在05-20之後 false

plus : 加日期或時間    

minus:減日期或時間

   
10 天日期為: 2018-05-23
10 天後減 3 天日期為: 2018-05-20
  
14:03 加上 4 分鐘: 14:07

to:新舊制轉換

  
instant : 2018-05-16T03:56:09.610Z
          date    : Wed May 16 11:56:09 GMT+08:00 2018

to:取得需要的格式

  
 

Instant.ofEpochMilli(long epochMilli) :參數為 n()

表示從1970-01-01 00:00:00開始n秒的時刻

toDays    : 1

toHours   : 34

toMinutes : 2072

toMillis  : 124333578

toNanos   : 124333578000000


at:組合時間與日期

  
日期時間 :2018-05-10T04:03

Zone 時區:

  
北京時區的日期時間 :

2015-11-30T23:45:59.000001234+08:00[UTC+08:00]

使用時刻,加上時區:
2018-05-16T12:32:18.147+08:00[UTC+08:00]
alan