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

Java 計算兩日期間隔天數工具方法:支援多格式解析、毫秒級精度與異常處理

     編輯:Java 綜合教學

需求場景

業務中頻繁需要計算「結束日期 - 開始日期」的間隔天數,日期字符串可能為 yyyy-MM-dd 或 yyyyMMdd 兩種格式。需封裝通用工具方法,自動識別格式、異常安全、返回 Long 天數。

工具方法實現

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 日期工具類
 */
public class DateUtils {

    private static final String FORMAT_DASH = "yyyy-MM-dd";
    private static final String FORMAT_PLAIN = "yyyyMMdd";

    /**
     * 計算兩個日期字符串之間的間隔天數 (end - start)
     *
     * @param startDate 開始日期,支援 yyyy-MM-dd 或 yyyyMMdd
     * @param endDate   結束日期,支援 yyyy-MM-dd 或 yyyyMMdd
     * @return 間隔天數 (可為負數,表示 start > end)
     * @throws ParseException 日期格式無法解析時拋出
     */
    public static Long daysBetween(String startDate, String endDate) throws ParseException {
        Date start = parseFlexible(startDate);
        Date end = parseFlexible(endDate);
        
        // 毫秒差轉天數:24h * 60m * 60s * 1000ms = 86,400,000
        long diffMs = end.getTime() - start.getTime();
        return diffMs / (24L * 60 * 60 * 1000);
    }

    /**
     * 靈活解析:自動檢測格式並解析
     */
    private static Date parseFlexible(String dateStr) throws ParseException {
        if (dateStr == null || dateStr.trim().isEmpty()) {
            throw new ParseException("日期字符串為空", 0);
        }
        String trimmed = dateStr.trim();
        // 簡單判斷:包含 '-' 按帶分隔符格式解析,否則按純數字格式
        if (trimmed.contains("-")) {
            return new SimpleDateFormat(FORMAT_DASH).parse(trimmed);
        } else {
            return new SimpleDateFormat(FORMAT_PLAIN).parse(trimmed);
        }
    }
}

使用示例

public class DateUtilsTest {
    public static void main(String[] args) {
        try {
            System.out.println(DateUtils.daysBetween("2024-01-01", "2024-01-10")); // 9
            System.out.println(DateUtils.daysBetween("20240101", "20240110"));     // 9
            System.out.println(DateUtils.daysBetween("2024-12-31", "2024-01-01")); // -365 (負數)
            System.out.println(DateUtils.daysBetween("20240228", "20240301"));     // 2 (閏年)
        } catch (ParseException e) {
            System.err.println("日期格式錯誤: " + e.getMessage());
        }
    }
}

關鍵點與改進建議

  1. 線程安全:SimpleDateFormat 非線程安全,生產環境建議用 ThreadLocal 或 Java 8+ DateTimeFormatter (線程安全)。
  2. Java 8+ 現代寫法 (推薦):
    import java.time.LocalDate;
    import java.time.format.DateTimeFormatter;
    import java.time.temporal.ChronoUnit;
    
    public static long daysBetweenModern(String start, String end) {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy[-MM][-dd][yyyyMMdd]"); // 非標準,建議分兩次試
        // 實際建議:嘗試解析,失敗則換格式
        LocalDate startDate = parseLocalDateFlexible(start);
        LocalDate endDate = parseLocalDateFlexible(end);
        return ChronoUnit.DAYS.between(startDate, endDate);
    }
  3. 時區影響:Date 依賴 JVM 默認時區,跨時區場景必須顯式指定時區或改用 LocalDate (無時區)。
  4. 邊界包含語義:本方法返回「日曆天數差」,若業務需「包含起始日」則 +1,需明確需求文檔。

總結

提供了一個健壯的 daysBetween 工具方法,支援雙格式自適應、異常拋出、負數處理。現代項目強烈建議遷移至 java.time 包 (LocalDate/ChronoUnit),享受線程安全、不可變、API 清晰的紅利。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved