fix: sub-second resolution `time` attribute (#176)

* fix: sub-second resolution `time` attribute

Fixes parsing of dates like: 2018-04-26T14:48:09.1234Z

Signed-off-by: Matej Vasek <mvasek@redhat.com>

* test: added test for datetime parsing formatting

Signed-off-by: Matej Vasek <mvasek@redhat.com>
This commit is contained in:
Matej Vasek 2020-06-18 16:59:12 +02:00 committed by GitHub
parent fd1c3268d9
commit 7d85d19f1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 1 deletions

View File

@ -40,6 +40,18 @@
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -19,10 +19,16 @@ package io.cloudevents.types;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
public final class Time {
public static final DateTimeFormatter RFC3339_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
public static final DateTimeFormatter RFC3339_DATE_FORMAT = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
.appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
.appendZoneOrOffsetId()
.toFormatter();
public static ZonedDateTime parseTime(String time) throws DateTimeParseException {
return ZonedDateTime.parse(time, RFC3339_DATE_FORMAT);

View File

@ -0,0 +1,53 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.cloudevents.types;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.time.ZonedDateTime;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
public class TimeTest {
@ParameterizedTest
@MethodSource("parseDateArguments")
void testParseAndFormatDate(String ts) {
ZonedDateTime zonedDateTime = Time.parseTime(ts);
assertThat(ts).isEqualTo(zonedDateTime.format(Time.RFC3339_DATE_FORMAT));
}
@Test
void testParseDateOffset() {
assertThat(Time.parseTime("1937-01-01T12:20:27.87+00:20"))
.isEqualTo("1937-01-01T12:00:27.87Z");
}
public static Stream<Arguments> parseDateArguments() {
return Stream.of(
Arguments.of("1985-04-12T23:20:50.52Z"),
Arguments.of("1990-12-31T23:59:00Z"),
Arguments.of("1990-12-31T15:59:00-08:00"),
Arguments.of("1937-01-01T12:00:27.87+00:20")
);
}
}

View File

@ -57,6 +57,15 @@ public class Data {
.withTime(TIME)
.build();
public static final CloudEvent V1_WITH_JSON_DATA_WITH_FRACTIONAL_TIME = CloudEventBuilder.v1()
.withId(ID)
.withType(TYPE)
.withSource(SOURCE)
.withData(DATACONTENTTYPE_JSON, DATASCHEMA, DATA_JSON_SERIALIZED)
.withSubject(SUBJECT)
.withTime(Time.parseTime("2018-04-26T14:48:09.1234Z"))
.build();
public static final CloudEvent V1_WITH_JSON_DATA_WITH_EXT = CloudEventBuilder.v1()
.withId(ID)
.withType(TYPE)

View File

@ -115,6 +115,7 @@ class JsonFormatTest {
Arguments.of(V03_WITH_TEXT_DATA, "v03/base64_text_data.json"),
Arguments.of(V1_MIN, "v1/min.json"),
Arguments.of(V1_WITH_JSON_DATA, "v1/json_data.json"),
Arguments.of(V1_WITH_JSON_DATA_WITH_FRACTIONAL_TIME, "v1/json_data_with_fractional_time.json"),
Arguments.of(V1_WITH_JSON_DATA_WITH_EXT, "v1/json_data_with_ext.json"),
Arguments.of(V1_WITH_XML_DATA, "v1/base64_xml_data.json"),
Arguments.of(V1_WITH_TEXT_DATA, "v1/base64_text_data.json")

View File

@ -0,0 +1,11 @@
{
"specversion": "1.0",
"id": "1",
"type": "mock.test",
"source": "http://localhost/source",
"dataschema": "http://localhost/schema",
"datacontenttype": "application/json",
"data": {},
"subject": "sub",
"time": "2018-04-26T14:48:09.1234Z"
}