You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何将混合日期时间单位的时长字符串解析为Period/Duration实例

实现方案

Java 8+ 自带的Period和Duration本身是职责拆分的:前者仅支持年、月、日等日期单位,后者仅支持时、分、秒等时间单位,所以混合单位的字符串无法直接解析为单个Period或Duration实例,你可以选择分开存储为两个实例,或者使用组合类存储。

方案1:纯JDK原生实现(无需引入第三方依赖)

核心思路是通过正则匹配字符串中所有「数值+单位」的片段,按单位类型分别归集到Period和Duration对象中,同时兼容单位的单复数、大小写格式。

解析代码示例

import java.time.Duration;
import java.time.Period;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TimeAmountParser {
    // 预编译匹配正则,适配单位单复数与大小写
    private static final Pattern TIME_PATTERN = Pattern.compile("(\\d+)\\s+(years?|months?|days?|hours?|minutes?|seconds?)", Pattern.CASE_INSENSITIVE);

    // 解析结果封装类,可按需调整结构
    public static class ParsedTimeAmount {
        private final Period period;
        private final Duration duration;

        public ParsedTimeAmount(Period period, Duration duration) {
            this.period = period;
            this.duration = duration;
        }

        public Period getPeriod() { return period; }
        public Duration getDuration() { return duration; }
    }

    public static ParsedTimeAmount parse(String input) {
        Matcher matcher = TIME_PATTERN.matcher(input);
        int years = 0, months = 0, days = 0;
        long hours = 0, minutes = 0, seconds = 0;

        while (matcher.find()) {
            long value = Long.parseLong(matcher.group(1));
            String unit = matcher.group(2).toLowerCase();
            switch (unit) {
                case "year": case "years": years = (int) value; break;
                case "month": case "months": months = (int) value; break;
                case "day": case "days": days = (int) value; break;
                case "hour": case "hours": hours = value; break;
                case "minute": case "minutes": minutes = value; break;
                case "second": case "seconds": seconds = value; break;
                default: throw new IllegalArgumentException("不支持的时间单位: " + unit);
            }
        }

        return new ParsedTimeAmount(
                Period.of(years, months, days),
                Duration.ofHours(hours).plusMinutes(minutes).plusSeconds(seconds)
        );
    }

    // 测试用例
    public static void main(String[] args) {
        // 测试示例1
        String test1 = "29 days 23 hours 59 minutes 20 seconds";
        ParsedTimeAmount result1 = parse(test1);
        System.out.println(result1.getPeriod()); // 输出P29D
        System.out.println(result1.getDuration()); // 输出PT23H59M20S

        // 测试示例2
        String test2 = "4 years 10 months 10 seconds";
        ParsedTimeAmount result2 = parse(test2);
        System.out.println(result2.getPeriod()); // 输出P4Y10M
        System.out.println(result2.getDuration()); // 输出PT10S
    }
}

方案2:用单个对象存储混合时间量

如果你希望用单个对象承载所有时间量,可以使用ThreeTen Extra库中的PeriodDuration类,该类是JSR310时间体系的官方扩展类,专门适配同时包含日期和时间单位的时间量场景,解析完成后直接调用PeriodDuration.of(period, duration)即可构造对应实例。

扩展说明

  • 如果需要支持毫秒、周等其他单位,只需要在正则规则和switch分支中补充对应配置即可
  • 如果需要自动做单位转换(比如25小时自动转为1天1小时),可以在解析完成后调用Duration#toDaysPart等内置方法转换后更新Period数值即可

内容的提问来源于stack exchange,提问作者Marwi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 03:09:02