System.currentTimeMillis()與時區無關
摘要:System.currentTimeMillis()獲取的時間戳與時區無關。
綜述
??System.currentTimeMillis()經常被用來獲取當前時間戳,單位是毫秒,可以用來計算當前年月日或者星期幾等,可以方便地與Date進行轉換,可以計算某個方法的耗時:
long curTime = System.currentTimeMillis();
doSth();
System.out.println("耗時 = " + (System.currentTimeMillis()-curTime));
??正因為該方法是當前時間節點與0時區(1970-01-01 00:00:00 +0:00)相差的毫秒數,所以在這個時間節點,無論在哪個時區獲取時間戳,其值絲毫不差。
測試用例
??如何驗證它不會因為時區不同而返回不同的數值呢?測試用例很簡單:調用函數TimeZone.setDefault(TimeZone zone)初始化操作系統時區為上海,打印一次時間戳的計算結果,接著切換操作系統的時區到東京,再運行一次,得到時間戳2。時間戳2和時間戳1的差值,等于切換時區的耗時,看看此耗時是否非常地小;為了使得實驗效果更理想,每次切換時區都打印時分秒格式的當前時間,而且加了一組巴黎時區的數據。
public static void main(String[] args) throws InterruptedException {
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
long timestamp1 = System.currentTimeMillis();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(new Date()));
System.out.println("時間戳: " + timestamp1 + ",OS time zone: " + ZoneId.systemDefault());
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo"));
long timestamp2 = System.currentTimeMillis();
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(new Date()));
System.out.println("時間戳: " + timestamp2 + ",OS time zone: " + ZoneId.systemDefault());
System.out.println("timestamp2 - timestamp1 = " + (timestamp2 - timestamp1));
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Paris"));
long timestamp3 = System.currentTimeMillis();
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(new Date()));
System.out.println("時間戳: " + timestamp3 + ",OS time zone: " + ZoneId.systemDefault());
System.out.println("timestamp3 - timestamp1 = " + (timestamp3 - timestamp1));
}
實驗結果如下:
2023-08-05 12:20:59
時間戳: 1691209259885,OS time zone: Asia/Shanghai
2023-08-05 13:21:00
時間戳: 1691209260033,OS time zone: Asia/Tokyo
timestamp2 - timestamp1 = 148
2023-08-05 06:21:00
時間戳: 1691209260035,OS time zone: Europe/Paris
timestamp3 - timestamp1 = 150
??分析實驗結果可知:
- 函數
System.currentTimeMillis()與時區毫無瓜葛。 df.format(new Date())的執行結果和時區休戚相關。其實,SimpleDateFormat的對象df可以調用函數df.setTimeZone(TimeZone.getTimeZone("UTC"))設置時區。
??關于時間的存儲和顯示問題,基于數據的存儲和顯示相分離是非常基礎的設計原則,在數據庫存儲時間的時候,只保存表示絕對時間的Long型時間戳,不用顧慮應用服務器和數據庫服務器的時區設置問題,在顯示給用戶的時候,根據用戶設置的時區轉換為字符串。
小結
??函數System.currentTimeMillis()獲取的時間戳與時區無關。基于時間戳的時間存儲不存在時區的問題,時區只與頁面顯示綁定。也就是說,在進行時間戳和日期之間的轉換時,需要根據不同的時區進行計算,以防止出現時間偏差。
讀后有收獲,小禮物走一走,請作者喝咖啡。
Buy me a coffee. ?Get red packets.作者:樓蘭胡楊
本文版權歸作者和博客園共有,歡迎轉載,但請注明原文鏈接,并保留此段聲明,否則保留追究法律責任的權利。

浙公網安備 33010602011771號