代码之家  ›  专栏  ›  技术社区  ›  Garret Wilson

YAML、时间戳和SnakeYAML引擎

  •  0
  • Garret Wilson  · 技术社区  · 5 年前

    我不确定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引擎库有一个 example 使用 !!时间戳 方法(例如。 !!timestamp 2020-03-24T12:34:00.333 ),但这是最近的一个变化,我确信这个支持是否已经发布。

    我试了两种形式 fooBar: !!timestamp 2020-03-24 而且 fooBar: !!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引擎是否支持官方的YAML日期方法?

    0 回复  |  直到 5 年前
        1
  •  1
  •   flyx    5 年前

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

    不会。YAML规范给出了三种模式(故障保护、JSON和核心),它们可以 应该 得到支持;它们都不包含时间戳类型。然而,看起来像时间戳的标量 可以 如果使用了支持它的模式,则可以进行这样的分析。规范只告诉您,如果要确保标量是 作为时间戳加载,在其前面加上 !!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");