推荐使用java.time包计算两时间小时差:Instant适用于UTC绝对时刻(如日志),LocalDateTime适用于同区本地时间,ZonedDateTime处理带时区时间;避免用SimpleDateFormat和Date。

Java 计算两个时间相差的小时数,推荐使用 java.time 包(Java 8+),它线程安全、语义清晰、不易出错。核心是用 Duration 或 ChronoUnit.HOURS 计算两个 Instant、LocalDateTime 或 ZonedDateTime 之间的小时差。
用 Instant 计算 UTC 时间差(推荐用于日志、系统时间)
如果两个时间都是精确到毫秒的绝对时刻(比如数据库中的 timestamp、API 返回的时间戳),应统一转为 Instant 再计算:
- 先将字符串或 long 值解析为
Instant(注意时区!) - 用
Duration.between(a, b).toHours()获取整数小时(向下取整) - 或用
ChronoUnit.HOURS.between(a, b)—— 更简洁,结果相同
示例:
Instant start = Instant.parse("2024-05-01T08:30:00Z");
Instant end = Instant.parse("2024-05-01T12:45:30Z");
<p>long hours = ChronoUnit.HOURS.between(start, end); // 结果:4
// 若需带小数(如 4.25 小时),可用:
double hoursWithFraction = Duration.between(start, end).toMillis() / 60.0 / 60.0; // ≈ 4.258
用 LocalDateTime 计算本地时间差(适合无时区业务场景)
如果两个时间都属于同一时区(比如纯业务日期时间,不涉及跨时区),可用 LocalDateTime:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 注意:
LocalDateTime本身不含时区信息,不能直接表示“某个时刻”,仅适用于本地上下文比较 - 解析后直接用
ChronoUnit.HOURS.between()
示例:
LocalDateTime start = LocalDateTime.parse("2024-05-01T09:00");
LocalDateTime end = LocalDateTime.parse("2024-05-01T14:30");
long hours = ChronoUnit.HOURS.between(start, end); // 结果:5(向下取整)
处理时区问题(避免常见坑)
若原始时间带时区(如 "2024-05-01T10:00+08:00" 或 "2024-05-01T02:00Z"),务必用 ZonedDateTime 解析:
- 错误做法:用
LocalDateTime.parse()直接解析带偏移的时间字符串 → 会丢失时区,导致计算错误 - 正确做法:用
ZonedDateTime.parse(),再转Instant统一比较
示例:
ZonedDateTime zdt1 = ZonedDateTime.parse("2024-05-01T10:00+08:00");
ZonedDateTime zdt2 = ZonedDateTime.parse("2024-05-01T03:00Z");
<p>long hours = ChronoUnit.HOURS.between(zdt1.toInstant(), zdt2.toInstant()); // 自动按 UTC 对齐
兼容旧代码:SimpleDateFormat + Date(不推荐,仅维护用)
若仍在用 Java 7 或遗留系统,可借助 Date 和毫秒差:
- 用
SimpleDateFormat解析字符串(注意设置setLenient(false)防误解析) - 用
date2.getTime() - date1.getTime()得毫秒差,再除以3600_000
⚠️ 注意:Date 是可变对象、非线程安全,且 SimpleDateFormat 不是线程安全的,必须每次新建或加锁。

















