0
# Formatting System
1
2
This document covers the comprehensive parsing and formatting system for all datetime types, including the builder DSL, predefined formats, and `DateTimeComponents` for complex parsing scenarios.
3
4
## DateTimeFormat Interface
5
6
The base interface for all datetime formatting operations.
7
8
```kotlin { .api }
9
sealed interface DateTimeFormat<T> {
10
// Format value to string
11
fun format(value: T): String
12
13
// Format value to appendable
14
fun <A : Appendable> formatTo(appendable: A, value: T): A
15
16
// Parse string to value
17
fun parse(input: CharSequence): T
18
19
// Parse string to value or return null if invalid
20
fun parseOrNull(input: CharSequence): T?
21
}
22
23
// Companion object for utility functions
24
object DateTimeFormat.Companion {
25
fun formatAsKotlinBuilderDsl(format: DateTimeFormat<*>): String
26
}
27
```
28
29
## Format Builders
30
31
Each datetime type provides a format builder function for creating custom formats using a DSL.
32
33
### LocalDate Format Builder
34
35
```kotlin { .api }
36
fun LocalDate.Companion.Format(
37
block: DateTimeFormatBuilder.WithDate.() -> Unit
38
): DateTimeFormat<LocalDate>
39
40
// Builder interface for date formatting
41
interface DateTimeFormatBuilder.WithDate {
42
// Year formatting
43
fun year(padding: Padding = Padding.ZERO)
44
fun yearTwoDigits(baseYear: Int)
45
46
// Month formatting
47
fun monthNumber(padding: Padding = Padding.ZERO)
48
fun monthName(names: MonthNames)
49
fun monthAbbreviated(names: MonthNames)
50
51
// Day formatting
52
fun dayOfMonth(padding: Padding = Padding.ZERO)
53
fun dayOfYear(padding: Padding = Padding.ZERO)
54
fun dayOfWeek(names: DayOfWeekNames)
55
fun dayOfWeekAbbreviated(names: DayOfWeekNames)
56
57
// Literal text
58
fun chars(value: String)
59
fun char(value: Char)
60
61
// Alternative formats
62
fun alternativeParsing(block: DateTimeFormatBuilder.WithDate.() -> Unit)
63
}
64
```
65
66
### LocalTime Format Builder
67
68
```kotlin { .api }
69
fun LocalTime.Companion.Format(
70
block: DateTimeFormatBuilder.WithTime.() -> Unit
71
): DateTimeFormat<LocalTime>
72
73
// Builder interface for time formatting
74
interface DateTimeFormatBuilder.WithTime {
75
// Hour formatting
76
fun hour(padding: Padding = Padding.ZERO)
77
fun hourOfAmPm(padding: Padding = Padding.ZERO)
78
fun amPmHour(padding: Padding = Padding.ZERO)
79
fun amPmMarker(am: String, pm: String)
80
81
// Minute and second formatting
82
fun minute(padding: Padding = Padding.ZERO)
83
fun second(padding: Padding = Padding.ZERO)
84
85
// Fractional second formatting
86
fun secondFraction(fixedLength: Int)
87
fun secondFraction(minLength: Int, maxLength: Int)
88
89
// Literal text
90
fun chars(value: String)
91
fun char(value: Char)
92
93
// Alternative formats
94
fun alternativeParsing(block: DateTimeFormatBuilder.WithTime.() -> Unit)
95
}
96
```
97
98
### LocalDateTime Format Builder
99
100
```kotlin { .api }
101
fun LocalDateTime.Companion.Format(
102
block: DateTimeFormatBuilder.WithDateTime.() -> Unit
103
): DateTimeFormat<LocalDateTime>
104
105
// Builder interface combining date and time formatting
106
interface DateTimeFormatBuilder.WithDateTime :
107
DateTimeFormatBuilder.WithDate,
108
DateTimeFormatBuilder.WithTime {
109
110
// Date component
111
fun date(format: DateTimeFormat<LocalDate>)
112
113
// Time component
114
fun time(format: DateTimeFormat<LocalTime>)
115
116
// Combined date and time with separator
117
fun dateTime(
118
dateFormat: DateTimeFormat<LocalDate>,
119
timeFormat: DateTimeFormat<LocalTime>,
120
separator: String = "T"
121
)
122
}
123
```
124
125
### YearMonth Format Builder
126
127
```kotlin { .api }
128
fun YearMonth.Companion.Format(
129
block: DateTimeFormatBuilder.WithYearMonth.() -> Unit
130
): DateTimeFormat<YearMonth>
131
132
// Builder interface for year-month formatting
133
interface DateTimeFormatBuilder.WithYearMonth {
134
// Year formatting
135
fun year(padding: Padding = Padding.ZERO)
136
fun yearTwoDigits(baseYear: Int)
137
138
// Month formatting
139
fun monthNumber(padding: Padding = Padding.ZERO)
140
fun monthName(names: MonthNames)
141
fun monthAbbreviated(names: MonthNames)
142
143
// Literal text
144
fun chars(value: String)
145
fun char(value: Char)
146
147
// Alternative formats
148
fun alternativeParsing(block: DateTimeFormatBuilder.WithYearMonth.() -> Unit)
149
}
150
```
151
152
### UtcOffset Format Builder
153
154
```kotlin { .api }
155
fun UtcOffset.Companion.Format(
156
block: DateTimeFormatBuilder.WithUtcOffset.() -> Unit
157
): DateTimeFormat<UtcOffset>
158
159
// Builder interface for UTC offset formatting
160
interface DateTimeFormatBuilder.WithUtcOffset {
161
// Offset formatting
162
fun offset(format: UtcOffsetFormat)
163
fun offsetHours(padding: Padding = Padding.ZERO)
164
fun offsetMinutesOfHour(padding: Padding = Padding.ZERO)
165
fun offsetSecondsOfMinute(padding: Padding = Padding.ZERO)
166
167
// Literal text
168
fun chars(value: String)
169
fun char(value: Char)
170
171
// Alternative formats
172
fun alternativeParsing(block: DateTimeFormatBuilder.WithUtcOffset.() -> Unit)
173
}
174
```
175
176
## Predefined Formats
177
178
Each datetime type provides commonly used predefined formats through its `Formats` object.
179
180
### LocalDate Formats
181
182
```kotlin { .api }
183
object LocalDate.Formats {
184
// ISO 8601 format: "2023-12-25"
185
val ISO: DateTimeFormat<LocalDate>
186
187
// ISO basic format: "20231225"
188
val ISO_BASIC: DateTimeFormat<LocalDate>
189
}
190
```
191
192
### LocalTime Formats
193
194
```kotlin { .api }
195
object LocalTime.Formats {
196
// ISO 8601 format: "14:30:00" or "14:30:00.123456789"
197
val ISO: DateTimeFormat<LocalTime>
198
}
199
```
200
201
### LocalDateTime Formats
202
203
```kotlin { .api }
204
object LocalDateTime.Formats {
205
// ISO 8601 format: "2023-12-25T14:30:00" or "2023-12-25T14:30:00.123456789"
206
val ISO: DateTimeFormat<LocalDateTime>
207
}
208
```
209
210
### YearMonth Formats
211
212
```kotlin { .api }
213
object YearMonth.Formats {
214
// ISO 8601 format: "2023-12"
215
val ISO: DateTimeFormat<YearMonth>
216
}
217
```
218
219
### UtcOffset Formats
220
221
```kotlin { .api }
222
object UtcOffset.Formats {
223
// ISO 8601 format: "+01:00", "-05:30", "Z"
224
val ISO: DateTimeFormat<UtcOffset>
225
226
// Four digits format: "+0100", "-0530", "+0000"
227
val FOUR_DIGITS: DateTimeFormat<UtcOffset>
228
}
229
```
230
231
## DateTimeComponents
232
233
Intermediate representation for parsing and formatting complex datetime values that may include timezone information and partial data.
234
235
```kotlin { .api }
236
class DateTimeComponents {
237
// Date components
238
var year: Int?
239
var monthNumber: Int?
240
var dayOfMonth: Int?
241
var dayOfYear: Int?
242
var dayOfWeek: DayOfWeek?
243
244
// Time components
245
var hour: Int?
246
var hourOfAmPm: Int?
247
var isAmPm: Boolean?
248
var minute: Int?
249
var second: Int?
250
var nanosecond: Int?
251
252
// Offset components
253
var offsetIsNegative: Boolean?
254
var offsetHours: Int?
255
var offsetMinutesOfHour: Int?
256
var offsetSecondsOfMinute: Int?
257
258
// Timezone component
259
var timeZoneId: String?
260
261
// Conversion methods
262
fun toLocalDate(): LocalDate
263
fun toLocalTime(): LocalTime
264
fun toLocalDateTime(): LocalDateTime
265
fun toUtcOffset(): UtcOffset
266
fun toInstantUsingOffset(): Instant
267
}
268
```
269
270
### DateTimeComponents Format Builder
271
272
```kotlin { .api }
273
fun DateTimeComponents.Companion.Format(
274
block: DateTimeFormatBuilder.WithDateTimeComponents.() -> Unit
275
): DateTimeFormat<DateTimeComponents>
276
277
// Builder interface for complex datetime formatting
278
interface DateTimeFormatBuilder.WithDateTimeComponents :
279
DateTimeFormatBuilder.WithDate,
280
DateTimeFormatBuilder.WithTime,
281
DateTimeFormatBuilder.WithUtcOffset {
282
283
// Timezone formatting
284
fun timeZoneId()
285
286
// Optional sections
287
fun optional(vararg format: String, block: DateTimeFormatBuilder.WithDateTimeComponents.() -> Unit)
288
}
289
```
290
291
### DateTimeComponents Predefined Formats
292
293
```kotlin { .api }
294
object DateTimeComponents.Formats {
295
// ISO 8601 with offset: "2023-12-25T14:30:00+01:00"
296
val ISO_DATE_TIME_OFFSET: DateTimeFormat<DateTimeComponents>
297
298
// RFC 1123: "Mon, 25 Dec 2023 14:30:00 GMT"
299
val RFC_1123: DateTimeFormat<DateTimeComponents>
300
}
301
```
302
303
## Padding Options
304
305
```kotlin { .api }
306
enum class Padding {
307
// No padding during formatting, optional during parsing
308
NONE,
309
310
// Pad with zeros during formatting, required during parsing
311
ZERO,
312
313
// Pad with spaces during formatting, required during parsing
314
SPACE
315
}
316
```
317
318
## Usage Examples
319
320
### Basic Format Builder Usage
321
322
```kotlin
323
// Custom date format: "25/12/2023"
324
val customDateFormat = LocalDate.Format {
325
dayOfMonth(Padding.ZERO)
326
char('/')
327
monthNumber(Padding.ZERO)
328
char('/')
329
year()
330
}
331
332
val date = LocalDate(2023, 12, 25)
333
val formatted = date.format(customDateFormat) // "25/12/2023"
334
val parsed = LocalDate.parse("01/01/2024", customDateFormat)
335
```
336
337
### Advanced Time Formatting
338
339
```kotlin
340
// 12-hour format with AM/PM: "2:30 PM"
341
val twelveHourFormat = LocalTime.Format {
342
amPmHour(Padding.NONE)
343
char(':')
344
minute(Padding.ZERO)
345
char(' ')
346
amPmMarker("AM", "PM")
347
}
348
349
val time = LocalTime(14, 30)
350
val formatted = time.format(twelveHourFormat) // "2:30 PM"
351
```
352
353
### Complex DateTime Formatting
354
355
```kotlin
356
// European style with timezone: "25. December 2023, 14:30 CET"
357
val europeanFormat = DateTimeComponents.Format {
358
dayOfMonth(Padding.NONE)
359
chars(". ")
360
monthName(MonthNames.ENGLISH_FULL)
361
char(' ')
362
year()
363
chars(", ")
364
hour(Padding.ZERO)
365
char(':')
366
minute(Padding.ZERO)
367
char(' ')
368
timeZoneId()
369
}
370
```
371
372
### Using Predefined Formats
373
374
```kotlin
375
// Using ISO formats
376
val date = LocalDate(2023, 12, 25)
377
val isoDate = date.format(LocalDate.Formats.ISO) // "2023-12-25"
378
379
val dateTime = LocalDateTime(2023, 12, 25, 14, 30, 45, 123_456_789)
380
val isoDateTime = dateTime.format(LocalDateTime.Formats.ISO) // "2023-12-25T14:30:45.123456789"
381
382
// Parse using predefined formats
383
val parsedDate = LocalDate.parse("2023-12-25") // Uses ISO format by default
384
val parsedDateTime = LocalDateTime.parse("2023-12-25T14:30:45", LocalDateTime.Formats.ISO)
385
```
386
387
### Working with DateTimeComponents
388
389
```kotlin
390
// Parse complex datetime string with timezone
391
val complexFormat = DateTimeComponents.Formats.ISO_DATE_TIME_OFFSET
392
val components = DateTimeComponents.parse("2023-12-25T14:30:00+01:00", complexFormat)
393
394
// Extract different representations
395
val instant = components.toInstantUsingOffset()
396
val localDateTime = components.toLocalDateTime()
397
val offset = components.toUtcOffset()
398
399
// Access individual components
400
val year = components.year // 2023
401
val timeZoneId = components.timeZoneId // null (offset-based, not zone-based)
402
```
403
404
### Alternative Parsing
405
406
```kotlin
407
// Accept multiple date formats during parsing
408
val flexibleDateFormat = LocalDate.Format {
409
year()
410
alternativeParsing {
411
char('-')
412
monthNumber(Padding.ZERO)
413
char('-')
414
dayOfMonth(Padding.ZERO)
415
}
416
alternativeParsing {
417
char('/')
418
monthNumber(Padding.ZERO)
419
char('/')
420
dayOfMonth(Padding.ZERO)
421
}
422
}
423
424
// Can parse both "2023-12-25" and "2023/12/25"
425
val date1 = LocalDate.parse("2023-12-25", flexibleDateFormat)
426
val date2 = LocalDate.parse("2023/12/25", flexibleDateFormat)
427
```
428
429
### Error Handling
430
431
```kotlin
432
// Safe parsing with null return
433
val maybeDate = LocalDate.parseOrNull("invalid-date") // returns null
434
435
// Exception-based parsing
436
try {
437
val date = LocalDate.parse("invalid-date") // throws DateTimeFormatException
438
} catch (e: DateTimeFormatException) {
439
println("Failed to parse date: ${e.message}")
440
}
441
```
442
443
## Integration with Instant Parsing
444
445
```kotlin
446
// Parse Instant with custom DateTimeComponents format
447
val instantFormat = DateTimeComponents.Format {
448
year()
449
char('-')
450
monthNumber(Padding.ZERO)
451
char('-')
452
dayOfMonth(Padding.ZERO)
453
char(' ')
454
hour(Padding.ZERO)
455
char(':')
456
minute(Padding.ZERO)
457
char(':')
458
second(Padding.ZERO)
459
char(' ')
460
offset(UtcOffsetFormat.FOUR_DIGITS)
461
}
462
463
val instant = Instant.parse("2023-12-25 14:30:00 +0100", instantFormat)
464
```