Formatting & Parsing

Pattern-based formatting, ISO parsing, type conversions, and range conversions. For arithmetic and anchoring, see the individual type pages.

Formatting

Format dates and times using pattern strings. Supported tokens:

Token Output Example
yyyy 4-digit year 2025
yy 2-digit year 25
MM Zero-padded month 03
MMM Abbreviated month name Mar
dd Zero-padded day 05
HH 24-hour hour 14
mm Minutes 30
ss Seconds 05
SSS Milliseconds 042
Z Timezone offset +02:00
val zoned = instant.atZone(MpTimezone.of("Europe/Berlin"))

zoned.format("dd MMM yyyy")         // "15 Mar 2025"
zoned.format("yyyy-MM-dd HH:mm:ss") // "2025-03-15 14:30:00"
zoned.format("dd/MM/yy")            // "15/03/25"
zoned.format("HH:mm Z")             // "14:30 +01:00"
The formatter never throws exceptions. It handles malformed patterns gracefully — you'll get output, just maybe not what you expected.

Parsing

All types support ISO-string parsing with both strict and safe variants:

// Strict — throws on invalid input
val instant = MpInstant.parse("2025-03-15T10:30:00Z")
val date = MpLocalDate.parse("2025-03-15")
val time = MpLocalTime.parse("14:30:00")

// Safe — returns null on invalid input
val maybe = MpLocalDate.tryParse("not-a-date")  // null
val ok = MpLocalDate.tryParse("2025-03-15")      // MpLocalDate

// Custom parser
val parser = MpDateTimeParser("dd/MM/yyyy")
val parsed = parser.parse("15/03/2025")

Conversions

Move freely between types:

val instant = MpInstant.parse("2025-03-15T10:30:00Z")

// Instant -> Zoned
val zoned = instant.atZone(MpTimezone.of("Europe/Berlin"))
val utc = instant.atUTC()

// Instant -> Local (drops timezone info)
val localDate = instant.toLocalDate()
val localDateTime = instant.toLocalDateTime()

// Zoned -> Instant (recovers absolute time)
val backToInstant = zoned.toInstant()

// Local -> Instant (requires timezone)
val fromLocal = localDateTime.toInstant(MpTimezone.UTC)

// Epoch conversions
val millis = instant.toEpochMillis()
val seconds = instant.toEpochSeconds()
val fromMillis = MpInstant.fromEpochMillis(millis)

Range conversions

Convert local date ranges to timezone-aware datetime ranges for different use cases:

import io.peekandpoke.ultra.datetime.DateTimeRangeConverter

val dateRange = MpLocalDateRange(
    from = MpLocalDate.of(2025, 3, 15),
    to = MpLocalDate.of(2025, 3, 20),
)
val tz = MpTimezone.of("Europe/Berlin")

// Noon to noon (hotel-style)
val noonToNoon = DateTimeRangeConverter.fromNoonToNoon(dateRange, tz)

// Morning to evening
val dayTime = DateTimeRangeConverter.fromMorningToEvening(dateRange, tz)

// Custom hour range
val custom = DateTimeRangeConverter.fromHourToHour(dateRange, tz, fromHour = 8, toHour = 18)