Java中 LocalDate、LocalTime、LocalDateTime三個時間工具類的使用介紹

                                        Java中 LocalDate、LocalTime、LocalDateTime三個時間工具類的使用介紹

一、背景:

      之前在做項目的過程中,對日期時間類沒有一個系統的瞭解,總是在用的時候去搜索一下,解決問題即完事,久而久之,導致對這個概念特別模糊。直到近期,做項目的過程中使用了mybatis-plus框架,這個框架自動生成映射文件的工具會將MySQL中的datetime類型轉化成Java中的LocalDateTime類型,由於幾次都出現了轉化錯誤、轉化繁瑣的問題,因此,就打算詳細的瞭解一下Java中的時間類的相關知識,希望下次再使用能夠做到心中有底。經過了幾天的瞭解,對這個時間概念算是有了一個大致的瞭解,記錄下來供以後參考。看來解決問題還得要抓住問題的本質,瞭解技術的來龍去脈,不能浮於表面。

二、介紹:

       在JDK8發佈的時候,推出了LocalDate、LocalTime、LocalDateTime這個三個時間處理類,以此來彌補之前的日期時間類的不足,簡化日期時間的操作。在Java8之前,處理日期時間的類是Date、Calendar,這兩個在使用起來總是讓人感覺不是很舒服,在設計上面有一些缺陷,並且還不是線程安全的。

       想要詳細的瞭解這幾個類,我們得要了解一點關於時間、時區劃分的一些知識。1884 年, 國際經度會議將地球表面按經線等分爲24 區,稱爲時區。即以本初子午線爲基準, 東西經度各7.5 度的範圍作爲零時區, 然後每隔15度爲一時區,每個時區相差一小時。北京時區爲東八區,要比零時區早8個小時。如果現在零時區的時間是10點的話,那北京時間就是18點。

       我們平時在程序裏面所見到的UTC時間,就是零時區的時間,它的全稱是Coordinated Universal Time ,即世界協調時間。另一個常見的縮寫是GMT,即格林威治標準時間,格林威治位於 零時區,因此,我們平時說的UTC時間和GMT時間在數值上面都是一樣的。 

        可能會有一些疑問,同樣是在地球上啊,不同的地區時間怎麼還不一樣了?難道我現在從北京乘個飛機飛到格林威治,還可以來個時光倒流?如果這樣,豈不很神奇?哈哈,當然事情的真相並不是這樣的。時間的流逝、細胞的衰老對於整個地球來說都是一樣的,因此,不管你在地球的哪裏,這一秒過去了,就是過去了,它最爲公平,不會多你一分,也不會少你一秒。那怎麼記錄這流逝的分分秒秒呢?有一個名詞,叫做時間戳,它是指格林威治(地球零時區)時間1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起至現在的總秒數,這個時間戳,在地球的各個地方都是一致的。在1970年以前,有其他的計時方式,由於沒有統一,還造成了一些軟件的運行在時間上的錯亂,險些釀成了的行業災難(具體的事件可以網上搜索)。如果單純指望這個時間戳作爲人們的計時標準,那也是不現實的,因爲這對人類的生產生活來說沒有任何的意義。舉個例子:每天早上八點上課(上班)符合我們的習慣,如果是***秒到了上課時間就有違人的正常腦回路了。這時候,根據地球上的不同經緯度、地球自轉的特點,就劃分了時區,時間戳根據不同的時區轉化成當地的時間,以此作爲作息標準,從而方便人們的生產生活。北京時間的8點我們可以見到太陽的升起,倫敦時間的八點他們也能見到太陽的升起。

       就這樣,可以知道,時間戳對地球上的任何一個地方都是一樣的,如果我們想要把時間戳轉化成當地的時間,就需要根據所在地區的時區進行轉化。不同時區之間進行時間轉化也是一樣的道理,我們需要根據時區的差異來轉化當地的時間。

三、使用方法:

 3.1  Java8 以前的時間處理:

     1,Date類的使用:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class TestTime {
	
public static void main(String[] args) {
	try {
        //獲取Date對象,存放的是時間戳
        Date date = new Date();
        //獲取時間戳(毫秒)
        long seconds = date.getTime();
        System.out.println("當前時間戳: " + seconds);
       
        //當前GMT(格林威治)時間、當前計算機系統所在時區的時間
        SimpleDateFormat beijingFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("本地(東八區)時間: " + beijingFormat.format(date) +"; GMT時間: " + date.toGMTString());
        
        //東八區時間轉換成東九區(東京)時間,比北京早一個小時
        SimpleDateFormat tokyoFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        tokyoFormat.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));
        System.out.println("東京(東九區)時間: "+tokyoFormat.format(date));
        
        //時間戳轉化成Date
        SimpleDateFormat timestampFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String fotmatString = timestampFormat.format(seconds);
        Date parseDate = timestampFormat.parse(fotmatString);
        System.out.println("時間戳轉化成Date之後的時間: "+parseDate + ";格式化之後的: "+ fotmatString);
	            
	} catch (Exception e) {
		e.printStackTrace();
	}
}
}

 輸出結果如下:

