moonbit_cron

    A pure MoonBit parser and next-trigger calculator for five-field Cron expressions.

    cron
    scheduler
    parser
    moonbit
    Download zip
    Version
    0.1.0
    License
    MIT
    Last updated
    2 months ago
    Downloads
    45

    No dependencies

    #MoonBit Cron

    MoonBit CI

    MoonBit Cron is a zero-dependency, pure MoonBit library for parsing standard five-field Cron expressions, checking whether a time matches, and finding the next trigger time. It is designed as a reusable building block for schedulers, automation tools, backend services, and command-line applications.

    #Features

    • Parses the five fields: minute, hour, day of month, month, and day of week.
    • Supports *, individual values, ranges (a-b), lists (a,b), and steps (*/n, a-b/n).
    • Accepts standard uppercase month names (JAN through DEC) and weekday names (SUN through SAT) in their corresponding fields.
    • Validates empty fields, malformed list items, non-positive steps, bounds, and oversized numeric input before it can overflow.
    • Uses standard Cron day-of-month/day-of-week OR semantics when both fields are restricted.
    • Calculates the next matching minute across month and leap-year boundaries.
    • Runs on the wasm, wasm-gc, JavaScript, and native MoonBit targets.

    #Install

    Install MoonBit with the official installer, then add the package after it is published to Mooncakes:

    moon add lijunjie860/moonbit_cron

    For local development:

    git clone https://github.com/lijunjie860/MoonBit-Cron.git cd MoonBit-Cron moon check --target all --warn-list +73 --deny-warn moon test --target all --warn-list +73 --deny-warn moon run cmd/main

    #API example

    import {
    "lijunjie860/moonbit_cron" @cron,
    }

    fn next_workday_trigger() -> Result[@cron.Time, String] {
    let expression = @cron.parse("*/15 9-17 * * 1-5")
    match expression {
    Err(message) => Err(message)
    Ok(expr) => expr.next(@cron.Time::{
    year: 2026,
    month: 10,
    day: 15,
    hour: 9,
    minute: 7,
    weekday: 4,
    })
    }
    }

    #Runnable CLI demonstration

    moon run cmd/main

    Expected output:

    Expression: */15 9-17 * * 1-5 Matches now: false Next trigger: 2026-10-15 9:15 (weekday 4)

    #Validation

    The GitHub Actions workflow installs MoonBit 0.10.3 and runs formatting, warning-free checks, builds, generated-interface verification, and tests on Ubuntu, macOS, and Windows. The test suite covers parser grammar, named month and weekday fields, invalid input, numeric overflow protection, DOM/DOW semantics, cross-month rollover, and leap-year scheduling.

    Run the same checks locally:

    moon fmt --check moon check --target all --warn-list +73 --deny-warn moon build --target all --warn-list +73 --deny-warn moon test --target all --warn-list +73 --deny-warn moon info

    #License

    Copyright (c) 2026 lijunjie860.

    This project is licensed under the MIT License.

    CronExpr

    pub(all) struct CronExpr {
    minute : CronField
    hour : CronField
    day_of_month : CronField
    month : CronField
    day_of_week : CronField
    } derive(Eq,
    Debug
    )

    Represents a parsed cron expression with 5 fields.

    CronExpr::matches

    fn CronExpr::matches(self : CronExpr, time : Time) -> Bool

    CronExpr::new

    fn CronExpr::new(minute : CronField, hour : CronField, day_of_month : CronField, month : CronField, day_of_week : CronField) -> CronExpr

    CronExpr::next

    fn CronExpr::next(self : CronExpr, from : Time) -> Result[Time, String]

    CronField

    pub(all) enum CronField {
    All
    Value(Int)
    Range(Int, Int)
    Step(CronField, Int)
    List(Array[CronField])
    } derive(Eq,
    Debug
    )

    Time

    pub(all) struct Time {
    year : Int
    month : Int
    day : Int
    hour : Int
    minute : Int
    weekday : Int
    } derive(Eq,
    Debug
    )

    Represents a specific time used for matching.

    add_minute

    fn add_minute(t : Time) -> Time

    days_in_month

    fn days_in_month(year : Int, month : Int) -> Int

    is_leap_year

    fn is_leap_year(year : Int) -> Bool

    parse

    fn parse(cron_str : String) -> Result[CronExpr, String]

    weekday

    fn weekday(year : Int, month : Int, day : Int) -> Int