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

2023-01-01 12:22:21 +08:00
 mylovesaber

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>
1947 次点击
所在节点    Java
12 条回复
learningman
2023-01-01 12:26:29 +08:00
你用双引号括上试试
mylovesaber
2023-01-01 12:29:55 +08:00
@learningman 我之前尝试过可以,但如果我本身不希望加上双引号呢?我卡住的地方就是这地方
cbdyzj
2023-01-01 12:30:55 +08:00
learningman
2023-01-01 12:31:52 +08:00
那就拿 Object 再判断呗,如果是 Date 就
var sdf = new SimpleDateFormat("yyyy-MM-dd");
var dateString = sdf.format(date);
fzdwx
2023-01-01 12:36:31 +08:00
`Yaml yaml = new Yaml();`

这是这个包做的附带的功能吧?
mylovesaber
2023-01-01 12:42:50 +08:00
@fzdwx 对,xml 中坐标指定了 snakeyaml
mylovesaber
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
2023-01-01 13:55:41 +08:00
@mylovesaber #7 完整代码给出来
momocraft
2023-01-01 14:02:44 +08:00
因为你用 yaml. yaml 是这样的

可以找个能配置的 parser, 或者不用 yaml
mylovesaber
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
2023-01-01 14:53:21 +08:00
@cbdyzj 感谢,这东西可用,我再找找怎么验证日期有效性
mylovesaber
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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/905904

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX