首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 取得當日 00:00:00 Timestamp 兩種做法與時區陷阱解析

     編輯:Java 程式設計入門

需求

取得「今天零點零分零秒」的 java.sql.Timestamp,常用於資料庫日期範圍查詢(如 WHERE create_time >= ?)。

原始碼分析

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

public class Test {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long t = System.currentTimeMillis();
        
        // 做法 1:直接對 86400000 取餘數 → 得到 GMT 00:00:00
        t = t / (1000 * 3600 * 24) * (1000 * 3600 * 24);
        System.out.println("GMT 零點:" + sdf.format(new Timestamp(t)));
        
        // 做法 2:再扣掉本地時區偏移 → 得到本地 00:00:00
        t = System.currentTimeMillis();
        t = t / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset();
        System.out.println("本地零點:" + sdf.format(new Timestamp(t)));
    }
}

輸出範例(GMT+8 環境)

GMT 零點:2024-01-15 00:00:00
本地零點:2024-01-15 00:00:00

乍看相同,實則內部毫秒值不同:

  • 做法 1:對應 UTC 00:00:00(即本地 08:00:00)
  • 做法 2:對應本地 00:00:00(即 UTC 16:00:00 前一日)

時區陷阱詳解

現代寫法(Java 8+ 推薦)

import java.time.*;
import java.sql.Timestamp;

public class ModernTimestamp {
    // 取得本地今天 00:00:00
    public static Timestamp localMidnight() {
        LocalDate today = LocalDate.now(ZoneId.systemDefault());
        LocalDateTime ldt = today.atStartOfDay(); // 00:00
        return Timestamp.valueOf(ldt);
    }

    // 取得 UTC 今天 00:00:00
    public static Timestamp utcMidnight() {
        LocalDate today = LocalDate.now(ZoneOffset.UTC);
        LocalDateTime ldt = today.atStartOfDay();
        return Timestamp.valueOf(ldt.atZone(ZoneOffset.UTC).toLocalDateTime());
    }
}

關鍵優勢

  • 自動處理夏令時間(DST)
  • 語意清晰、不可變、執行緒安全
  • 無需手動計算毫秒數、時區偏移

總結

舊代碼雖能湊出「看起來正確」的字串,但毫秒值語意模糊,極易在跨時區、夏令時間、資料庫時區設定不一致時產生 Bug。請全面改用 java.time API,徹底消除時區陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
做法毫秒值基準適用場景風險
僅除以 86400000UTC 零點資料庫儲存 UTC 時間、跨時區系統若資料庫用本地時間,查詢會偏移 8 小時
再扣 getRawOffset()本地零點資料庫儲存本地時間、單時區系統夏令時間未處理(getRawOffset 不含 DST)