一般我們對日期的操作使用的類有Date、DateTimeFormat、Calendar,在進行日期格式操作時一般用DateTimeFormat比較多,我們知道Date出來的數據格式是
Mon Jun 15 11:00:59 CST 2020
我們想把它轉換成易讀的格式,使用DateTimeFormat:
public void test() {
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
System.out.println(formatter.format(date));
}
打印結果:
2020-06-15 11:03:23
問題1:如何我們操作頻繁,豈不是每次都要new一個SimpleDateFormat對象?
對於這個問題的一般解決方式是創建一個靜態共享變量來避免多次創建對象:
public class Test {
private static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
...
}
問題2:SimpleDateFormat線程安全性?
我們知道SimpleDateFormat不是線程安全的,如果涉及到多線程就要考慮這個問題了。
線程安全:有多個線程同時訪問一個變量可能會出現問題,例如線程A和線程B同時訪問變量s,A修改了s值,B緊接着修改了s值,然後A去拿s的值,這時候拿到的不是預期的值,這時候就出問題了;
對於這個問題一般考慮加鎖:
public class Test {
private static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
public void test() {
synchronized (formatter) {
Date date = new Date();
System.out.println(formatter.format(date));
}
}
}
問題3:對性能的影響?
如果線程很多、訪問很頻繁的話,一直會有線程在排隊等待鎖,這樣的話對性能影響還是不小的,這時候可以考慮使用:
方式1:ThreadLocal
public class Test {
private static ThreadLocal<SimpleDateFormat> formatThreadLocal = new ThreadLocal<>();
private void dateTest() {
SimpleDateFormat sdf = formatThreadLocal.get();
if (sdf == null) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
formatThreadLocal.set(sdf);
}
System.out.println(sdf.format(new Date()));
}
}
方式2:DateTimeFormatter代替SimpleDateFormat
private void dateTest2() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
System.out.println(formatter.format(LocalDateTime.now()));
}
}
總結:在解決日期相關問題時,儘量用DateTimeFormatter代替SimpleDateFormat、LocalDateTime代替Calendar、Instant代替Date,注意SDK版本。