DateTimeFormatter接替SimpleDateFormat

        java程序猿經常會碰到的一個問題就是日期格式化。當接收參數中有日期或時間,那麼就需要與前端商量好其格式,這邊我知道是2種:1、時間戳 2、字符串。

        先說一下時間戳,這個形勢的參數,Java只需new Date(Long date)就能獲得Date,但是我在使用過程中還是碰到奇怪的問題,就是時區與數據庫對不上。獲得的Date是CST格式的,而 CST卻同時可以代表如下 4 個不同的時區:

Central Standard Time (USA) UT-6:00

Central Standard Time (Australia) UT+9:30

China Standard Time UT+8:00

Cuba Standard Time UT-4:00

所以用起來還是有點麻煩,於是我放棄了時間戳。

        然後我用起了字符串,字符串就簡單了,只需要用SimpleDateFormat格式化一下,而且後端在調試模式可以很明確看到什麼時間。但是SimpleDateFormat有個缺點就是線程不安全,而且在使用的時候需要拋出異常或者try catch,至於為什麼線程不安全我就不細說了,在阿里的Java開發手冊(嵩山版)中有明確指出:【強制】SimpleDateFormat 是線程不安全的類,一般不要定義為 static變量,如果定義為 static, 必須加鎖,或者使用 DateUtils工具類。 正例:注意線程安全,使用 DateUtils。亦推薦如下處理: private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { return new SimpleDateFormat(“yyyy-MM-dd”); } }; 說明:如果是JDK8 的應用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar, DateTimeFormatter 代替SimpleDateFormat,官方給出的解釋:simple beautiful strong immutable thread-safe。

        那麼解決他線程不安全有幾種辦法:

1、將SimpleDateFormat定義成局部變量,在每次用到的時候就創建一個對象,方法結束作為垃圾回收,但是這樣會消耗內存,就是大家用一個杯子喝水,可能不衛生或者搶着喝,但是每人一個一次性杯子,就增加了開銷。

2、加線程同步鎖(synchronized)這個我忘的差不多了,自行百度,這不是本節重點。

3、使用ThreadLocal,這個同上。

4、這個簡單,不安全咱不用,jdk1.8中新增了 LocalDate 與 LocalDateTime等類來解決日期處理方法,同時引入了一個新的類DateTimeFormatter來解決日期格式化問題。API中講的很詳細,重點是This class is immutable and thread-safe。這個類是不可變的和線程安全的。LocalDateTime,DateTimeFormatter兩個類都是線程安全的,只要不創建為public類型就沒啥問題。可以使用Instant代替 Date,LocalDateTime代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat,具體使用方法可以查看API。

下面是我自用的一個工具類:

 1 package com.hmbb.demo.util;
 2 import org.springframework.util.StringUtils;
 3 import java.time.LocalDateTime;
 4 import java.time.ZoneId;
 5 import java.time.format.DateTimeFormatter;
 6 import java.util.Date;
 7  8 /**
 9  * @description 時間工具類
10  * @author: zx
11  * @create: 2020-10-28 09:43:30
12  **/
13 public class DateUtils {
14 15 16     private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
17 18     /**
19      *  字符串轉Date
20      * @param date 時間字符串 "yyyy-MM-dd HH:mm:ss" or "yyyy-MM-dd"
21      * @param type null or "00" or "23"
22      * @return Date
23      */
24     public static Date getDate(String date,String type){
25         try {
26             if(StringUtils.isEmpty(date))return null;
27             if(date.length()==10){
28                 date = date.concat(" 00:00:00");
29             }
30             LocalDateTime localDateTime = LocalDateTime.parse(date,formatter);
31             if(StringUtils.isEmpty(type)){
32                 return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
33             }else{
34                 return changeFormat(localDateTime,type);
35             }
36         }catch (Exception e){
37             e.printStackTrace();
38         }
39         return null;
40     }
41     private static Date changeFormat(LocalDateTime localDateTime,String type){
42         if("00".equals(type)){
43             localDateTime = localDateTime.withHour(00);
44             localDateTime = localDateTime.withMinute(00);
45             localDateTime = localDateTime.withSecond(00);
46             return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
47         }else if("23".equals(type)){
48             localDateTime = localDateTime.withHour(23);
49             localDateTime = localDateTime.withMinute(59);
50             localDateTime = localDateTime.withSecond(59);
51             return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
52         }else {
53             throw  new IllegalArgumentException(type+"--type參數異常!");
54         }
55     }
56 }
註:type: null 返回原格式  00 當天最初時刻,時分秒為0  23 當天最後時刻,23時59分59秒
Tags: