如何将Joda-Time Period API迁移至java.time?寻求日期时间统一处理方案
Joda-Time Period 迁移至 java.time 的解决方案
Joda-Time 的 Period API 可同时处理日期(年、月、日)与时间(时、分、秒、毫秒),但 java.time 将该能力拆分为两个独立类:
Period:仅处理日期维度(年、月、日),基于日历规则动态计算(比如2月会按实际天数处理)Duration:仅处理时间维度(时、分、秒、毫秒),基于固定毫秒数计算
单独使用任一 API 都会有局限,比如用 Duration 处理月份时会默认按30天计算,不符合实际日历规则。以下是可行的解决方案:
方案1:组合使用 Period + Duration
将原 Joda-Time Period 拆分为日期部分(用 Period)和时间部分(用 Duration),操作时依次应用两者,既保留日历维度的动态计算,又能正确处理时间部分。
示例代码:
// 原 Joda-Time 代码 // Period jodaPeriod = new Period(1, 2, 3, 4, 5, 6, 7, 8); // 1年2月3日4时5分6秒8毫秒 // LocalDateTime dt = LocalDateTime.now().plus(jodaPeriod); // 迁移后的 java.time 代码 Period datePeriod = Period.of(1, 2, 3); // 1年2月3日 Duration timeDuration = Duration.ofHours(4) .plusMinutes(5) .plusSeconds(6) .plusMillis(8); // 4时5分6秒8毫秒 LocalDateTime dt = LocalDateTime.now(); dt = dt.plus(datePeriod).plus(timeDuration);
方案2:自定义组合类封装日期+时间
如果需要一个单一对象同时管理日期和时间维度,可以自定义实现 TemporalAdjuster 接口,内部封装 Period 和 Duration,统一对外提供操作入口。
示例代码:
public class CombinedPeriod implements TemporalAdjuster { private final Period datePeriod; private final Duration timeDuration; public CombinedPeriod(Period datePeriod, Duration timeDuration) { this.datePeriod = datePeriod; this.timeDuration = timeDuration; } @Override public Temporal adjustInto(Temporal temporal) { // 先调整日期,再调整时间 return temporal.plus(datePeriod).plus(timeDuration); } // 静态工厂方法,简化实例创建 public static CombinedPeriod of(int years, int months, int days, long hours, long minutes, long seconds, long millis) { Period p = Period.of(years, months, days); Duration d = Duration.ofHours(hours) .plusMinutes(minutes) .plusSeconds(seconds) .plusMillis(millis); return new CombinedPeriod(p, d); } }
使用方式:
CombinedPeriod combined = CombinedPeriod.of(1, 2, 3, 4, 5, 6, 8); LocalDateTime dt = LocalDateTime.now().with(combined);
注意事项
- 禁止用
Duration处理年、月维度:Duration基于固定毫秒数计算,无法适配不同月份的天数差异,必须用Period处理日期维度。 - 自定义类需兼容不同
Temporal类型:如果需要支持LocalDate(仅日期)或LocalTime(仅时间),可在adjustInto方法中添加类型判断,避免抛出异常。
内容的提问来源于stack exchange,提问作者Saurabh Sole
相关产品推荐
相关产品推荐

