YAML, временные метки и SnakeYAML Engine - PullRequest
0 голосов
/ 05 апреля 2020

Я не уверен, как YAML "метки времени" должны быть представлены. Из спецификации YAML 1.2 может показаться, что YAML просто предполагает, что если у вас есть значение в строковом формате, которое выглядит как дата ISO 8601, то оно анализируется как дата, если вы не говорите иначе. Вот пара примеров из spe c:

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

Независимый от языка тип отметки Timestamp для рабочего проекта YAML ™ версии 1.1 (с 2005 года, в настоящее время 15 лет go!) Указывает на необходимость использования специального тега в форме 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-24, так и fooBar: !!timestamp 2020-03-24T12:34:00.333, но SnakeYAML Engine сообщил:

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

Так что же является официальным способом представления даты (особенно локальной даты с YYYY- MM-DD) в YAML, и отражен ли правильный подход в последней спецификации YAML? Поддерживает ли SnakeYAML Engine официальный подход к датам YAML?

1 Ответ

1 голос
/ 06 апреля 2020

Из спецификации YAML 1.2 может показаться, что YAML просто предполагает, что если у вас есть значение в строковом формате, которое выглядит как дата ISO 8601, то оно анализируется как дата, если вы не говорите иначе.

Нет. YAML spe c дает три схемы (Failsafe, JSON и Core), которые должны поддерживаться ; ни один из них не включает тип метки времени. Однако скаляр, похожий на отметку времени , может быть проанализирован как таковой, если используется схема, которая его поддерживает. Spe c только говорит вам, что если вы хотите убедиться, что скаляр не загружен как отметка времени, добавьте к нему префикс !!str.

Так что же является официальным способ представления даты (в частности, локальной даты с YYYY-MM-DD) в YAML.

Определение !!timestamp, которое вы связали, ближе всего к тому, что официальный способ будет быть. Однако репозиторий тегов, содержащий его, не является частью спецификации c, и реализации не обязаны его поддерживать. Кроме того, он определен для устаревшего YAML 1.1.

Это означает, что SnakeYAML вообще не требуется поддерживать временные метки. В приведенном вами примере видно, что поддержка меток времени не включена; В примере реализованы временные метки загрузки. Вы можете изменить этот код для использования с обычным интерфейсом publi c:

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");
...