一个安全且完美的DateUitls(Date LocalDateTime long String相互转化)

140 阅读1分钟

Date LocalDateTime long String相互转化

先发代码

代码比较简单,没有记下来的意义,主要是备忘

不要使用SimpleDateFormat ,因为线程不安全,会在文章的最后,简单说明多线程情况下不安全的原因

package com.zhiweicoding.haiyoutool.utils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;

/**
 * @author by diaozhiwei on 2023/01/31.
 * @email diaozhiwei2k@163.com
 */
public class DateTimeFormatUtil {

    public static final DateTimeFormatter DATE_TIME_FULL = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    public static final DateTimeFormatter DATE_TIME_ALL = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter TIME_ALL = DateTimeFormatter.ofPattern("HH:mm:ss");
    public static final DateTimeFormatter DATE_ALL = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter DATE_TIME_ALL_CLOSELY = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    public static LocalDateTime dateToDT(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static Date dTToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static long stringToLong(String dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return stringToLong(dateStr, formatter);
    }

    public static long stringToLong(String dateStr, DateTimeFormatter pattern) {
        LocalDateTime parse = LocalDateTime.parse(dateStr, pattern);
        return dTToLong(parse);
    }

    public static LocalDateTime stringToDT(String dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return stringToDT(dateStr, formatter);
    }

    public static LocalDateTime stringToDT(String dateStr, DateTimeFormatter pattern) {
        LocalDateTime parse = LocalDateTime.parse(dateStr, pattern);
        return parse.atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static LocalDateTime longToDT(long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), TimeZone.getDefault().toZoneId());
    }

    public static long dTToLong(LocalDateTime dt) {
        return dt.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    public static String dTToString(LocalDateTime dt, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return dTToString(dt, formatter);
    }

    public static String dTToString(LocalDateTime dt, DateTimeFormatter pattern) {
        return dt.format(pattern);
    }

}

github源码地址

简单说明下使用LocalDateTime的原因

先看java DateFormat源码代码

    protected Calendar calendar;
 
    private StringBuffer format(Date date, StringBuffer toAppendTo,
                                FieldDelegate delegate) {
        // Convert input date to time field list
       calendar.setTime(date);

       boolean useDateFormatSymbols = useDateFormatSymbols();

       for (int i = 0; i < compiledPattern.length; ) {
           int tag = compiledPattern[i] >>> 8;
           int count = compiledPattern[i++] & 0xff;
           if (count == 255) {
               count = compiledPattern[i++] << 16;
               count |= compiledPattern[i++];
           }
           switch (tag) {
           case TAG_QUOTE_ASCII_CHAR:
               toAppendTo.append((char)count);
               break;
           case TAG_QUOTE_CHARS:
               toAppendTo.append(compiledPattern, i, count);
               i += count;
               break;
           default:
               subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
               break;
           }
       }
       return toAppendTo;
   }

calendar 属性是共享变量,在多线程的情况下,没有做线程安全控制。很可能发生一个线程刚刚set了值,另外一个线程又set了另外的值,导致结果异常的情况。所以在原来的代码中经常会使用ThreadLocal的方式创建SimpleDateFormat对象。