日常開發中,我們經常需要使用時間相關類,想必大家對
SimpleDateFormat
並不陌生。主要用它進行時間的格式化輸出和解析,挺方便快捷的,但是SimpleDateFormat
並不是一個線程安全的類。在多線程情況下,會出現異常,想必有經驗的小夥伴也遇到過。
接下來看看《阿里巴巴開發手冊》對SimpleDateFormat
是怎麼看待的?
【強制】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
JDK8 DateUtils
個人總結:
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
/**
* @ClassName DateUtils
* @Description 時間工具類 1.8版本
* @Author QiMing
* @Date 2019/4/30 8:45
* @Version 1.0
*/
public class DateUtils {
/**
* 缺省的日期顯示格式: yyyy-MM-dd
*/
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
/**
* 用做單號
*/
public static final String DEFAULT_DATE_FORMAT_ORDER = "yyyyMMdd";
/**
* 缺省的日期顯示格式: yyyy-MM
*/
public static final String DEFAULT_YYMM_FORMAT = "yyyy-MM";
/**
* 缺省的日期時間顯示格式:yyyy-MM-dd HH:mm:ss
*/
public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
* 缺省的日期時間顯示格式:yyyy-MM-dd HH:mm:ss:sss
*/
public static final String YMDHMSS = "yyyy-MM-dd HH:mm:ss:sss";
/**
* 字符串時間
*/
public static final String YMDHMS = "yyyyMMddHHmmss";
/**
* 當前時間
*/
public static Date DATE_NOW = new Date();
/**
* 當前時間
*/
public static LocalDate localDate = LocalDate.now();
/**
* @Title getDay
* @Description 獲取年月日(當天)
* @Param []
* @Return java.lang.String
* @Date 2019/6/4 15:26
* @Author QiMing
*/
public static String getDay() {
LocalDate date = LocalDate.now();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT);
return date.format(fmt);
}
/**
* @Title getDayTime
* @Description 年月日時分秒 (當天) 此方法不支持毫秒
* @Param []
* @Return java.lang.String
* @Date 2019/6/4 15:28
* @Author QiMing
*/
public static String getDayTime() {
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMAT);
return date.format(fmt);
}
/**
* @Title getDateToString
* @Description date類型轉換字符串
* @Param [date]
* @Return java.lang.String
* @Date 2019/7/8 11:07
* @Author QiMing
*/
public static String getDateToString(Date date) {
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT_ORDER);
return localDateTime.format(fmt);
}
/**
* @Title getLocalDateToString
* @Description LocalDate轉換String
* @Param [localDate]
* @Return java.lang.String
* @Date 2019/7/8 11:10
* @Author QiMing
*/
public static String getLocalDateToString(LocalDate localDate) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT_ORDER);
return localDate.format(fmt);
}
/**
* @Title getFixedTime
* @Description 自定固定時間
* @Param [year, month, day, hour, minute, second]
* @Return java.time.LocalDateTime
* @Date 2019/7/8 15:23
* @Author QiMing
*/
public static LocalDateTime getFixedTime(int year, int month, int day, int hour, int minute, int second) {
return LocalDateTime.of(year, month, day, hour, minute, second);
}
/**
* @Title settingsTime
* @Description 設置固定時間
* @Param [year, month, day, hour, minute, second]
* @Return java.time.LocalDateTime
* @Date 2019/7/8 15:29
* @Author QiMing
*/
public static LocalDateTime settingsTime(int year, int month, int day, int hour, int minute, int second) {
return LocalDateTime.now().withYear(year).withMonth(month).withDayOfMonth(day).withHour(hour).withMinute(minute).withSecond(second);
}
/**
* @Title firstToMonth
* @Description 當月第一天
* @Param []
* @Return java.time.LocalDate
* @Date 2019/7/8 15:31
* @Author QiMing
*/
public static LocalDate firstToMonth() {
return localDate.with(TemporalAdjusters.firstDayOfMonth());
}
/**
* @Title lastToMonth
* @Description 本月最後一天
* @Param []
* @Return java.time.LocalDate
* @Date 2019/7/8 15:33
* @Author QiMing
*/
public static LocalDate lastToMonth() {
return localDate.with(TemporalAdjusters.lastDayOfMonth());
}
/**
* @Title firstNextMonth
* @Description 下個月第一天
* @Param []
* @Return java.time.LocalDate
* @Date 2019/7/8 15:35
* @Author QiMing
*/
public static LocalDate firstNextMonth() {
return localDate.with(TemporalAdjusters.firstDayOfNextMonth());
}
/**
* @Title firstToYear
* @Description 本年第一天
* @Param []
* @Return java.time.LocalDate
* @Date 2019/7/8 15:36
* @Author QiMing
*/
public static LocalDate firstToYear() {
return localDate.with(TemporalAdjusters.firstDayOfYear());
}
/**
* @Title lastToYear
* @Description 本年最後一天
* @Param []
* @Return java.time.LocalDate
* @Date 2019/7/8 15:37
* @Author QiMing
*/
public static LocalDate lastToYear() {
return localDate.with(TemporalAdjusters.lastDayOfYear());
}
/*——————————————————— 時間相差 start ———————————————————————*/
/**
* @Title difference
* @Description 相差分鐘
* @Param [localTime, localTime1]
* @Return long
* @Date 2019/7/8 15:43
* @Author QiMing
*/
public static long difference(LocalTime localTime, LocalTime localTime1) {
return Duration.between(localTime, localTime1).getSeconds();
}
/**
* @Title aFewYearsApart
* @Description 相差幾年
* @Param [oldDate, newDate]
* @Return long
* @Date 2019/7/8 15:47
* @Author QiMing
*/
public static long aFewYearsApart(LocalDateTime oldDate, LocalDateTime newDate) {
return ChronoUnit.YEARS.between(oldDate, newDate);
}
/**
* @Title aFewMonthsApart
* @Description 相差幾個月
* @Param [oldDate, newDate]
* @Return long
* @Date 2019/7/8 15:49
* @Author QiMing
*/
public static long aFewMonthsApart(LocalDateTime oldDate, LocalDateTime newDate) {
return ChronoUnit.MONTHS.between(oldDate, newDate);
}
/**
* @Title aFewWEEKSApart
* @Description 相差多少周
* @Param [oldDate, newDate]
* @Return long
* @Date 2019/7/8 15:50
* @Author QiMing
*/
public static long aFewWEEKSApart(LocalDateTime oldDate, LocalDateTime newDate) {
return ChronoUnit.WEEKS.between(oldDate, newDate);
}
/**
* @Title aFewDAYSApart
* @Description 相差多少天
* @Param [oldDate, newDate]
* @Return long
* @Date 2019/7/8 15:51
* @Author QiMing
*/
public static long aFewDAYSApart(LocalDateTime oldDate, LocalDateTime newDate) {
return ChronoUnit.DAYS.between(oldDate, newDate);
}
/**
* @Title aFewHOURSApart
* @Description 相差多少小時
* @Param [oldDate, newDate]
* @Return long
* @Date 2019/7/8 15:52
* @Author QiMing
*/
public static long aFewHOURSApart(LocalDateTime oldDate, LocalDateTime newDate) {
return ChronoUnit.HOURS.between(oldDate, newDate);
}
/**
* @Title aFewHOURSApart
* @Description 相差多少分鐘
* @Param [oldDate, newDate]
* @Return long
* @Date 2019/7/8 15:52
* @Author QiMing
*/
public static long aFewMINUTESApart(LocalDateTime oldDate, LocalDateTime newDate) {
return ChronoUnit.MINUTES.between(oldDate, newDate);
}
/**
* @Title aFewSECONDSApart
* @Description 相差多少秒
* @Param [oldDate, newDate]
* @Return long
* @Date 2019/7/8 15:54
* @Author QiMing
*/
public static long aFewSECONDSApart(LocalDateTime oldDate, LocalDateTime newDate) {
return ChronoUnit.SECONDS.between(oldDate, newDate);
}
/**
* @Title aFewMILLISApart
* @Description 相差多少毫秒
* @Param [oldDate, newDate]
* @Return long
* @Date 2019/7/8 15:55
* @Author QiMing
*/
public static long aFewMILLISApart(LocalDateTime oldDate, LocalDateTime newDate) {
return ChronoUnit.MILLIS.between(oldDate, newDate);
}
/**
* @Title aFewMILLISApart
* @Description 相差多少納秒
* @Param [oldDate, newDate]
* @Return long
* @Date 2019/7/8 15:55
* @Author QiMing
*/
public static long aFewNANOSApart(LocalDateTime oldDate, LocalDateTime newDate) {
return ChronoUnit.NANOS.between(oldDate, newDate);
}
/*——————————————————— 時間相差 end ———————————————————————*/
/**
* @Title getTimestamp
* @Description 獲取時間戳13位
* @Param []
* @Return long
* @Date 2019/7/8 15:59
* @Author QiMing
*/
public static long getTimestamp() {
return Clock.systemDefaultZone().millis();
}
/*——————————————————————— 時間轉換 Start ——————————————————————*/
/**
* @Title dateToLocalDateTime
* @Description date轉換LocalDateTime
* @Param [date]
* @Return java.time.LocalDateTime
* @Date 2019/7/8 16:05
* @Author QiMing
*/
public static LocalDateTime dateToLocalDateTime(Date date) {
// LocalDateTime.ofInstant(date.toInstant(),ZoneId.systemDefault());
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
/**
* @Title dateToLocalDate
* @Description date轉換LocalDate
* @Param [date]
* @Return java.time.LocalDate
* @Date 2019/7/8 16:08
* @Author QiMing
*/
public static LocalDate dateToLocalDate(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
/**
* @Title dateToLocalTime
* @Description date轉換LocalTime
* @Param [date]
* @Return java.time.LocalTime
* @Date 2019/7/8 16:08
* @Author QiMing
*/
public static LocalTime dateToLocalTime(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
}
/**
* @Title localDateTimeToDate
* @Description LocalDateTime轉爲Date
* @Param [localDateTime]
* @Return java.util.Date
* @Date 2019/7/8 16:10
* @Author QiMing
*/
public static Date localDateTimeToDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* @Title localDateToDate
* @Description LocalDate -> Date,時間默認都是00
* @Param [localDate]
* @Return java.util.Date
* @Date 2019/7/8 16:13
* @Author QiMing
*/
public static Date localDateToDate(LocalDate localDate) {
return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
/*——————————————————————— 時間轉換 End ——————————————————————*/
/*———————————————————————— 日期與字符串、字符串與時間轉換 Start ——————————————————————————*/
/**
* @Title stringConversionLocalDate
* @Description 字符串轉LocalDate
* @Param [ymd]
* @Return java.time.LocalDate
* @Date 2019/7/8 16:19
* @Author QiMing
*/
public static LocalDate stringConversionLocalDate(String ymd) {
return LocalDate.parse(ymd, DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
}
/**
* @Title stringConversionLocalDateTime
* @Description 字符串轉LocalDateTime
* @Param [ymdhms]
* @Return java.time.LocalDateTime
* @Date 2019/7/8 16:22
* @Author QiMing
*/
public static LocalDateTime stringConversionLocalDateTime(String ymdhms) {
return LocalDateTime.parse(ymdhms, DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMAT));
}
/**
* @Title localDateConversionString
* @Description localDate轉字符串
* @Param [localDate]
* @Return java.lang.String
* @Date 2019/7/8 16:24
* @Author QiMing
*/
public static String localDateConversionString(LocalDate localDate) {
return localDate.format(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
}
/**
* @Title localDateTimeConversionString
* @Description localDateTime轉字符串
* @Param [localDateTime]
* @Return java.lang.String
* @Date 2019/7/8 16:25
* @Author QiMing
*/
public static String localDateTimeConversionString(LocalDateTime localDateTime) {
return localDateTime.format(DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMAT));
}
/**
* @Title localDateTimeToString
* @Description localDateTime轉字符串
* @Param [localDateTime]
* @Return java.lang.String
* @Date 2019/7/8 16:28
* @Author QiMing
*/
public static String localDateTimeToString(LocalDateTime localDateTime) {
return DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMAT).format(localDateTime);
}
/*———————————————————————— 日期與字符串、字符串與時間轉換 end ——————————————————————————*/
/**
* @Title timestampConversionLocalDateTime
* @Description 時間戳轉換Localdatetime
* @Param [timeMillis]
* @Return java.time.LocalDateTime
* @Date 2019/7/8 16:32
* @Author QiMing
*/
public static LocalDateTime timestampConversionLocalDateTime(long timeMillis) {
Instant instant = Instant.ofEpochMilli(timeMillis);
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
}
/**
* @Title localDateTimeConversiontimestamp
* @Description localDateTime 轉換時間戳
* @Param [localDateTime]
* @Return long
* @Date 2019/7/8 16:34
* @Author QiMing
*/
public static long localDateTimeConversiontimestamp(LocalDateTime localDateTime) {
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
/**
* @Title getWeek
* @Description 獲取周幾
* @Param [localDate]
* @Return java.lang.String
* @Date 2019/7/8 17:08
* @Author QiMing
*/
public static String getWeek(LocalDate localDate) {
String week = String.valueOf(localDate.getDayOfWeek());
switch (week) {
case "MONDAY":
week = "週一";
break;
case "TUESDAY":
week = "週二";
break;
case "WEDNESDAY":
week = "週三";
break;
case "THURSDAY":
week = "週四";
break;
case "FRIDAY":
week = "週五";
break;
case "SATURDAY":
week = "週六";
break;
case "SUNDAY":
week = "週日";
break;
}
return week;
}
/**
* @Title localDateTimeChangeTen
* @Description LocalDateTime轉換10位時間戳
* @Param [localDateTime]
* @Return long
* @Date 2019/7/9 8:39
* @Author QiMing
*/
public static long localDateTimeChangeTen(LocalDateTime localDateTime) {
long lon = localDateTimeConversiontimestamp(localDateTime) / 1000;
return Long.valueOf(String.format("%010d", lon));
}
}