Date的無參構造函數如下圖:

 

   我們可以看到,Date中存放的是時間戳,因此,我們在世界各地調用這個方法,獲取到的值都是一樣的。只是在不同的地方,這個值會根據時區轉化成當地的時間而已。

3.2  Java8 之後的時間處理:

       從Java8開始,推出了LocalDate、LocalTime、LocalDateTime這三個工具類,實現了更好地時間處理,我們先看如何使用,然後,再進行比較。

 1,工具類的獲取與使用:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class TestLocalTime {
public static void main(String[] args) {
	//獲取當前時區的日期
	LocalDate localDate = LocalDate.now();
	System.out.println("localDate: " + localDate);
	//時間
	LocalTime localTime = LocalTime.now();
	System.out.println("localTime: " + localTime);
	//根據上面兩個對象,獲取日期時間
	LocalDateTime localDateTime = LocalDateTime.of(localDate,localTime);
	System.out.println("localDateTime: " + localDateTime);
	//使用靜態方法生成此對象
	LocalDateTime localDateTime2 = LocalDateTime.now();
	System.out.println("localDateTime2: " + localDateTime2);
	//格式化時間
	DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
	System.out.println("格式化之後的時間: " + localDateTime2.format(formatter));
	
	//轉化爲時間戳(秒)
	long epochSecond = localDateTime2.toEpochSecond(ZoneOffset.of("+8"));
	//轉化爲毫秒
	long epochMilli = localDateTime2.atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli();
	System.out.println("時間戳爲:(秒) " + epochSecond + "; (毫秒): " + epochMilli);
	
	//時間戳(毫秒)轉化成LocalDateTime
	Instant instant = Instant.ofEpochMilli(epochMilli);
	LocalDateTime localDateTime3 = LocalDateTime.ofInstant(instant, ZoneOffset.systemDefault());
	System.out.println("時間戳(毫秒)轉化成LocalDateTime: " + localDateTime3.format(formatter));
	//時間戳(秒)轉化成LocalDateTime
	Instant instant2 = Instant.ofEpochSecond(epochSecond);
	LocalDateTime localDateTime4 = LocalDateTime.ofInstant(instant2, ZoneOffset.systemDefault());
	System.out.println("時間戳(秒)轉化成LocalDateTime: " + localDateTime4.format(formatter));
}
}

   上述程序運行結果如下圖所示:

    新推出來的這三個類,與MySQL中的日期時間類型正好對應,如果我們使用MySQL數據庫的話,在插入相應字段的時候,都不需要再進行任何的轉化了。對應關係如下:

   LocalTime  對應  time
   LocalDate  對應  date
   LocalDateTime  對應  datetime(timestamp)

2,增加、減去時間:

看看上圖,是不是非常的簡單方便呢。

3,LocalDateTime 與 Date 的相互轉化

// Date 轉化成 LocalDateTime
public static LocalDateTime dateToLocalDate(Date date) {
	Instant instant = date.toInstant();
	ZoneId zoneId = ZoneId.systemDefault();
	return instant.atZone(zoneId).toLocalDateTime();
}
// LocalDateTime 轉化成 Date
public static Date localDateTimeToDate(LocalDateTime localDateTime) {
	ZoneId zoneId = ZoneId.systemDefault();
	ZonedDateTime zdt = localDateTime.atZone(zoneId);
	return Date.from(zdt.toInstant());
}

由於 LocalDate、LocalTime 或者只含有日期,或者只含有時間,因此,不能和Date直接進行轉化。

四、總結:

      瞭解好時區,時間戳等這幾個概念,對於我們瞭解程序語言中時間類的構造非常有幫助。Java8 新推出來的這三個類,不僅讓我們在日常編程中更爲高效方便,而且,在與數據庫時間類型的對應上更爲友好。

最後總結:

1,時間戳: 是指格林威治(地球零時區)時間1970年01月01日00時00分00秒起至現在的總秒數,這個時間戳,在地球的各個地方都是一致的;

2,時區:由於地球的自轉,根據接收太陽光照的順序將地球劃分成24個區,從而方便當地人的生產生活,每個時區相差一小時,可以根據時間戳和時區計算當地的時間。格林威治處於零時區,北京處於東八區,因此,北京時間比格林威治時間早8個小時。

3,LocalDateTime 比 Date使用起來更爲方便,兩者可以相互進行轉化。

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