Java日期時間API系列31-----Jdk8中java.time包中的新的日期時間API類,時間戳的獲取方式對比、轉換和使用。


 

  時間戳是指格林威治時間1970年01月01日00時00分00秒起至現在的總毫秒數,是所有時間的基礎,其他時間可以通過時間戳轉換得到。Java中本來已經有相關獲取時間戳的方法,Java8后增加新的類Instant等專用於處理時間戳問題。

 

 1 獲取時間戳的方法和性能對比

1.1 獲取時間戳方法

Java8以前可以使用System.currentTimeMillis() 、new Date().getTime() 、和Calendar.getInstance().getTimeInMillis()獲取。Java8以后可以另外通過Instant.now().toEpochMilli()和Clock.systemUTC().millis()獲取。

比較簡單,下面直接看代碼:

    /**
     * 使用System獲取時間戳
     */
    @Test
    public void getEpochMilliWithSystem(){
        long s = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            System.currentTimeMillis();
        }
        System.out.println("getEpochMilliWithSystem cost:"+(System.currentTimeMillis()-s));
    }
    
    /**
     * 使用Date獲取時間戳
     */
    @Test
    public void getEpochMilliWithDate(){
        long s = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            new Date().getTime();
        }
        System.out.println("getEpochMilliWithDate cost:"+(System.currentTimeMillis()-s));
    }
    
    /**
     * 使用Calendar獲取時間戳
     */
    @Test
    public void getEpochMilliWithCalendar(){
        long s = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            Calendar.getInstance().getTimeInMillis();
        }
        System.out.println("getEpochMilliWithCalendar cost:"+(System.currentTimeMillis()-s));
    }
    
    /**
     * 使用Instant獲取時間戳
     */
    @Test
    public void getEpochMilliWithInstant(){
        long s = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            Instant.now().toEpochMilli();
        }
        System.out.println("getEpochMilliWithInstant cost:"+(System.currentTimeMillis()-s));
    }
    
    /**
     * 使用Clock獲取時間戳
     */
    @Test
    public void getEpochMilliWithClock(){
        long s = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            Clock.systemUTC().millis();
        }
        System.out.println("getEpochMilliWithClock cost:"+(System.currentTimeMillis()-s));
    }

查看過上面相關源碼,基本都是通過System.currentTimeMillis() 來創建對象的。比如 new Date:

    public Date() {
        this(System.currentTimeMillis());
    }

 

1.2 性能對比

上面代碼執行輸出:

getEpochMilliWithSystem cost:5
getEpochMilliWithDate cost:38
getEpochMilliWithCalendar cost:1094
getEpochMilliWithInstant cost:106
getEpochMilliWithClock cost:17

通過1.1 中的分析得知基本都是通過System.currentTimeMillis() 來創建對象的System.currentTimeMillis()最快,性能最好。

所以,性能排序:System > Clock > DateInstant > Calendar

 

