在業務開發中,常需計算兩個時間點之間的天、時、分、秒差值。本文提供一個基於毫秒數運算的通用工具方法,並說明其原理與注意事項。
import java.util.Calendar;
import java.util.Date;
public class DateDiffUtils {
/**
* 計算從指定日期到現在的時間差
* @param pastDate 過去的日期
* @return 格式化字符串:X天Y時Z分W秒
*/
public static String getDurationFrom(Date pastDate) {
Calendar cal = Calendar.getInstance();
cal.setTime(pastDate);
long pastMs = cal.getTimeInMillis();
long nowMs = System.currentTimeMillis();
long diffMs = nowMs - pastMs;
if (diffMs < 0) return "0秒"; // 未來時間
long days = diffMs / (1000 * 60 * 60 * 24);
long hours = (diffMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
long minutes = (diffMs % (1000 * 60 * 60)) / (1000 * 60);
long seconds = (diffMs % (1000 * 60)) / 1000;
StringBuilder sb = new StringBuilder();
if (days > 0) sb.append(days).append("天");
if (hours > 0) sb.append(hours).append("時");
if (minutes > 0) sb.append(minutes).append("分");
if (seconds > 0 || sb.length() == 0) sb.append(seconds).append("秒");
return sb.toString();
}
/**
* 計算任意兩個日期的差值
*/
public static String getDurationBetween(Date start, Date end) {
long diffMs = end.getTime() - start.getTime();
if (diffMs < 0) { // 交換保證正數
long tmp = start.getTime();
start = end;
end = new Date(tmp);
diffMs = -diffMs;
}
long days = diffMs / 86400000L;
long hours = (diffMs % 86400000L) / 3600000L;
long minutes = (diffMs % 3600000L) / 60000L;
long seconds = (diffMs % 60000L) / 1000L;
return String.format("%d天%d時%d分%d秒", days, hours, minutes, seconds);
}
}
Date created = new Date(System.currentTimeMillis() - 90061000L); // 1天1時1分1秒前 System.out.println(DateDiffUtils.getDurationFrom(created)); // 輸出:1天1時1分1秒 Date d1 = new Date(2023, 0, 1); // 2023-01-01 Date d2 = new Date(2023, 0, 3, 5, 30, 10); // 2023-01-03 05:30:10 System.out.println(DateDiffUtils.getDurationBetween(d1, d2)); // 輸出:2天5時30分10秒
Date.getTime() / Calendar.getTimeInMillis() 返回距離 Unix 紀元 (1970-01-01 00:00:00 UTC) 的毫秒數86400000L (一天毫秒數)、3600000L (一小時) 等,提升可讀性與性能import java.time.*;
import java.time.temporal.ChronoUnit;
public class ModernDateDiff {
public static String between(LocalDateTime start, LocalDateTime end) {
long days = ChronoUnit.DAYS.between(start, end);
long hours = ChronoUnit.HOURS.between(start, end) % 24;
long minutes = ChronoUnit.MINUTES.between(start, end) % 60;
long seconds = ChronoUnit.SECONDS.between(start, end) % 60;
return String.format("%d天%d時%d分%d秒", days, hours, minutes, seconds);
}
}
java.time 包提供不可變、線程安全、時區感知的現代 API,新項目強烈推薦使用。
java.util.Date 基於 UTC 毫秒差**不受影響**,但若需「日曆日」差(如同一壽命日期),需用 LocalDate 配合時區處理DATETIME/TIMESTAMP 讀取後建議立即轉為 Instant 或 LocalDateTime 操作long 範圍,極少見但需留意掌握毫秒運算核心邏輯,靈活應對各種時間差計算場景。