From 3c9b3ed61628eb0dad60a3f432d37d7e06c95f34 Mon Sep 17 00:00:00 2001 From: Thomas Cederholm Date: Tue, 2 Jun 2026 08:15:44 +0200 Subject: [PATCH] test: Assert date-time format accepts all ISO-8601 fractional precisions The OpenAPI 'date-time' string format delegates to OffsetDateTime.parse, which already accepts everything from second precision through nanosecond precision (and either Z or numeric offset). Pin that behaviour so we can keep emitting Java's natural toString() form on responses without fear of clients sending higher-precision timestamps back to us. --- .../validate/StringIntegerNumberTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/test/java/com/retailsvc/http/validate/StringIntegerNumberTest.java b/src/test/java/com/retailsvc/http/validate/StringIntegerNumberTest.java index fc5d5b19..ee8cc2e5 100644 --- a/src/test/java/com/retailsvc/http/validate/StringIntegerNumberTest.java +++ b/src/test/java/com/retailsvc/http/validate/StringIntegerNumberTest.java @@ -158,6 +158,40 @@ void stringFormatIpv6() { .isEqualTo("format"); } + @Test + void stringFormatDateTimeAcceptsAnyIsoPrecision() { + StringSchema s = + new StringSchema(Set.of(TypeName.STRING), null, null, null, "date-time", null, Map.of()); + assertThatCode(() -> v.validate("2026-01-01T20:00Z", s, "/v")).doesNotThrowAnyException(); + assertThatCode(() -> v.validate("2026-01-01T20:00:00Z", s, "/v")).doesNotThrowAnyException(); + assertThatCode(() -> v.validate("2026-01-01T20:00:00.1Z", s, "/v")).doesNotThrowAnyException(); + assertThatCode(() -> v.validate("2026-01-01T20:00:00.123Z", s, "/v")) + .doesNotThrowAnyException(); + assertThatCode(() -> v.validate("2026-01-01T20:00:00.000000Z", s, "/v")) + .doesNotThrowAnyException(); + assertThatCode(() -> v.validate("2026-01-01T20:00:00.123456789Z", s, "/v")) + .doesNotThrowAnyException(); + assertThatCode(() -> v.validate("2026-01-01T20:00:00+02:00", s, "/v")) + .doesNotThrowAnyException(); + assertThatCode(() -> v.validate("2026-01-01T20:00:00.250-05:30", s, "/v")) + .doesNotThrowAnyException(); + } + + @Test + void stringFormatDateTimeRejectsBadValues() { + StringSchema s = + new StringSchema(Set.of(TypeName.STRING), null, null, null, "date-time", null, Map.of()); + assertThatThrownBy(() -> v.validate("2026-01-01T20:00:00", s, "/v")) + .extracting(t -> ((ValidationException) t).error().keyword()) + .isEqualTo("format"); + assertThatThrownBy(() -> v.validate("2026-01-01 20:00:00Z", s, "/v")) + .extracting(t -> ((ValidationException) t).error().keyword()) + .isEqualTo("format"); + assertThatThrownBy(() -> v.validate("not-a-date", s, "/v")) + .extracting(t -> ((ValidationException) t).error().keyword()) + .isEqualTo("format"); + } + @Test void integerWithMinMax() { IntegerSchema s =