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

如何在Java中通过argparse4j直接接收java.time.Duration类型命令行参数?

用argparse4j直接接收java.time.Duration参数的最优方案

当然有更直接的办法——给argparse4j自定义一个ArgumentType,让它自动把输入字符串转换成Duration类型,不用在业务代码里手动处理解析逻辑。

步骤1:实现自定义的Duration ArgumentType

argparse4j允许通过实现ArgumentType<T>接口扩展支持任意类型的参数。我们可以写一个类型转换器,既支持标准ISO-8601格式,还能兼容更友好的简化格式(比如1h30m、5s这种用户更容易输入的形式):

import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentType;
import net.sourceforge.argparse4j.inf.Namespace;
import java.time.Duration;

public class DurationArgumentType implements ArgumentType<Duration> {
    @Override
    public Duration convert(ArgumentParser parser, Namespace namespace, String value) {
        // 先尝试标准ISO-8601格式(比如PT1H30M)
        try {
            return Duration.parse(value);
        } catch (IllegalArgumentException e) {
            // 兼容简化格式解析
            long totalSeconds = 0;
            String input = value.trim();
            int index = 0;

            while (index < input.length()) {
                // 提取数字部分
                int numStart = index;
                while (index < input.length() && Character.isDigit(input.charAt(index))) {
                    index++;
                }
                if (numStart == index) {
                    throw parser.error("无效的时长格式:" + value);
                }
                long number = Long.parseLong(input.substring(numStart, index));

                // 提取单位部分
                if (index >= input.length()) {
                    throw parser.error("缺少时长单位:" + value);
                }
                char unit = input.charAt(index);
                switch (unit) {
                    case 'h':
                        totalSeconds += number * 3600;
                        break;
                    case 'm':
                        totalSeconds += number * 60;
                        break;
                    case 's':
                        totalSeconds += number;
                        break;
                    default:
                        throw parser.error("未知的时长单位:" + unit);
                }
                index++;
            }
            return Duration.ofSeconds(totalSeconds);
        }
    }
}

步骤2:在ArgumentParser中使用自定义类型

定义好转换器后,直接在参数声明时指定type为我们的自定义类型即可:

import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;
import java.time.Duration;

public class AppDemo {
    public static void main(String[] args) {
        ArgumentParser parser = ArgumentParsers.newFor("DurationDemo").build()
                .description("演示argparse4j接收Duration参数");

        parser.addArgument("--timeout")
                .type(new DurationArgumentType())
                .required(true)
                .help("超时时间,支持ISO-8601格式(如PT1H30M)或简化格式(如1h30m、30s)");

        try {
            Namespace namespace = parser.parseArgs(args);
            Duration timeout = namespace.get("timeout");
            System.out.println("解析后的时长:" + timeout);
            // 直接使用timeout做业务逻辑,无需手动转换
        } catch (ArgumentParserException e) {
            parser.handleError(e);
            System.exit(1);
        }
    }
}

这个方案的优势

  • 直接绑定类型:参数解析完成后直接拿到Duration对象,业务代码里不用再写Duration.parse()的重复逻辑
  • 格式友好:同时支持标准ISO-8601和用户更易输入的简化格式,提升使用体验
  • 统一错误处理:解析失败时自动整合到argparse4j的错误提示体系,不用自己处理异常判断

如果只需要支持标准ISO-8601格式,自定义类型可以更简单,直接返回Duration.parse(value)即可,同样比手动解析更整洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:55:19