2.時間戳轉換為其他類

 2.1 時間戳和其他類型的轉換

    /**
     * 時間戳epochMilli毫秒轉Date
     * @param epochMilli
     * @return
     */
    public static Date toDate(long epochMilli){
        Objects.requireNonNull(epochMilli, "epochMilli");
        return new Date(epochMilli);
    }
    /**
     * 時間戳epochMilli毫秒轉LocalDateTime
     * @param epochMilli
     * @return
     */
    public static LocalDateTime toLocalDateTime(long epochMilli) {
        Objects.requireNonNull(epochMilli, "epochMilli");
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault());
    }
    /**
     * 時間戳epochMilli毫秒轉LocalDate
     * @param epochMilli
     * @return
     */
    public static LocalDate toLocalDate(long epochMilli) {
        Objects.requireNonNull(epochMilli, "epochMilli");
        return toLocalDateTime(epochMilli).toLocalDate();
    }
    /**
     * 時間戳epochMilli毫秒轉Instant
     * @param epochMilli
     * @return
     */
    public static Instant toInstant(long epochMilli) {
        Objects.requireNonNull(epochMilli, "epochMilli");
        return Instant.ofEpochMilli(epochMilli);
    }
    /**
     * 時間戳epochMilli毫秒轉ZonedDateTime,時區為系統默認時區
     * @param epochMilli
     * @return
     */
    public static ZonedDateTime toZonedDateTime(long epochMilli) {
        Objects.requireNonNull(epochMilli, "epochMilli");
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault())
                .atZone(ZoneId.systemDefault());
    }
    /**
     * 時間戳epochMilli轉Timestamp
     * @param epochMilli
     * @return
     */
    public static Timestamp toTimestamp(long epochMilli){
        return new Timestamp(epochMilli);
    }

    /**
     * Date轉時間戳
     * 從1970-01-01T00:00:00Z開始的毫秒值
     * @param date
     * @return
     */
    public static long toEpochMilli(Date date){
        Objects.requireNonNull(date, "date");
        return date.getTime();
    }
    /**
     * LocalDateTime轉時間戳
     * 從1970-01-01T00:00:00Z開始的毫秒值
     * @param localDateTime
     * @return
     */
    public static long toEpochMilli(LocalDateTime localDateTime){
        return toInstant(localDateTime).toEpochMilli();
    }
    /**
     * LocalDate轉時間戳
     * 從1970-01-01T00:00:00Z開始的毫秒值
     * @param localDate
     * @return
     */
    public static long toEpochMilli(LocalDate localDate){
        return toInstant(localDate).toEpochMilli();
    }
    /**
     * Instant轉時間戳
     * 從1970-01-01T00:00:00Z開始的毫秒值
     * @param instant
     * @return
     */
    public static long toEpochMilli(Instant instant){
        Objects.requireNonNull(instant, "instant");
        return instant.toEpochMilli();
    }
    /**
     * ZonedDateTime轉時間戳,注意,zonedDateTime時區必須和當前系統時區一致,不然會出現問題
     * 從1970-01-01T00:00:00Z開始的毫秒值
     * @param zonedDateTime
     * @return
     */
    public static long toEpochMilli(ZonedDateTime zonedDateTime) {
        Objects.requireNonNull(zonedDateTime, "zonedDateTime");
        return zonedDateTime.toInstant().toEpochMilli();
    }
    /**
     * Timestamp轉時間戳
     * 從1970-01-01T00:00:00Z開始的毫秒值
     * @param timestamp
     * @return
     */
    public static long toEpochMilli(Timestamp timestamp){
        Objects.requireNonNull(timestamp, "timestamp");
        return timestamp.getTime();
    }

 

測試代碼:

    /**
     * 時間戳轉換測試
     */
    @Test
    public void epochMilliConverterTest(){
        System.out.println("===================epochMilliConverterTest=====================");
        Date date = new Date();
        long epochMilli = date.getTime();
        System.out.println("epochMilli:"+epochMilli);
        System.out.println("===================ToOther=====================");
        System.out.println(DateTimeConverterUtil.toDate(epochMilli));
        System.out.println(DateTimeConverterUtil.toLocalDateTime(epochMilli));
        System.out.println(DateTimeConverterUtil.toLocalDate(epochMilli));
        System.out.println(DateTimeConverterUtil.toInstant(epochMilli));
        System.out.println(DateTimeConverterUtil.toZonedDateTime(epochMilli));
        System.out.println(DateTimeConverterUtil.toTimestamp(epochMilli));
        System.out.println("===================toEpochMilli=====================");
        System.out.println(DateTimeConverterUtil.toEpochMilli(new Date()));
        System.out.println(DateTimeConverterUtil.toEpochMilli(LocalDateTime.now()));
        // 另一種方式: +8 時區
        System.out.println(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());
        System.out.println(DateTimeConverterUtil.toEpochMilli(LocalDate.now()));
        System.out.println(DateTimeConverterUtil.toEpochMilli(Instant.now()));
        System.out.println(DateTimeConverterUtil.toEpochMilli(ZonedDateTime.now()));
        System.out.println(DateTimeConverterUtil.toEpochMilli(new Timestamp(System.currentTimeMillis())));
    }

 

輸出:

===================epochMilliConverterTest=====================
epochMilli:1587950768191
===================ToOther=====================
Mon Apr 27 09:26:08 CST 2020
2020-04-27T09:26:08.191
2020-04-27
2020-04-27T01:26:08.191Z
2020-04-27T09:26:08.191+08:00[Asia/Shanghai]
2020-04-27 09:26:08.191
===================toEpochMilli=====================
1587950768304
1587950768304
1587950768304
1587916800000
1587950768305
1587950768305
1587950768305

 

 3 Timestamp

