From cb86fcd3666f9ce45b6528de42a529f45d8ceb90 Mon Sep 17 00:00:00 2001 From: Ian Botsford <83236726+ianbotsf@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:51:30 +0000 Subject: [PATCH] add ISO_8601_FULL timestamp format for untruncated precision --- .changes/29e93882-7346-4a2f-bbcd-1cdf478a3b10.json | 5 +++++ runtime/runtime-core/api/runtime-core.api | 1 + .../aws/smithy/kotlin/runtime/time/TimestampFormat.kt | 5 +++++ .../aws/smithy/kotlin/runtime/time/InstantTest.kt | 11 +++++++++++ .../src/aws/smithy/kotlin/runtime/time/InstantJVM.kt | 1 + .../src/aws/smithy/kotlin/runtime/serde/Parsers.kt | 1 + .../kotlin/runtime/serde/json/JsonSerializer.kt | 1 + 7 files changed, 25 insertions(+) create mode 100644 .changes/29e93882-7346-4a2f-bbcd-1cdf478a3b10.json diff --git a/.changes/29e93882-7346-4a2f-bbcd-1cdf478a3b10.json b/.changes/29e93882-7346-4a2f-bbcd-1cdf478a3b10.json new file mode 100644 index 000000000..b7d63fa80 --- /dev/null +++ b/.changes/29e93882-7346-4a2f-bbcd-1cdf478a3b10.json @@ -0,0 +1,5 @@ +{ + "id": "29e93882-7346-4a2f-bbcd-1cdf478a3b10", + "type": "feature", + "description": "Add new `ISO_8601_FULL` timestamp format for untruncated precision" +} \ No newline at end of file diff --git a/runtime/runtime-core/api/runtime-core.api b/runtime/runtime-core/api/runtime-core.api index 33b6c8e63..add320979 100644 --- a/runtime/runtime-core/api/runtime-core.api +++ b/runtime/runtime-core/api/runtime-core.api @@ -2211,6 +2211,7 @@ public final class aws/smithy/kotlin/runtime/time/TimestampFormat : java/lang/En public static final field ISO_8601 Laws/smithy/kotlin/runtime/time/TimestampFormat; public static final field ISO_8601_CONDENSED Laws/smithy/kotlin/runtime/time/TimestampFormat; public static final field ISO_8601_CONDENSED_DATE Laws/smithy/kotlin/runtime/time/TimestampFormat; + public static final field ISO_8601_FULL Laws/smithy/kotlin/runtime/time/TimestampFormat; public static final field RFC_5322 Laws/smithy/kotlin/runtime/time/TimestampFormat; public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Laws/smithy/kotlin/runtime/time/TimestampFormat; diff --git a/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/time/TimestampFormat.kt b/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/time/TimestampFormat.kt index 66ae0217c..18d005b66 100644 --- a/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/time/TimestampFormat.kt +++ b/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/time/TimestampFormat.kt @@ -27,6 +27,11 @@ public enum class TimestampFormat { */ ISO_8601_CONDENSED_DATE, + /** + * ISO-8601/RFC5399 timestamp including fractional seconds at arbitrary (i.e., untruncated) precision + */ + ISO_8601_FULL, + /** * RFC-5322/2822/822 IMF timestamp * See: https://tools.ietf.org/html/rfc5322 diff --git a/runtime/runtime-core/common/test/aws/smithy/kotlin/runtime/time/InstantTest.kt b/runtime/runtime-core/common/test/aws/smithy/kotlin/runtime/time/InstantTest.kt index 2f692d567..4c96d68dc 100644 --- a/runtime/runtime-core/common/test/aws/smithy/kotlin/runtime/time/InstantTest.kt +++ b/runtime/runtime-core/common/test/aws/smithy/kotlin/runtime/time/InstantTest.kt @@ -37,6 +37,7 @@ class InstantTest { val expectedIso8601: String, val expectedIso8601Cond: String, val expectedIso8601CondDate: String, + val expectedIso8601Full: String = expectedIso8601, ) private val iso8601Tests = listOf( @@ -80,6 +81,16 @@ class InstantTest { Iso8601FmtTest(1604605357, 0, "2020-11-05T19:42:37Z", "20201105T194237Z", "20201105"), Iso8601FmtTest(1604558257, 0, "2020-11-05T06:37:37Z", "20201105T063737Z", "20201105"), Iso8601FmtTest(1604650057, 0, "2020-11-06T08:07:37Z", "20201106T080737Z", "20201106"), + + // Test full-precision ISO 8601 + Iso8601FmtTest( + 1604604157, + 123_456_789, + "2020-11-05T19:22:37.123456Z", + "20201105T192237Z", + "20201105", + "2020-11-05T19:22:37.123456789Z", + ), ) private val iso8601Forms = mapOf( diff --git a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/time/InstantJVM.kt b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/time/InstantJVM.kt index 7ed814ae3..b90a57de8 100644 --- a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/time/InstantJVM.kt +++ b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/time/InstantJVM.kt @@ -69,6 +69,7 @@ public actual class Instant(internal val value: jtInstant) : Comparable TimestampFormat.ISO_8601 -> ISO_INSTANT.format(value.truncatedTo(ChronoUnit.MICROS)) TimestampFormat.ISO_8601_CONDENSED -> ISO_8601_CONDENSED.format(value) TimestampFormat.ISO_8601_CONDENSED_DATE -> ISO_8601_CONDENSED_DATE.format(value) + TimestampFormat.ISO_8601_FULL -> ISO_INSTANT.format(value) TimestampFormat.RFC_5322 -> RFC_5322_FIXED_DATE_TIME.format(ZonedDateTime.ofInstant(value, ZoneOffset.UTC)) TimestampFormat.EPOCH_SECONDS -> { val sb = StringBuffer("$epochSeconds") diff --git a/runtime/serde/common/src/aws/smithy/kotlin/runtime/serde/Parsers.kt b/runtime/serde/common/src/aws/smithy/kotlin/runtime/serde/Parsers.kt index 3991f0f1a..d5277fd3d 100644 --- a/runtime/serde/common/src/aws/smithy/kotlin/runtime/serde/Parsers.kt +++ b/runtime/serde/common/src/aws/smithy/kotlin/runtime/serde/Parsers.kt @@ -43,6 +43,7 @@ public fun String.parseBigDecimal(): Result = parse(::BigDecimal) private fun String.toTimestamp(fmt: TimestampFormat): Instant = when (fmt) { TimestampFormat.ISO_8601_CONDENSED, TimestampFormat.ISO_8601_CONDENSED_DATE, + TimestampFormat.ISO_8601_FULL, TimestampFormat.ISO_8601, -> Instant.fromIso8601(this) diff --git a/runtime/serde/serde-json/common/src/aws/smithy/kotlin/runtime/serde/json/JsonSerializer.kt b/runtime/serde/serde-json/common/src/aws/smithy/kotlin/runtime/serde/json/JsonSerializer.kt index 139f3aa3c..f3aaf482e 100644 --- a/runtime/serde/serde-json/common/src/aws/smithy/kotlin/runtime/serde/json/JsonSerializer.kt +++ b/runtime/serde/serde-json/common/src/aws/smithy/kotlin/runtime/serde/json/JsonSerializer.kt @@ -297,6 +297,7 @@ public class JsonSerializer : TimestampFormat.ISO_8601, TimestampFormat.ISO_8601_CONDENSED, TimestampFormat.ISO_8601_CONDENSED_DATE, + TimestampFormat.ISO_8601_FULL, TimestampFormat.RFC_5322, -> jsonWriter.writeValue(value.format(format)) }