@@ -39,11 +39,56 @@ public annotation class FormatStringsInDatetimeFormats
39
39
*
40
40
* In addition to the standard syntax, this function also supports the following extensions:
41
41
* * `[]` denote optional sections. For example, `hh:mm[:ss]` will allow parsing seconds optionally.
42
- * This is similar to what is supported by the Java Time's `DateTimeFormatter` class, but with the difference that,
43
- * for formatting, the optional sections have a different meaning: they are not included in the output if all the
44
- * fields they contain have their default values. See [DateTimeFormatBuilder.optional] for more details.
45
- * * One or more `p` characters before a field specifies that the field should be padded with zeroes to the length
46
- * equal to the number of `p` characters. This is also supported by the Java Time's `DateTimeFormatter` class.
42
+ * This is similar to what is supported by the Java Time's `DateTimeFormatter` class.
43
+ *
44
+ * Usage example:
45
+ * ```
46
+ * DateTimeComponents.Format {
47
+ * // 2023-01-20T23:53:16.312+03:30[Asia/Tehran]
48
+ * byUnicodePattern("uuuu-MM-dd'T'HH:mm[:ss[.SSS]]xxxxx'['VV']'")
49
+ * }
50
+ * ```
51
+ *
52
+ * The list of supported directives is as follows:
53
+ *
54
+ * | **Directive** | **Meaning** |
55
+ * | `'string'` | literal `string`, without quotes |
56
+ * | `'''` | literal char `'` |
57
+ * | `[fmt]` | equivalent to `fmt` during formatting, but during parsing also accepts the empty string |
58
+ * | `u` | ISO year without padding |
59
+ * | `uu` | last two digits of the ISO year, with the base year 2000 |
60
+ * | `uuuu` | ISO year, zero-padded to four digits |
61
+ * | `M`, `L` | month number (1-12), without padding |
62
+ * | `MM`, `LL` | month number (01-12), zero-padded to two digits |
63
+ * | `d` | day-of-month (1-31), without padding |
64
+ * | `H` | hour-of-day (0-23), without padding |
65
+ * | `HH` | hour-of-day (00-23), zero-padded to two digits |
66
+ * | `m` | minute-of-hour (0-59), without padding |
67
+ * | `mm` | minute-of-hour (00-59), zero-padded to two digits |
68
+ * | `s` | second-of-hour (0-59), without padding |
69
+ * | `ss` | second-of-hour (00-59), zero-padded to two digits |
70
+ * | `S`, `SS`, `SSS`... | fraction-of-second without a leading dot, with as many digits as the format length |
71
+ * | `VV` | timezone name (for example, `Europe/Berlin`) |
72
+ *
73
+ * The UTC offset is formatted using one of the following directives. In every one of these formats, hours, minutes,
74
+ * and seconds are zero-padded to two digits. Also, hours are unconditionally present.
75
+ *
76
+ * | **Directive** | **Minutes** | **Seconds** | **Separator** | **Representation of zero** |
77
+ * | `X` | unless zero | never | none | `Z` |
78
+ * | `XX` | always | never | none | `Z` |
79
+ * | `XXX` | always | never | colon | `Z` |
80
+ * | `XXXX` | always | unless zero | none | `Z` |
81
+ * | `XXXXX`, `ZZZZZ` | always | unless zero | colon | `Z` |
82
+ * | `x` | unless zero | never | none | `+00` |
83
+ * | `xx`, `Z`, `ZZ`, `ZZZ` | always | never | none | `+0000` |
84
+ * | `xxx` | always | never | colon | `+00:00` |
85
+ * | `xxxx` | always | unless zero | none | `+0000` |
86
+ * | `xxxxx` | always | unless zero | colon | `+00:00` |
87
+ *
88
+ * `y` is the most common way to represent the year, but it's not supported by [byUnicodePattern] because its
89
+ * interpretation depends on which calendar is being used.
90
+ * For the ISO chronology and years 0001 and later, one can obtain results that are equivalent to `yyyy` and `yy` like
91
+ * this: `byUnicodePattern(pattern.replace("yyyy", "uuuu").replace("yy", "uu")`.
47
92
*
48
93
* @throws IllegalArgumentException if the pattern is invalid or contains unsupported directives.
49
94
* @throws IllegalArgumentException if the builder is incompatible with the specified directives.
@@ -378,7 +423,7 @@ internal sealed interface UnicodeFormat {
378
423
class FractionOfSecond (override val formatLength : Int ) : WithSubsecondPrecision() {
379
424
override val formatLetter = ' S'
380
425
override fun addToFormat (builder : DateTimeFormatBuilder .WithTime ) =
381
- builder.secondFraction(minLength = formatLength, maxLength = formatLength)
426
+ builder.secondFraction(formatLength)
382
427
}
383
428
384
429
class MilliOfDay (override val formatLength : Int ) : WithSubsecondPrecision() {
@@ -407,7 +452,10 @@ internal sealed interface UnicodeFormat {
407
452
408
453
class TimeZoneId (override val formatLength : Int ) : ZoneBased() {
409
454
override val formatLetter = ' V'
410
- override fun addToFormat (builder : DateTimeFormatBuilder .WithDateTimeComponents ) = builder.timeZoneId()
455
+ override fun addToFormat (builder : DateTimeFormatBuilder .WithDateTimeComponents ) = when (formatLength) {
456
+ 2 -> builder.timeZoneId()
457
+ else -> unknownLength()
458
+ }
411
459
}
412
460
413
461
class GenericTimeZoneName (override val formatLength : Int ) : ZoneBased() {
0 commit comments