V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mylovesaber
V2EX  ›  Java

为何 Java 从配置文件读取的时间参数会被强制认为是 Date 类型?设置 Object 类型会被强制转换成完整的 Date 格式?

  •  
  •   mylovesaber · 2023-01-01 12:22:21 +08:00 · 1927 次点击
    这是一个创建于 474 天前的主题,其中的信息可能已经有所发展或是发生改变。

    settings.yml 部分内容:

    period:
      from: 2022-05-10
      to: 2023-01-01
    

    如果我设置变量:

        private static String periodFrom;
        private static String periodTo;
        
        Yaml yaml = new Yaml();
        FileInputStream fileInputStream = new FileInputStream("settings.yml");
        HashMap yamlMap = yaml.load(fileInputStream);
        
        HashMap period = (HashMap) yamlMap.get("period");
        periodFrom = (String) period.get("from");
        periodTo = (String) period.get("to");
    	System.out.println(periodFrom);
    

    报错:Exception in thread "main" java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String

    也就是这里变量 periodFrom 和 periodTo 必须是 Date 或者 Object 这类范围更广的类型。java 为何会认定我设置的参数本身不是 String 而是 Date 呢?

    如果我将 String 类型改成 Object 的话,sout 输出的是:Tue May 10 08:00:00 CST 2022 而不是我希望的 2022-05-10,这又是为什么呢?网上查了好像没什么头绪,还请赐教...

    我希望的是读取这个日期参数,然后进行检查是否格式正确,如果正确,那么该日期将转换后(转换成 2017-01-01T00:00:00Z )用于从 gitlab 拉取 commit 信息

    参考: https://github.com/gitlab4j/gitlab4j-api#commitsapi

    其中:

    // Get a list of commits associated with the specified branch that fall within the specified time window
    // This uses the ISO8601 date utilities the in org.gitlab4j.api.utils.ISO8601 class
    Date since = ISO8601.toDate("2017-01-01T00:00:00Z");
    Date until = new Date(); // now
    List<Commit> commits = gitLabApi.getCommitsApi().getCommits(1234, "new-feature", since, until);
    

    xml 需要添加坐标:

    
        <repositories>
            <repository>
                <id>apache</id>
                <url>https://repo.maven.apache.org/maven2</url>
            </repository>
        </repositories>
        
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
            <dependency>
                <groupId>org.yaml</groupId>
                <artifactId>snakeyaml</artifactId>
                <version>1.33</version>
            </dependency>
        </dependencies>
    
    12 条回复    2023-01-01 15:03:01 +08:00
    learningman
        1
    learningman  
       2023-01-01 12:26:29 +08:00
    你用双引号括上试试
    mylovesaber
        2
    mylovesaber  
    OP
       2023-01-01 12:29:55 +08:00
    @learningman 我之前尝试过可以,但如果我本身不希望加上双引号呢?我卡住的地方就是这地方
    learningman
        4
    learningman  
       2023-01-01 12:31:52 +08:00
    那就拿 Object 再判断呗,如果是 Date 就
    var sdf = new SimpleDateFormat("yyyy-MM-dd");
    var dateString = sdf.format(date);
    fzdwx
        5
    fzdwx  
       2023-01-01 12:36:31 +08:00
    `Yaml yaml = new Yaml();`

    这是这个包做的附带的功能吧?
    mylovesaber
        6
    mylovesaber  
    OP
       2023-01-01 12:42:50 +08:00
    @fzdwx 对,xml 中坐标指定了 snakeyaml
    mylovesaber
        7
    mylovesaber  
    OP
       2023-01-01 12:52:54 +08:00
    @learningman 可能不太行
    ```java
    String formatPeriodFrom = simpleDateFormat.format(periodFrom);
    System.out.println(formatPeriodFrom);
    Date parsePeriodFrom = simpleDateFormat.parse(formatPeriodFrom);
    System.out.println(parsePeriodFrom);

    String formatPeriodTo = simpleDateFormat.format(periodTo);
    System.out.println(formatPeriodTo);
    Date parsePeriodTo = simpleDateFormat.parse(formatPeriodTo);
    System.out.println(parsePeriodTo);
    ```
    他会自动往后加时间以让设置的日期生效
    2022-05-10
    Tue May 10 00:00:00 CST 2022
    2023-02-01
    Wed Feb 01 00:00:00 CST 2023

    yml:
    ```yaml
    period:
    from: 2022-05-10
    to: 2023-01-32
    ```

    我可能得试试 api 的介绍了。。
    learningman
        8
    learningman  
       2023-01-01 13:55:41 +08:00
    @mylovesaber #7 完整代码给出来
    momocraft
        9
    momocraft  
       2023-01-01 14:02:44 +08:00
    因为你用 yaml. yaml 是这样的

    可以找个能配置的 parser, 或者不用 yaml
    mylovesaber
        10
    mylovesaber  
    OP
       2023-01-01 14:52:44 +08:00
    yaml 读取不对的问题解决了。按照三楼给的方法,这货是会自动匹配日期,发现 string 类型变量值长得跟日期差不多就自动转换成 Date 并补全完整时间信息了,所以先添加一个排除功能的 java 文件到项目中,https://github.com/snakeyaml/snakeyaml/blob/master/src/test/java/examples/resolver/CustomResolver.java

    然后将一楼的:
    Yaml yaml = new Yaml();
    改成:
    Yaml yaml = new Yaml(new Constructor(), new Representer(), new DumperOptions(), new CustomResolver());
    记得 import ,idea 会提醒导入。

    然后我看看这日期合法性怎么搞
    mylovesaber
        11
    mylovesaber  
    OP
       2023-01-01 14:53:21 +08:00
    @cbdyzj 感谢,这东西可用,我再找找怎么验证日期有效性
    mylovesaber
        12
    mylovesaber  
    OP
       2023-01-01 15:03:01 +08:00
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    simpleDateFormat.setLenient(false); //没这个就会自动将不合法的日期按照相差天数自动延后出可用的日期而不是检查日期是否合法了
    try {
    Date parsePeriodFrom = simpleDateFormat.parse(periodFrom);
    System.out.println(parsePeriodFrom);
    } catch (ParseException e) {
    System.out.println("起始日期格式为:yyyy-MM-dd ,例:2022-01-01 ,请检查");
    }


    好了问题解决,感谢各位
    @cbdyzj @learningman
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2340 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 90ms · UTC 16:10 · PVG 00:10 · LAX 09:10 · JFK 12:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.