Added LocalTime.Formats.ISO_BASIC (ISO 8601 basic format) - #518
Added LocalTime.Formats.ISO_BASIC (ISO 8601 basic format)#518lucgirardin wants to merge 14 commits into
Conversation
|
ISO 8601 specifies that the format for time-of-day includes a leading |
|
You are right, thanks for spotting this! I believe the same should also apply to LocalTime.Formats.ISO. Should I attempt to change it as well? |
The extended ISO format is allowed to omit the In fact, regarding usefulness: is |
|
I find it very useful, for example if one need to have a timestamp stored in a file name, in my case |
dkhalanskyjb
left a comment
There was a problem hiding this comment.
Got it! I don't see any problems with adding a LocalTime.Formats.ISO_BASIC if it is indeed useful, but by that logic, it also makes sense to add LocalDateTime.Formats.ISO_BASIC (which is the 20250415T065500 part in your message).
| // 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') |
There was a problem hiding this comment.
Please see internal val ISO_DATETIME: our format is case-insensitive.
| * | ||
| * @sample kotlinx.datetime.test.samples.LocalTimeSamples.Formats.isoBasic | ||
| */ | ||
| public val ISO_BASIC: DateTimeFormat<LocalTime> |
There was a problem hiding this comment.
Please also add tests. Examples: LocalDateTimeFormatTest#testIso, LocalDateFormatTest#testBasicIso, etc.
| /** | ||
| * ISO 8601 basic format. | ||
| * | ||
| * Examples: `1234`, `123456`, `123456.789`, `123456.1234`. |
There was a problem hiding this comment.
These examples are not valid for this format.
|
Should be complete now! |
| * 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 |
There was a problem hiding this comment.
| * 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 |
b) is the extended format.
| * | ||
| * When formatting, seconds are always included, even if they are zero. | ||
| * Fractional parts of the second are included if non-zero. | ||
| * |
There was a problem hiding this comment.
I think LocalDateTime.ISO_BASIC is also worth mentioning (given that you personally were interested in LocalDateTime.Formats.ISO_BASIC, for example).
| optional { | ||
| second() | ||
| } | ||
| optional { | ||
| char('.') | ||
| secondFraction(1, 9) | ||
| } | ||
| } |
There was a problem hiding this comment.
| optional { | |
| second() | |
| } | |
| optional { | |
| char('.') | |
| secondFraction(1, 9) | |
| } | |
| } | |
| optional { | |
| second() | |
| optional { | |
| char('.') | |
| secondFraction(1, 9) | |
| } | |
| } | |
| } |
As the tests show, otherwise, 12:30:00.123 gets formatted as T1230.123, which is not valid: fractions of a second are only emitted together with the second value itself, even if it is zero.
… itself, even if it is zero.
|
Thanks for your careful review! |
| @Test | ||
| fun testBasicIso() { | ||
| val dateTimes = buildMap<LocalDateTime, Pair<String, Set<String>>> { | ||
| put(LocalDateTime(2008, 7, 5, 0, 0, 0, 0), ("20080705T0000" to setOf("20080705T0000"))) |
There was a problem hiding this comment.
Here, the same parsable representation is listed twice.
| optional { | ||
| second() | ||
| optional { | ||
| char('.') | ||
| secondFraction(1, 9) | ||
| } | ||
| } |
There was a problem hiding this comment.
Now that I look at it, it's inconsistent to optionally omit seconds here on formatting. ISO allows parsing missing seconds, but does not omit them on its own.
| optional { | |
| second() | |
| optional { | |
| char('.') | |
| secondFraction(1, 9) | |
| } | |
| } | |
| second() | |
| optional { | |
| char('.') | |
| secondFraction(1, 9) | |
| } |
|
Sorry for the long delay. Everything should now be good to go, hopefully! |
| * - `00000830T184300.5` | ||
| * - `-00010830T184300.123456789` | ||
| * | ||
| * When formatting, seconds always included. |
There was a problem hiding this comment.
| * When formatting, seconds always included. | |
| * When formatting, seconds are always included. |
| * 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 |
There was a problem hiding this comment.
LocalDateTimeSamples needs to include the actual sample. Also, please use consistent naming: for LocalDate and LocalTime, this sample is called isoBasic.
| } | ||
|
|
||
| @Test | ||
| fun testBasicIso() { |
There was a problem hiding this comment.
Please also add the corresponding test for LocalTime.Formats.ISO_BASIC.
| @Test | ||
| fun testBasicIso() { | ||
| val dateTimes = buildMap<LocalDateTime, Pair<String, Set<String>>> { | ||
| put(LocalDateTime(2008, 7, 5, 0, 0, 0, 0), ("20080705T000000" to setOf("20080705t000000"))) |
There was a problem hiding this comment.
Please also test the scenarios of parsing a string which does not include the seconds.
dkhalanskyjb
left a comment
There was a problem hiding this comment.
Another thing that I noticed just now: please also add the new constants to this list:
kotlinx-datetime/core/common/src/format/DateTimeFormat.kt
Lines 154 to 171 in 90be731
No description provided.