///|
/// The five writing styles, one moment at a time.
///
/// The `%` directives every Unix has, Go's reference-time layout, the Unicode
/// LDML pattern, and the ECMAScript ISO shapes. This file runs one moment through
/// each language, then reads the pieces back.
///
/// moon run src/examples/format
fn main raise {
let moment = @moondate.parse("2026-09-22T14:30:05.123456+08:00")
// One line per directive, so the table doubles as a reference. The columns are
// the directive, what it means, and what it gives for this moment.
let lines = [
("%Y", "four-digit year", "%Y"),
("%y", "two-digit year", "%y"),
("%m", "month, 01 to 12", "%m"),
("%d", "day of month, 01 to 31", "%d"),
("%H", "hour on a 24-hour clock", "%H"),
("%I", "hour on a 12-hour clock", "%I"),
("%M", "minute", "%M"),
("%S", "second", "%S"),
("%f", "microseconds", "%f"),
("%p", "AM or PM", "%p"),
("%j", "day of year, 001 to 366", "%j"),
("%a", "short weekday name", "%a"),
("%A", "long weekday name", "%A"),
("%b", "short month name", "%b"),
("%B", "long month name", "%B"),
("%G", "ISO week year", "%G"),
("%V", "ISO week number", "%V"),
("%u", "ISO weekday, 1 to 7", "%u"),
("%w", "weekday, 0 to 6, Sunday is 0", "%w"),
("%z", "offset from UTC, no colon", "%z"),
("%Z", "zone name", "%Z"),
("%%", "a literal percent sign", "%%"),
]
for (directive, meaning, pattern) in lines {
let value = moment.strftime(pattern)
println(directive + "\t" + meaning + "\t" + value)
}
println("")
// A format string is usually longer than one directive, and the literal text
// between them is copied through untouched.
println(moment.strftime("%A, %d %B %Y at %H:%M:%S %z"))
println(moment.strftime("%G-W%V-%u, day %j of %Y"))
println(moment.strftime("%I:%M %p on day %d"))
println("")
// The shape decides what the missing pieces are. A bare day is midnight, a bare
// clock is 1 January 1900 — the same defaults C's `struct tm` has always had.
let day = @moondate.parse("2026-09-22")
println(day.strftime("%Y-%m-%d %H:%M:%S"))
let clock = @moondate.parse("14:30:05")
println(clock.strftime("%Y-%m-%d %H:%M:%S"))
println("")
// Reading is the other direction. Directives in the format match the pieces in
// the text; anything else has to match character for character.
let read = @moondate.strptime("22 September 2026, 14:30", "%d %B %Y, %H:%M")
println(read)
println(read.strftime("%Y-%m-%dT%H:%M:%S"))
// Whitespace in the format matches any run of whitespace, which is what makes a
// format survive text that was aligned by hand.
println(
@moondate.strptime("Sun Nov 6 08:49:37 1994", "%a %b %d %H:%M:%S %Y"),
)
println("")
// Go's reference-time layout. The template is Go's own reference moment
// (`Mon Jan 2 15:04:05 MST 2006`), and each recognisable piece names a field.
println(moment.layout(@moondate.RFC3339))
println(moment.layout(@moondate.RFC1123))
println(moment.layout("Monday, 02-Jan-06 15:04:05 MST"))
println("")
// A Unicode LDML pattern: a run of a letter names a field, and its length is the
// width. Text in single quotes is literal.
println(moment.pattern("EEEE, MMMM d, yyyy 'at' HH:mm"))
println(moment.pattern("yyyy-MM-dd'T'HH:mm:ssXXX"))
println("")
// The ECMAScript shapes: `to_iso_string` is always the UTC instant with
// milliseconds, `to_utc_string` is the HTTP-style GMT form, and `isoformat`
// picks its own precision and writes the offset or leaves it off.
println(moment.to_iso_string())
println(moment.to_utc_string())
println(moment.isoformat(fraction=3, offset=false))
println("")
// A format that does not match the text is refused, and the reason says which
// piece failed rather than "invalid input".
try {
let _ = @moondate.strptime("2026-09-22", "%Y/%m/%d")
} catch {
err => println("refused: " + err.to_string())
}
// The same goes for a value that is out of range: 31 is a fine day, but not in
// a month that has 30 of them.
try {
let _ = @moondate.strptime("2026-04-31", "%Y-%m-%d")
} catch {
err => println("refused: " + err.to_string())
}
}