【问题标题】:YAML, timestamps, and SnakeYAML EngineYAML、时间戳和 SnakeYAML 引擎
【发布时间】:2020-07-17 19:37:55
【问题描述】:

我不确定 YAML“时间戳”应该如何表示。从YAML 1.2 specification 看来,YAML 似乎只是假设如果您有一个看起来像 ISO 8601 日期的字符串格式的值,那么除非您另有说明,否则它将被解析为日期。以下是规范中的几个示例:

date: 2002-12-14
not-date: !!str 2002-04-28

Timestamp Language-Independent Type for YAML™ Version 1.1 工作草案(从 2005 年开始,目前是 15 年前!)似乎表明应该使用 tag:yaml.org,2002:timestamp 形式的特殊标签。它还表示!!timestamp 的简写。

在 Java 中使用 SnakeYAML Engine v2.0 (org.snakeyaml:snakeyaml-engine:2.0) 我尝试解析 2002-12-14 表单,得到一个字符串作为解析值,而不是任何类型的日期对象。我看到 SnakeYAML 引擎存储库有一个使用 !!timestamp 方法的 example(例如 !!timestamp 2020-03-24T12:34:00.333),但这是最近的更改,我确定此支持是否已经发布。

我尝试了fooBar: !!timestamp 2020-03-24fooBar: !!timestamp 2020-03-24T12:34:00.333 两种形式,但 SnakeYAML 引擎报告:

could not determine a constructor for the tag tag:yaml.org,2002:timestamp

那么在 YAML 中表示日期(特别是带有 YYYY-MM-DD 的本地日期)的官方方式是什么,最新的 YAML 规范中是否反映了正确的方式? SnakeYAML Engine 是否支持官方的 YAML 日期方法?

【问题讨论】:

    标签: java yaml snakeyaml


    【解决方案1】:

    从 YAML 1.2 规范来看,YAML 似乎只是假设如果您有一个看起来像 ISO 8601 日期的字符串格式的值,那么除非您另有说明,否则它将被解析为日期。

    没有。 YAML 规范给出了三种应该支持的模式(Failsafe、JSON 和 Core);它们都不包含时间戳类型。但是,如果使用支持它的模式,则可以像时间戳 一样解析标量。该规范仅告诉您,如果您想确保标量作为时间戳加载,请在其前面加上!!str

    那么在 YAML 中表示日期(特别是带有 YYYY-MM-DD 的本地日期)的官方方式是什么。

    您链接的!!timestamp 定义最接近官方方式。但是,包含它的标签存储库不是规范的一部分,并且不需要实现来支持它。此外,它是为过时的 YAML 1.1 定义的。

    这意味着 SnakeYAML 根本不需要支持时间戳。您可以在给出的示例中看到不包括时间戳支持;该示例实现了加载时间戳本身。您可以修改该代码以与普通公共接口一起使用:

    class TimestampConstructor extends Constructor {
        public static final Pattern TIMESTAMP = Pattern
                .compile("^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\\.[0-9]*)?(?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$");
        public static final Tag TAG = new Tag(Tag.PREFIX + "timestamp");
    
    
        public TimestampConstructor() {
            this.yamlConstructors.put(TAG, new ConstructTimestamp());
        }
    
        private class ConstructTimestamp extends AbstractConstruct {
            public Object construct(Node node) {
                String val = (String) constructScalar(node);
                return LocalDateTime.parse(val);
            }
        }
    }
    

    然后,像这样使用它:

    Yaml yaml = new Yaml(new TimestampConstructor());
    yaml.addImplicitResolver(TimestampConstructor.TAG,
            TimestampConstructor.PATTERN, "0123456789");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-08
      • 2020-05-24
      • 2013-09-20
      • 2018-12-26
      • 1970-01-01
      • 2014-04-11
      • 2020-05-16
      • 1970-01-01
      相关资源
      最近更新 更多