现代时间模型硬核实践:Instant/ZoneId/DST、区间/周期与可测试性
大约 2 分钟
现代时间模型硬核实践:Instant/ZoneId/DST、区间/周期与可测试性
新手先看 · 一屏速览
- 业务用
LocalDate/LocalDateTime;存储与跨系统传输用Instant(或 epoch millis) - 显式
ZoneId、DateTimeFormatter;避免平台默认 - 注意 DST(夏令时):本地时间在某些地区可能不存在或重复
1. 本地时间 vs 瞬时时间
Instant now = Instant.now();
ZonedDateTime z = now.atZone(ZoneId.of("Asia/Shanghai"));Instant是 UTC 时间线上的瞬间;ZonedDateTime= 本地时间 + 时区 补充:OffsetDateTime仅包含固定偏移,不含完整时区规则(不适合处理 DST)
2. 解析与格式化
var fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime t = LocalDateTime.parse("2024-10-01 08:00:00", fmt);
System.out.println(t.format(fmt));DateTimeFormatter 线程安全,可复用;统一格式在边界层集中维护
3. Duration/Period 与区间
Duration d = Duration.between(Instant.now(), Instant.now().plusSeconds(3600));
Period p = Period.between(LocalDate.now(), LocalDate.now().plusDays(30));Duration 基于秒/纳秒,适合机器时间;Period 基于人类日历(年月日),跨月要谨慎
4. DST 与陷阱
- 在夏令时切换点,本地时间可能跳变或重复;以
ZonedDateTime与ZoneRules校正 示例:美国某些地区“2:00 → 3:00”跳变,LocalDateTime的 2:30 可能不存在
5. 可测试性与时钟
最近建一些几十个工作内推群,各大城市都有,群里目前已经收集了很多内推岗位,大厂、中厂、小厂、外包都有。 欢迎HR、开发、测试、运维和产品加入。

扫描下方微信,备注:网站+所在城市,即可拉你进工作内推群。

Clock clock = Clock.fixed(Instant.parse("2024-01-01T00:00:00Z"), ZoneId.of("UTC"));
Instant.now(clock);- 通过注入
Clock实现可控时间,便于单元测试 在业务对象中持有Clock,避免直接调用Instant.now(),实现可重复测试
6. 旧 API 互操作
Instant i = new Date().toInstant();
Date d = Date.from(Instant.now());避免 java.util.Date/Calendar 在新代码中的直接使用;仅在互操作边界转换
7. 实战清单与反模式
- 清单:显式时区;统一格式化;跨系统用 UTC 或 epoch;注入时钟便于测试
- 反模式:
new Date()+SimpleDateFormat(线程不安全);平台默认时区与格式
8. 练习
- 将订单系统的本地时间持久化为 UTC,展示时按用户时区还原
- 模拟一段覆盖 DST 切换点的业务逻辑,验证时间计算正确