Timestamp是Java8以前處理時間戳的類。Timestamp和其他類型的轉換

    /**
     * Timestamp轉LocalDateTime
     * @param timestamp
     * @return
     */
    public static LocalDateTime toLocalDateTime(Timestamp timestamp) {
        Objects.requireNonNull(timestamp, "timestamp");
        return timestamp.toLocalDateTime();
    }
    /**
     * Timestamp轉Instant
     * @param timestamp
     * @return
     */
    public static Instant toInstant(Timestamp timestamp) {
        Objects.requireNonNull(timestamp, "timestamp");
        return timestamp.toInstant();
    }
    /**
     * Timestamp轉時間戳
     * 從1970-01-01T00:00:00Z開始的毫秒值
     * @param timestamp
     * @return
     */
    public static long toEpochMilli(Timestamp timestamp){
        Objects.requireNonNull(timestamp, "timestamp");
        return timestamp.getTime();
    }
    /**
     * Date轉Timestamp
     * @param date
     * @return
     */
    public static Timestamp toTimestamp(Date date){
        Objects.requireNonNull(date, "date");
        return new Timestamp(date.getTime());
    }
    /**
     * LocalDateTime轉Timestamp
     * @param localDateTime
     * @return
     */
    public static Timestamp toTimestamp(LocalDateTime localDateTime){
        Objects.requireNonNull(localDateTime, "localDateTime");
        return Timestamp.valueOf(localDateTime);
    }
    
    /**
     * Instant轉Timestamp
     * @param instant
     * @return
     */
    public static Timestamp toTimestamp(Instant instant){
        Objects.requireNonNull(instant, "instant");
        return Timestamp.from(instant);
    }

    /**
     * 時間戳epochMilli轉Timestamp
     * @param epochMilli
     * @return
     */
    public static Timestamp toTimestamp(long epochMilli){
        return new Timestamp(epochMilli);
    }

測試代碼:

    /**
     * Timestamp轉換測試
     */
    @Test
    public void timestampConverterTest(){
        System.out.println("===================timestampConverterTest=====================");
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        long epochMilli = timestamp.getTime();
        System.out.println("epochMilli:"+epochMilli);
        System.out.println("===================ToOther=====================");
        System.out.println(DateTimeConverterUtil.toLocalDateTime(timestamp));
        System.out.println(DateTimeConverterUtil.toInstant(timestamp));
        System.out.println(DateTimeConverterUtil.toEpochMilli(timestamp));
        System.out.println("===================toEpochMilli=====================");
        System.out.println(DateTimeConverterUtil.toTimestamp(new Date()));
        System.out.println(DateTimeConverterUtil.toTimestamp(LocalDateTime.now()));
        System.out.println(DateTimeConverterUtil.toTimestamp(Instant.now()));
        System.out.println(DateTimeConverterUtil.toTimestamp(epochMilli));
    }

輸出:

===================timestampConverterTest=====================
epochMilli:1587950937677
===================ToOther=====================
2020-04-27T09:28:57.677
2020-04-27T01:28:57.677Z
1587950937677
===================toEpochMilli=====================
2020-04-27 09:28:57.774
2020-04-27 09:28:57.781
2020-04-27 09:28:57.782
2020-04-27 09:28:57.677

 

4 Instant

Java8可以使用Instant方便的獲取時間戳相關的信息。

4.1 創建方式

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

Instant now方法默認使用的是UTC,協調世界時。now(Clock clock)方法
clock參數可以設置時區信息,就可以獲取不同時區的Instant,比如 Clock systemDefaultZone()
或指定時區 Clock system(ZoneId zone)等。



4.2 獲取時間戳


public long toEpochMilli() 獲取時間戳 單位為毫秒。

public long getEpochSecond() 獲取時間戳 單位為秒。

 

5.總結

   通過上面可以看出,時間戳是所有時間創建和轉換的基礎,通過簡單的System.currentTimeMillis()獲取到,但時間戳只是一個簡單的數字,不轉換為其他時間類沒有意義,比如 年、月、日、時、分、秒、星期、閏年、時區、夏令時等,更多相關的比如各種節假日,星座等附加意義的信息。

 

源代碼地址:https://github.com/xkzhangsan/xk-time


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM