YAML、时间戳和SnakeYAML引擎

huangapple go评论96阅读模式
英文:

YAML, timestamps, and SnakeYAML Engine

问题

我不确定 YAML "timestamps" 应该如何表示。根据 YAML 1.2 规范,似乎 YAML 只是假设如果您有一个看起来像 ISO 8601 日期的字符串格式值,那么它会被解析为日期,除非您另有说明。以下是规范中的一些示例:

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

YAML™ 版本 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 Engine 仓库有一个示例使用了 !!timestamp 方法(例如 !!timestamp 2020-03-24T12:34:00.333),但这是一个最近的更改,我不确定这个支持是否已经发布。

我尝试了 fooBar: !!timestamp 2020-03-24fooBar: !!timestamp 2020-03-24T12:34:00.333 这两种形式,但 SnakeYAML Engine 报告了以下错误:

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

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

英文:

I'm unsure how YAML "timestamps" are supposed to be represented. From the YAML 1.2 specification, it would seem that YAML just assumes that if you have a value in string format that looks like an ISO 8601 date, then it is parsed as a date unless you say differently. Here are a couple of examples from the spec:

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

The Timestamp Language-Independent Type for YAML™ Version 1.1 working draft (from 2005, currently 15 years ago!) seems to indicate that a special tag in the form tag:yaml.org,2002:timestamp should be used. It also indicates a shorthand of !!timestamp.

In Java using SnakeYAML Engine v2.0 (org.snakeyaml:snakeyaml-engine:2.0) I tried parsing the 2002-12-14 form, and got a string as the parsed value, not any sort of date object. I see that the SnakeYAML Engine repository has an example using the !!timestamp approach (e.g. !!timestamp 2020-03-24T12:34:00.333), but this is a recent change and I'm sure if this support has been released yet.

I tried both the form fooBar: !!timestamp 2020-03-24 and also fooBar: !!timestamp 2020-03-24T12:34:00.333, but SnakeYAML Engine reported:

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

So what is the official way to represent a date (specifically a local date with YYYY-MM-DD) in YAML, and is the correct approach reflected in the latest YAML specification? Does SnakeYAML Engine support the official YAML date approach?

答案1

得分: 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");
英文:

> From the YAML 1.2 specification, it would seem that YAML just assumes that if you have a value in string format that looks like an ISO 8601 date, then it is parsed as a date unless you say differently.

No. The YAML spec gives three schemas (Failsafe, JSON and Core) that should be supported; none of them includes a timestamp type. However, a scalar looking like a timestamp can be parsed as such if a schema is used that supports it. The spec only tells you that if you want to ensure that a scalar is not loaded as timestamp, prefix it with !!str.

> So what is the official way to represent a date (specifically a local date with YYYY-MM-DD) in YAML.

The !!timestamp definition you linked is closest to what an official way would be. However, the tag repository containing it is not part of the spec and implementations are not required to support it. Furthermore, it is defined for outdated YAML 1.1.

This means that SnakeYAML isn't required to support timestamps at all. You can see in the example you give that timestamp support is not included; the example implements loading timestamps itself. You can modify that code to use with the normal public interface:

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);
        }
    }
}

Then, use it like this:

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

huangapple
  • 本文由 发表于 2020年4月6日 04:28:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/61049072.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定