Dates, times, durations and cron expressions for MoonBit.
moon add moonbitstack/moondatefn main raise {
let stamp = @moondate.parse("2026-09-22T14:30:05.123456+08:00")
println(stamp.strftime("%A %d %B %Y at %H:%M"))
println(stamp.epoch())
}Tuesday 22 September 2026 at 14:30
1790058605| What it is | Written | epoch | |
|---|---|---|---|
| Zoned | An instant. Sits on the timeline. | 2026-09-22T14:30:00+08:00 | Some |
| Plain | A wall clock. An alarm, an opening time. | 2026-09-22T14:30:00 | None |
| Day | A date with no time. | 2026-09-22 | None |
| Clock | A time with no date. | 14:30:00 | None |
let m = @moondate.parse("1970-01-01T00:00:00+00:19:32.37")
m.isoformat() // 1970-01-01T00:00:00+00:19:32.37
m.instant() // Some((-1173, 630000000)) — 1172.37 s before the epoch
m.epoch() // Some(-1173), the same instant floored| Form | Where it is used |
|---|---|
| RFC 3339 / ISO 8601 | TOML, JSON Schema's date-time, most of the wire |
| IMF-fixdate, RFC 850, asctime | HTTP's Date header (RFC 9110 §5.6.7): all three read, the first written |
| UTCTime, GeneralizedTime | ASN.1, so X.509 validity (ITU-T X.680 §47) |
| strftime / strptime | The % directives of C23, POSIX, glibc, Python, chrono and C++20 |
| layout / parse_layout | Go's time reference layouts (RFC3339, RFC1123, …) |
| pattern / parse_pattern | Unicode LDML patterns, what ICU, Intl and Java use |
| isoformat, to_iso_string, to_utc_string | ECMA-262's Date Time String Format and Temporal |
| Style | Write | Read | Where it is from |
|---|---|---|---|
| % directives | strftime | strptime | C23, POSIX, glibc, Python, chrono, C++20 |
| Reference-time layout | layout | parse_layout | Go's time package |
| LDML pattern | pattern | parse_pattern | Unicode UTS #35, ICU, Intl, Java |
| ECMAScript ISO | isoformat, to_iso_string, to_utc_string | parse | ECMA-262 and Temporal |
let m = @moondate.parse("2026-09-22T14:30:05.123456+08:00")
m.strftime("%A %d %B %Y, %I:%M %p") // Tuesday 22 September 2026, 02:30 PM
m.layout(@moondate.RFC1123) // Tue, 22 Sep 2026 14:30:05 +08:00
m.pattern("EEEE, MMMM d, yyyy 'at' HH:mm") // Tuesday, September 22, 2026 at 14:30
m.to_iso_string() // 2026-09-22T06:30:05.123Z
m.isoformat(fraction=3, offset=false) // 2026-09-22T14:30:05.123m.strftime("%#B %10Y %-d") // SEPTEMBER 0000002026 22
m.strftime("%Ez %Oz") // +08:00 +0800
m.pattern("Y-'W'ww c B") // 2026-W39 2 in the afternoon
m.isoformat() // 2026-09-22T14:30:05.123456+08:00| Package | What it is |
|---|---|
| moonbitstack/moondate/zone | A TZif file read (RFC 9636), the POSIX TZ strings a file's footer carries, and the question every wall clock raises in a zone |
| moonbitstack/moondate/tzdata | The IANA release itself, compiled from its own source the first time a zone is asked for |
| moonbitstack/moondate/zoneinfo | The zones this machine keeps: a file by path, a name from the system's directory, and the zone TZ and /etc/localtime name |
let tz = @tzdata.load("America/New_York")
let moment = tz.moment(1790058605) // 2026-09-22T02:30:05-04:00
moment.strftime("%H:%M %Z %z") // 02:30 EDT -0400
moment.pattern("VV") // America/New_York
moment.layout(@moondate.RFC1123) // Tue, 22 Sep 2026 02:30:05 EDT
moment.isoformat(zone_name=true) // 2026-09-22T02:30:05-04:00[America/New_York]let tz = @zoneinfo.system() // TZ, then /etc/localtime
let shanghai = @zoneinfo.named("Asia/Shanghai") // from /usr/share/zoneinfo
let same = @zoneinfo.open("/etc/localtime") // any TZif file, by pathlet moment = @tzdata.parse("2026-11-01T01:30:00[America/New_York]")
moment.strftime("%H:%M %Z") // 01:30 EDT| fold | A clock read twice | A clock never read |
|---|---|---|
| Compatible (default) | the earlier instant | the later instant |
| Earlier / Later | by instant | by instant |
| Reject | refuses | refuses |
let tz = @tzdata.load("America/New_York")
tz.read(@moondate.Date::new(2026, 3, 8), @moondate.Time::new(2, 30))
// never, between 1772951400 and 1772955000
tz.read(@moondate.Date::new(2026, 11, 1), @moondate.Time::new(1, 30))
// twice, at 1793511000 and 1793514600| Type | Built with | Asked |
|---|---|---|
| Tz | @zone.Tz::parse(bytes), @zone.Tz::of, @tzdata.load(name), @zoneinfo.open, @zoneinfo.named, @zoneinfo.system | name, at, offset, abbrev, is_dst, changes, read, epoch, moment, zoned, readings, rule |
| Reading | — | the fields: when it began, the offset in seconds, whether daylight saving was on, the abbreviation |
| Local | Tz::read | epoch(fold~), is_exact |
| Rule | Rule::parse | text, at |
| Tz from the database | @tzdata.load, @tzdata.find | the same, plus @tzdata.zones, @tzdata.links, @tzdata.release |
| Tz from this machine | @zoneinfo.open, @zoneinfo.named, @zoneinfo.system | the same, plus @zoneinfo.directory |
| Type | Built with | Asked |
|---|---|---|
| Date | Date::new, of_days, of_ordinal, of_isocalendar | weekday, yearday, isocalendar, ordinal, days, diff, plus_days, plus_months, replace |
| Time | Time::new, midnight, end_of_day | nanos, replace |
| Moment | parse, of_isoformat, http, asn1, strftime, strptime, layout, parse_layout, pattern, parse_pattern, combine, of_epoch | epoch, instant, timestamp, date, time, zone, utcoffset, astimezone, isoformat, to_iso_string, to_utc_string, strftime, layout, pattern, http_text, asn1_text, ctime, timetuple, weekday, isocalendar, ordinal, diff, plus, replace |
| Span | Span::new, of, nanosecond … day | add, sub, seconds, total_seconds, parts, neg, abs |
| Zone | Utc, Offset(minutes), Named(name, offset, abbrev), Precise(nanos) | nanos, seconds, minutes, name, abbrev |
| Cron | @cron.parse | matches, next |
| What it shows | |
|---|---|
| hello | The smallest complete program: read, look inside, write back. |
| shapes | Zoned, Plain, Day and Clock side by side, and what each one can answer. |
| calendar | Weekdays, ISO week dates, ordinals, month lengths, adding days and months. |
| zones | One instant written three ways, astimezone, the epoch both directions, spans. |
| wire | HTTP dates in three formats, ASN.1 time in two, and the refusals. |
| format | One moment through all five styles: % directives, Go layout, LDML pattern, ECMAScript. |
| schedule | Cron expressions: what they mean, the next few firings, the or-rule, the refusals. |
| worldclock | Five cities at one instant, and the two hours of the year that need a decision. |
let every_quarter = @cron.parse("*/15 9-17 * * MON-FRI")
let next = every_quarter.next(now)| %Y %C %y | year of four digits, century, two-digit year |
| %G %g | ISO week year, two-digit |
| %m %B %b %h | month, long and short name |
| %d %e | day of month, zero- and space-padded |
| %j | day of year, 001 to 366 |
| %U %W %V | week of year, Sunday-, Monday-, and ISO-based |
| %u %w | weekday, 1 to 7 and 0 to 6 |
| %a %A | short and long weekday name |
| %q | quarter of the year, 1 to `4 (chrono) |
| %H %k %I %l | hour, 00 and 0, twelve-hour 01 and 1 |
| %M %S | minute, second |
| %p %P | AM/PM and am/pm |
| %f %.f %.Nf %Nf %N | fractional second, dot or not, N digits or auto |
| %s | seconds since the epoch |
| %z %:z %::z %:::z %#z %Ez %Oz | offset: +0800, +08:00, +08:00:00, +08 at the precision it needs, and the two ISO 8601 forms of C++20 |
| %Z | UTC, UTC±HH:MM for a fixed offset, or nothing when there is no zone |
| %c %x %X %D %F %T %R %r %v %+ | the composite forms |
| %n %t %% | a newline, a tab, a per cent sign |
let ANSIC : Stringfn leap(year : Int) -> BoolInstall
Download zipDates, times, durations and cron expressions for MoonBit.