From c8e275714af960d4d6e5f364d8c9459a4c9e517d Mon Sep 17 00:00:00 2001 From: Luc Girardin Date: Sun, 13 Apr 2025 17:15:23 +0200 Subject: [PATCH 1/9] Added LocalTime.Formats.ISO_BASIC (ISO 8601 basic format) --- core/common/src/LocalTime.kt | 12 ++++++++++++ core/common/src/format/LocalTimeFormat.kt | 16 ++++++++++++++++ core/common/test/samples/LocalTimeSamples.kt | 14 ++++++++++++++ core/commonKotlin/src/LocalTime.kt | 1 + core/jvm/src/LocalTimeJvm.kt | 1 + 5 files changed, 44 insertions(+) diff --git a/core/common/src/LocalTime.kt b/core/common/src/LocalTime.kt index 7cf01459b..8267f3eb8 100644 --- a/core/common/src/LocalTime.kt +++ b/core/common/src/LocalTime.kt @@ -197,6 +197,18 @@ public expect class LocalTime : Comparable { * [kotlinx.datetime.format.DateTimeFormat] for [LocalTime] values. */ public object Formats { + /** + * ISO 8601 basic format. + * + * Examples: `1234`, `123456`, `123456.789`, `123456.1234`. + * + * When formatting, seconds are always included, even if they are zero. + * Fractional parts of the second are included if non-zero. + * + * @sample kotlinx.datetime.test.samples.LocalTimeSamples.Formats.isoBasic + */ + public val ISO_BASIC: DateTimeFormat + /** * ISO 8601 extended format. * diff --git a/core/common/src/format/LocalTimeFormat.kt b/core/common/src/format/LocalTimeFormat.kt index d1854e124..cbb59dfc2 100644 --- a/core/common/src/format/LocalTimeFormat.kt +++ b/core/common/src/format/LocalTimeFormat.kt @@ -279,6 +279,22 @@ internal class LocalTimeFormat(override val actualFormat: CachedFormatStructure< } // these are constants so that the formats are not recreated every time they are used +internal val ISO_TIME_BASIC by lazy { + LocalTimeFormat.build { + hour() + minute() + alternativeParsing({ + // intentionally empty + }) { + second() + optional { + char('.') + secondFraction(1, 9) + } + } + } +} + internal val ISO_TIME by lazy { LocalTimeFormat.build { hour() diff --git a/core/common/test/samples/LocalTimeSamples.kt b/core/common/test/samples/LocalTimeSamples.kt index 3bbb19e89..33132da24 100644 --- a/core/common/test/samples/LocalTimeSamples.kt +++ b/core/common/test/samples/LocalTimeSamples.kt @@ -280,6 +280,20 @@ class LocalTimeSamples { } class Formats { + @Test + fun isoBasic() { + // Parsing and formatting LocalTime values using the ISO_BASIC format + val timeWithNanoseconds = LocalTime(hour = 8, minute = 30, second = 15, nanosecond = 160_000_000) + val timeWithSeconds = LocalTime(hour = 8, minute = 30, second = 15) + val timeWithoutSeconds = LocalTime(hour = 8, minute = 30) + check(LocalTime.Formats.ISO_BASIC.parse("083015.16") == timeWithNanoseconds) + check(LocalTime.Formats.ISO_BASIC.parse("083015") == timeWithSeconds) + check(LocalTime.Formats.ISO_BASIC.parse("0830") == timeWithoutSeconds) + check(LocalTime.Formats.ISO_BASIC.format(timeWithNanoseconds) == "083015.16") + check(LocalTime.Formats.ISO_BASIC.format(timeWithSeconds) == "083015") + check(LocalTime.Formats.ISO_BASIC.format(timeWithoutSeconds) == "083000") + } + @Test fun iso() { // Parsing and formatting LocalTime values using the ISO format diff --git a/core/commonKotlin/src/LocalTime.kt b/core/commonKotlin/src/LocalTime.kt index 28ebd78df..fe3077e8e 100644 --- a/core/commonKotlin/src/LocalTime.kt +++ b/core/commonKotlin/src/LocalTime.kt @@ -84,6 +84,7 @@ public actual class LocalTime actual constructor( } public actual object Formats { + public actual val ISO_BASIC: DateTimeFormat get() = ISO_TIME_BASIC public actual val ISO: DateTimeFormat get() = ISO_TIME } diff --git a/core/jvm/src/LocalTimeJvm.kt b/core/jvm/src/LocalTimeJvm.kt index 98f42011b..dd11650a5 100644 --- a/core/jvm/src/LocalTimeJvm.kt +++ b/core/jvm/src/LocalTimeJvm.kt @@ -88,6 +88,7 @@ public actual class LocalTime internal constructor( } public actual object Formats { + public actual val ISO_BASIC: DateTimeFormat get() = ISO_TIME_BASIC public actual val ISO: DateTimeFormat get() = ISO_TIME } From cca454f037ff560d850007fb096cedb66d95ebde Mon Sep 17 00:00:00 2001 From: Luc Girardin Date: Mon, 14 Apr 2025 22:21:30 +0200 Subject: [PATCH 2/9] Corrected LocalTime.Formats.ISO_BASIC with leading 'T' --- core/common/src/format/LocalTimeFormat.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/core/common/src/format/LocalTimeFormat.kt b/core/common/src/format/LocalTimeFormat.kt index cbb59dfc2..405ae930c 100644 --- a/core/common/src/format/LocalTimeFormat.kt +++ b/core/common/src/format/LocalTimeFormat.kt @@ -281,6 +281,7 @@ internal class LocalTimeFormat(override val actualFormat: CachedFormatStructure< // these are constants so that the formats are not recreated every time they are used internal val ISO_TIME_BASIC by lazy { LocalTimeFormat.build { + char('T') hour() minute() alternativeParsing({ From 8d17ebb787fce003bbeed4005f6ee8ce884b10b1 Mon Sep 17 00:00:00 2001 From: Luc Girardin Date: Mon, 14 Apr 2025 22:23:06 +0200 Subject: [PATCH 3/9] Corrected LocalTime.Formats.ISO_BASIC with leading 'T' --- core/common/test/samples/LocalTimeSamples.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/common/test/samples/LocalTimeSamples.kt b/core/common/test/samples/LocalTimeSamples.kt index 33132da24..28b5fdbe4 100644 --- a/core/common/test/samples/LocalTimeSamples.kt +++ b/core/common/test/samples/LocalTimeSamples.kt @@ -286,12 +286,12 @@ class LocalTimeSamples { val timeWithNanoseconds = LocalTime(hour = 8, minute = 30, second = 15, nanosecond = 160_000_000) val timeWithSeconds = LocalTime(hour = 8, minute = 30, second = 15) val timeWithoutSeconds = LocalTime(hour = 8, minute = 30) - check(LocalTime.Formats.ISO_BASIC.parse("083015.16") == timeWithNanoseconds) - check(LocalTime.Formats.ISO_BASIC.parse("083015") == timeWithSeconds) - check(LocalTime.Formats.ISO_BASIC.parse("0830") == timeWithoutSeconds) - check(LocalTime.Formats.ISO_BASIC.format(timeWithNanoseconds) == "083015.16") - check(LocalTime.Formats.ISO_BASIC.format(timeWithSeconds) == "083015") - check(LocalTime.Formats.ISO_BASIC.format(timeWithoutSeconds) == "083000") + check(LocalTime.Formats.ISO_BASIC.parse("T083015.16") == timeWithNanoseconds) + check(LocalTime.Formats.ISO_BASIC.parse("T083015") == timeWithSeconds) + check(LocalTime.Formats.ISO_BASIC.parse("T0830") == timeWithoutSeconds) + check(LocalTime.Formats.ISO_BASIC.format(timeWithNanoseconds) == "T083015.16") + check(LocalTime.Formats.ISO_BASIC.format(timeWithSeconds) == "T083015") + check(LocalTime.Formats.ISO_BASIC.format(timeWithoutSeconds) == "T083000") } @Test From 8cddb49ae97629ef9b5bbbf40d0e4e4c0606ee2d Mon Sep 17 00:00:00 2001 From: Luc Girardin Date: Sat, 26 Apr 2025 14:22:45 +0200 Subject: [PATCH 4/9] Format is case-insensitive --- core/common/src/format/LocalTimeFormat.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/common/src/format/LocalTimeFormat.kt b/core/common/src/format/LocalTimeFormat.kt index 405ae930c..b8df2334d 100644 --- a/core/common/src/format/LocalTimeFormat.kt +++ b/core/common/src/format/LocalTimeFormat.kt @@ -281,7 +281,7 @@ internal class LocalTimeFormat(override val actualFormat: CachedFormatStructure< // these are constants so that the formats are not recreated every time they are used internal val ISO_TIME_BASIC by lazy { LocalTimeFormat.build { - char('T') + alternativeParsing({ char('t') }) { char('T') } hour() minute() alternativeParsing({ From 76a093a6af6007f64e01d8d1f666556806e30209 Mon Sep 17 00:00:00 2001 From: Luc Girardin Date: Sat, 26 Apr 2025 14:25:33 +0200 Subject: [PATCH 5/9] ISO_BASIC starts with T --- core/common/src/LocalTime.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/common/src/LocalTime.kt b/core/common/src/LocalTime.kt index 8267f3eb8..379d81853 100644 --- a/core/common/src/LocalTime.kt +++ b/core/common/src/LocalTime.kt @@ -200,7 +200,7 @@ public expect class LocalTime : Comparable { /** * ISO 8601 basic format. * - * Examples: `1234`, `123456`, `123456.789`, `123456.1234`. + * Examples: `T1234`, `T123456`, `T123456.789`, `T123456.1234`. * * When formatting, seconds are always included, even if they are zero. * Fractional parts of the second are included if non-zero. From 8075aa0df633982449fa57df46e7da4254c9af7e Mon Sep 17 00:00:00 2001 From: Luc Girardin Date: Thu, 1 May 2025 07:35:30 +0200 Subject: [PATCH 6/9] Added ISO_BASIC to API --- core/api/kotlinx-datetime.api | 1 + core/api/kotlinx-datetime.klib.api | 2 ++ 2 files changed, 3 insertions(+) diff --git a/core/api/kotlinx-datetime.api b/core/api/kotlinx-datetime.api index e5429a44d..c9a320ddd 100644 --- a/core/api/kotlinx-datetime.api +++ b/core/api/kotlinx-datetime.api @@ -494,6 +494,7 @@ public final class kotlinx/datetime/LocalTime$Companion { public final class kotlinx/datetime/LocalTime$Formats { public static final field INSTANCE Lkotlinx/datetime/LocalTime$Formats; public final fun getISO ()Lkotlinx/datetime/format/DateTimeFormat; + public final fun getISO_BASIC ()Lkotlinx/datetime/format/DateTimeFormat; } public final class kotlinx/datetime/LocalTimeKt { diff --git a/core/api/kotlinx-datetime.klib.api b/core/api/kotlinx-datetime.klib.api index 2fb3de669..2a875ecb9 100644 --- a/core/api/kotlinx-datetime.klib.api +++ b/core/api/kotlinx-datetime.klib.api @@ -480,6 +480,8 @@ final class kotlinx.datetime/LocalTime : kotlin/Comparable(): kotlinx.datetime.format/DateTimeFormat // kotlinx.datetime/LocalTime.Formats.ISO.|(){}[0] + final val ISO_BASIC // kotlinx.datetime/LocalTime.Formats.ISO_BASIC|{}ISO_BASIC[0] + final fun (): kotlinx.datetime.format/DateTimeFormat // kotlinx.datetime/LocalTime.Formats.ISO_BASIC.|(){}[0] } } From 8177fe6f0d5b4787595b6c51315ada0264a51323 Mon Sep 17 00:00:00 2001 From: Luc Girardin Date: Thu, 1 May 2025 08:25:00 +0200 Subject: [PATCH 7/9] Added tests for ISO_BASIC --- core/api/kotlinx-datetime.api | 1 + core/api/kotlinx-datetime.klib.api | 2 ++ core/common/src/LocalDateTime.kt | 19 ++++++++++ core/common/src/format/LocalDateTimeFormat.kt | 7 ++++ core/common/src/format/LocalTimeFormat.kt | 4 ++- .../test/format/LocalDateTimeFormatTest.kt | 35 +++++++++++++++++++ core/common/test/samples/LocalTimeSamples.kt | 2 +- core/commonKotlin/src/LocalDateTime.kt | 1 + core/jvm/src/LocalDateTimeJvm.kt | 1 + 9 files changed, 70 insertions(+), 2 deletions(-) diff --git a/core/api/kotlinx-datetime.api b/core/api/kotlinx-datetime.api index c9a320ddd..f950edbee 100644 --- a/core/api/kotlinx-datetime.api +++ b/core/api/kotlinx-datetime.api @@ -449,6 +449,7 @@ public final class kotlinx/datetime/LocalDateTime$Companion { public final class kotlinx/datetime/LocalDateTime$Formats { public static final field INSTANCE Lkotlinx/datetime/LocalDateTime$Formats; public final fun getISO ()Lkotlinx/datetime/format/DateTimeFormat; + public final fun getISO_BASIC ()Lkotlinx/datetime/format/DateTimeFormat; } public final class kotlinx/datetime/LocalDateTimeKt { diff --git a/core/api/kotlinx-datetime.klib.api b/core/api/kotlinx-datetime.klib.api index 2a875ecb9..ef5ca19e5 100644 --- a/core/api/kotlinx-datetime.klib.api +++ b/core/api/kotlinx-datetime.klib.api @@ -444,6 +444,8 @@ final class kotlinx.datetime/LocalDateTime : kotlin/Comparable(): kotlinx.datetime.format/DateTimeFormat // kotlinx.datetime/LocalDateTime.Formats.ISO.|(){}[0] + final val ISO_BASIC // kotlinx.datetime/LocalDateTime.Formats.ISO_BASIC|{}ISO_BASIC[0] + final fun (): kotlinx.datetime.format/DateTimeFormat // kotlinx.datetime/LocalDateTime.Formats.ISO_BASIC.|(){}[0] } } diff --git a/core/common/src/LocalDateTime.kt b/core/common/src/LocalDateTime.kt index 8e5085ca4..e425906e4 100644 --- a/core/common/src/LocalDateTime.kt +++ b/core/common/src/LocalDateTime.kt @@ -194,6 +194,25 @@ public expect class LocalDateTime : Comparable { * @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.Formats.iso */ public val ISO: DateTimeFormat + + /** + * ISO 8601 basic format. + * + * Examples of datetime in ISO 8601 format: + * - `20200830T1843` + * - `+120200830T184300` + * - `00000830T184300.5` + * - `-00010830T184300.123456789` + * + * When formatting, seconds are included, only if they are non-zero. + * Fractional parts of the second are included if non-zero. + * + * See ISO-8601-1:2019, 5.4.2.1b), the version without the offset, together with + * [LocalDate.Formats.ISO_BASIC] and [LocalTime.Formats.ISO_BASIC]. + * + * @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.Formats.basicIso + */ + public val ISO_BASIC: DateTimeFormat } /** diff --git a/core/common/src/format/LocalDateTimeFormat.kt b/core/common/src/format/LocalDateTimeFormat.kt index 8e97ea607..51511606e 100644 --- a/core/common/src/format/LocalDateTimeFormat.kt +++ b/core/common/src/format/LocalDateTimeFormat.kt @@ -82,4 +82,11 @@ internal val ISO_DATETIME by lazy { } } +internal val ISO_DATETIME_BASIC by lazy { + LocalDateTimeFormat.build { + date(ISO_DATE_BASIC) + time(ISO_TIME_BASIC) + } +} + private val emptyIncompleteLocalDateTime = IncompleteLocalDateTime() diff --git a/core/common/src/format/LocalTimeFormat.kt b/core/common/src/format/LocalTimeFormat.kt index b8df2334d..5f20840e5 100644 --- a/core/common/src/format/LocalTimeFormat.kt +++ b/core/common/src/format/LocalTimeFormat.kt @@ -287,7 +287,9 @@ internal val ISO_TIME_BASIC by lazy { alternativeParsing({ // intentionally empty }) { - second() + optional { + second() + } optional { char('.') secondFraction(1, 9) diff --git a/core/common/test/format/LocalDateTimeFormatTest.kt b/core/common/test/format/LocalDateTimeFormatTest.kt index 32ab5596e..e31c68a58 100644 --- a/core/common/test/format/LocalDateTimeFormatTest.kt +++ b/core/common/test/format/LocalDateTimeFormatTest.kt @@ -224,6 +224,41 @@ class LocalDateTimeFormatTest { test(dateTimes, LocalDateTime.Formats.ISO) } + @Test + fun testBasicIso() { + val dateTimes = buildMap>> { + put(LocalDateTime(2008, 7, 5, 0, 0, 0, 0), ("20080705T0000" to setOf("20080705T0000"))) + put(LocalDateTime(2007, 12, 31, 1, 0, 0, 0), ("20071231T0100" to setOf("20071231t010000"))) + put(LocalDateTime(999, 11, 30, 23, 0, 0, 0), ("09991130T2300" to setOf())) + put(LocalDateTime(-1, 1, 2, 0, 1, 0, 0), ("-00010102T0001" to setOf())) + put(LocalDateTime(9999, 10, 31, 12, 30, 0, 0), ("99991031T1230" to setOf())) + put(LocalDateTime(-9999, 9, 30, 23, 59, 0, 0), ("-99990930T2359" to setOf())) + put(LocalDateTime(10000, 8, 1, 0, 0, 1, 0), ("+100000801T000001" to setOf())) + put(LocalDateTime(-10000, 7, 1, 0, 0, 59, 0), ("-100000701T000059" to setOf())) + put(LocalDateTime(123456, 6, 1, 13, 44, 0, 0), ("+1234560601T1344" to setOf())) + put(LocalDateTime(-123456, 5, 1, 13, 44, 0, 0), ("-1234560501T1344" to setOf())) + put(LocalDateTime(123456, 6, 1, 0, 0, 0, 100000000), ("+1234560601T0000.1" to setOf("+1234560601T000000.1", "+1234560601T000000.10", "+1234560601T000000.100"))) + put(LocalDateTime(-123456, 5, 1, 0, 0, 0, 10000000), ("-1234560501T0000.01" to setOf("-1234560501T000000.01"))) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 1000000), ("20220102T0000.001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 100000), ("20220102T0000.0001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 10000), ("20220102T0000.00001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 1000), ("20220102T0000.000001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 100), ("20220102T0000.0000001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 10), ("20220102T0000.00000001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 1), ("20220102T0000.000000001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 999999999), ("20220102T0000.999999999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 99999999), ("20220102T0000.099999999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 9999999), ("20220102T0000.009999999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 999999), ("20220102T0000.000999999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 99999), ("20220102T0000.000099999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 9999), ("20220102T0000.000009999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 999), ("20220102T0000.000000999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 99), ("20220102T0000.000000099" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 9), ("20220102T0000.000000009" to setOf())) + } + test(dateTimes, LocalDateTime.Formats.ISO_BASIC) + } + @Test fun testDoc() { val dateTime = LocalDateTime(2020, 8, 30, 18, 43, 13, 0) diff --git a/core/common/test/samples/LocalTimeSamples.kt b/core/common/test/samples/LocalTimeSamples.kt index 28b5fdbe4..7780a5b36 100644 --- a/core/common/test/samples/LocalTimeSamples.kt +++ b/core/common/test/samples/LocalTimeSamples.kt @@ -291,7 +291,7 @@ class LocalTimeSamples { check(LocalTime.Formats.ISO_BASIC.parse("T0830") == timeWithoutSeconds) check(LocalTime.Formats.ISO_BASIC.format(timeWithNanoseconds) == "T083015.16") check(LocalTime.Formats.ISO_BASIC.format(timeWithSeconds) == "T083015") - check(LocalTime.Formats.ISO_BASIC.format(timeWithoutSeconds) == "T083000") + check(LocalTime.Formats.ISO_BASIC.format(timeWithoutSeconds) == "T0830") } @Test diff --git a/core/commonKotlin/src/LocalDateTime.kt b/core/commonKotlin/src/LocalDateTime.kt index 9375ae91b..c23447fb9 100644 --- a/core/commonKotlin/src/LocalDateTime.kt +++ b/core/commonKotlin/src/LocalDateTime.kt @@ -33,6 +33,7 @@ public actual constructor(public actual val date: LocalDate, public actual val t public actual object Formats { public actual val ISO: DateTimeFormat = ISO_DATETIME + public actual val ISO_BASIC: DateTimeFormat = ISO_DATETIME_BASIC } public actual constructor(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int, nanosecond: Int) : diff --git a/core/jvm/src/LocalDateTimeJvm.kt b/core/jvm/src/LocalDateTimeJvm.kt index 235be9071..c6c419cb4 100644 --- a/core/jvm/src/LocalDateTimeJvm.kt +++ b/core/jvm/src/LocalDateTimeJvm.kt @@ -110,6 +110,7 @@ public actual class LocalDateTime internal constructor( public actual object Formats { public actual val ISO: DateTimeFormat = ISO_DATETIME + public actual val ISO_BASIC: DateTimeFormat = ISO_DATETIME_BASIC } private fun writeReplace(): Any = Ser(Ser.DATE_TIME_TAG, this) From a40381717975d472a9185496cb725bd8e178d8fc Mon Sep 17 00:00:00 2001 From: Luc Girardin Date: Fri, 2 May 2025 07:30:11 +0200 Subject: [PATCH 8/9] a) is the basic format --- core/common/src/LocalDateTime.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/common/src/LocalDateTime.kt b/core/common/src/LocalDateTime.kt index e425906e4..be97f0451 100644 --- a/core/common/src/LocalDateTime.kt +++ b/core/common/src/LocalDateTime.kt @@ -207,7 +207,7 @@ public expect class LocalDateTime : Comparable { * When formatting, seconds are included, only if they are non-zero. * Fractional parts of the second are included if non-zero. * - * See ISO-8601-1:2019, 5.4.2.1b), the version without the offset, together with + * See ISO-8601-1:2019, 5.4.2.1a), the version without the offset, together with * [LocalDate.Formats.ISO_BASIC] and [LocalTime.Formats.ISO_BASIC]. * * @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.Formats.basicIso From deefb8d30c429185c96d49935917d9341d7f74ee Mon Sep 17 00:00:00 2001 From: Luc Girardin Date: Fri, 2 May 2025 07:47:21 +0200 Subject: [PATCH 9/9] Fractions of a second are only emitted together with the second value itself, even if it is zero. --- core/common/src/LocalTime.kt | 2 ++ core/common/src/format/LocalTimeFormat.kt | 8 ++--- .../test/format/LocalDateTimeFormatTest.kt | 36 +++++++++---------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/core/common/src/LocalTime.kt b/core/common/src/LocalTime.kt index 379d81853..6092b5b5a 100644 --- a/core/common/src/LocalTime.kt +++ b/core/common/src/LocalTime.kt @@ -205,6 +205,7 @@ public expect class LocalTime : Comparable { * When formatting, seconds are always included, even if they are zero. * Fractional parts of the second are included if non-zero. * + * @see LocalDateTime.Formats.ISO_BASIC * @sample kotlinx.datetime.test.samples.LocalTimeSamples.Formats.isoBasic */ public val ISO_BASIC: DateTimeFormat @@ -227,6 +228,7 @@ public expect class LocalTime : Comparable { * We *forbid* using the time designator `T` to allow for a predictable composition of formats: * see the note at the end of rule 5.3.5. * + * @see LocalDateTime.Formats.ISO * @sample kotlinx.datetime.test.samples.LocalTimeSamples.Formats.iso */ public val ISO: DateTimeFormat diff --git a/core/common/src/format/LocalTimeFormat.kt b/core/common/src/format/LocalTimeFormat.kt index 5f20840e5..bd281c2c8 100644 --- a/core/common/src/format/LocalTimeFormat.kt +++ b/core/common/src/format/LocalTimeFormat.kt @@ -289,10 +289,10 @@ internal val ISO_TIME_BASIC by lazy { }) { optional { second() - } - optional { - char('.') - secondFraction(1, 9) + optional { + char('.') + secondFraction(1, 9) + } } } } diff --git a/core/common/test/format/LocalDateTimeFormatTest.kt b/core/common/test/format/LocalDateTimeFormatTest.kt index e31c68a58..5ab708df5 100644 --- a/core/common/test/format/LocalDateTimeFormatTest.kt +++ b/core/common/test/format/LocalDateTimeFormatTest.kt @@ -237,24 +237,24 @@ class LocalDateTimeFormatTest { put(LocalDateTime(-10000, 7, 1, 0, 0, 59, 0), ("-100000701T000059" to setOf())) put(LocalDateTime(123456, 6, 1, 13, 44, 0, 0), ("+1234560601T1344" to setOf())) put(LocalDateTime(-123456, 5, 1, 13, 44, 0, 0), ("-1234560501T1344" to setOf())) - put(LocalDateTime(123456, 6, 1, 0, 0, 0, 100000000), ("+1234560601T0000.1" to setOf("+1234560601T000000.1", "+1234560601T000000.10", "+1234560601T000000.100"))) - put(LocalDateTime(-123456, 5, 1, 0, 0, 0, 10000000), ("-1234560501T0000.01" to setOf("-1234560501T000000.01"))) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 1000000), ("20220102T0000.001" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 100000), ("20220102T0000.0001" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 10000), ("20220102T0000.00001" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 1000), ("20220102T0000.000001" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 100), ("20220102T0000.0000001" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 10), ("20220102T0000.00000001" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 1), ("20220102T0000.000000001" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 999999999), ("20220102T0000.999999999" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 99999999), ("20220102T0000.099999999" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 9999999), ("20220102T0000.009999999" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 999999), ("20220102T0000.000999999" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 99999), ("20220102T0000.000099999" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 9999), ("20220102T0000.000009999" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 999), ("20220102T0000.000000999" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 99), ("20220102T0000.000000099" to setOf())) - put(LocalDateTime(2022, 1, 2, 0, 0, 0, 9), ("20220102T0000.000000009" to setOf())) + put(LocalDateTime(123456, 6, 1, 0, 0, 0, 100000000), ("+1234560601T000000.1" to setOf("+1234560601T000000.10", "+1234560601T000000.100"))) + put(LocalDateTime(-123456, 5, 1, 0, 0, 0, 10000000), ("-1234560501T000000.01" to setOf("-1234560501T000000.010"))) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 1000000), ("20220102T000000.001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 100000), ("20220102T000000.0001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 10000), ("20220102T000000.00001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 1000), ("20220102T000000.000001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 100), ("20220102T000000.0000001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 10), ("20220102T000000.00000001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 1), ("20220102T000000.000000001" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 999999999), ("20220102T000000.999999999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 99999999), ("20220102T000000.099999999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 9999999), ("20220102T000000.009999999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 999999), ("20220102T000000.000999999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 99999), ("20220102T000000.000099999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 9999), ("20220102T000000.000009999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 999), ("20220102T000000.000000999" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 99), ("20220102T000000.000000099" to setOf())) + put(LocalDateTime(2022, 1, 2, 0, 0, 0, 9), ("20220102T000000.000000009" to setOf())) } test(dateTimes, LocalDateTime.Formats.ISO_BASIC) }