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.pantech.cloud.cargo.utils;
 2 
 3 import org.springframework.util.StringUtils;
 4 
 5 import java.time.LocalDate;
 6 import java.time.LocalDateTime;
 7 import java.time.ZoneId;
 8 import java.time.format.DateTimeFormatter;
 9 import java.util.Date;
10 
11 /**
12  * @description 时间工具类
13  * @author: zx
14  * @create: 2020-10-28 09:43:30
15  **/
16 public class DateUtilsJDK8 {
17 
18     private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
19     private static final DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
20 
21     /**
22      * 字符串转Date<br>
23      *
24      * @param date 时间字符串 "yyyy-MM-dd HH:mm:ss" or "yyyy-MM-dd"
25      * @param type null or "00" or "23"
26      * @return Date
27      */
28     public static Date getDate(String date, String type) {
29         try {
30             LocalDateTime localDateTime = null;
31             if (StringUtils.isEmpty(date)) return null;
32             if (date.length() == 10) {
33                 LocalDate parse = LocalDate.parse(date, formatter2);
34                 localDateTime = parse.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
35 
36             } else if(date.length()==19) {
37                 localDateTime = LocalDateTime.parse(date, formatter);
38             }else{
39                 throw new IllegalArgumentException("时间字符串格式错误!");
40             }
41             if (StringUtils.isEmpty(type)) {
42                 return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
43             } else {
44                 return changeFormat(localDateTime, type);
45             }
46         } catch (Exception e) {
47             e.printStackTrace();
48         }
49         return null;
50     }
51 
52     private static Date changeFormat(LocalDateTime localDateTime, String type) {
53         if ("00".equals(type)) {
54             localDateTime = localDateTime.withHour(00);
55             localDateTime = localDateTime.withMinute(00);
56             localDateTime = localDateTime.withSecond(00);
57             return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
58         } else if ("23".equals(type)) {
59             localDateTime = localDateTime.withHour(23);
60             localDateTime = localDateTime.withMinute(59);
61             localDateTime = localDateTime.withSecond(59);
62             return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
63         } else {
64             throw new IllegalArgumentException(type + "--type参数异常!");
65         }
66     }
67 }

 

 

注:type: null 返回原格式  00 当天最初时刻,时分秒为0  23 当天最后时刻,23时59分59秒
posted @ 2020-11-02 16:24  土豆GPT  阅读(751)  评论(0编辑  收藏  举报