目录

MoonCron

A cron expression parser and schedule calculator written in MoonBit.

MoonCron parses, validates, describes, matches, builds, normalizes, and analyzes cron expressions. It also calculates previous and future matching times. It is a cron rule library and CLI; it does not execute or schedule tasks.

Features

  • Standard 5-field expressions: minute hour day-of-month month day-of-week
  • Extended 6-field expressions with seconds
  • Values, lists, ranges, steps, and range-with-step syntax
  • Seven aliases: @hourly, @daily, @midnight, @weekly, @monthly, @yearly, and @annually
  • Detailed validation errors
  • Date/time matching with cron day-of-month OR day-of-week semantics
  • Previous, next, bounded, and range-based execution-time queries
  • English and Chinese descriptions
  • Fluent CronBuilder and quick constructors
  • Normalization, equivalence checks, field set operations, and frequency analysis
  • CLI commands for validation, description, calculation, and matching
  • 151 tests across Wasm, Wasm-GC, JavaScript, and Native

Supported Syntax

Syntax Example Meaning
Wildcard * Any valid value
Value 5 One specific value
List 1,3,5 Any listed value
Range 1-5 Inclusive range
Step */10 Every 10 values
Range + step 10-50/5 Every 5 values from 10 through 50

Field layouts:

# Standard
minute hour day-of-month month day-of-week

# Extended
second minute hour day-of-month month day-of-week

See docs/syntax.md for the complete syntax guide.

Installation

Add MoonCron to moon.mod:

import {
  "001-Elsa/mooncron@0.1.0"
}

Import it in moon.pkg:

import {
  "001-Elsa/mooncron" @mooncron,
}

Published package: 001-Elsa/mooncron on Mooncakes

Library Usage

let cron = @mooncron.CronExpr::parse("*/15 9-17 * * 1-5")

match cron {
  Ok(expr) => {
    let now = @mooncron.DateTime::new(2026, 7, 27, 9, 0)
    println(expr.matches(now).to_string())
    println(expr.describe_en())
    println(expr.describe_cn())

    for time in expr.next_n(now, 5) {
      println(time.to_string())
    }
  }
  Err(err) => println(@mooncron.cron_error_to_string(err))
}

Common API

pub fn CronExpr::parse(String) -> Result[CronExpr, CronError]
pub fn CronExpr::matches(Self, DateTime) -> Bool
pub fn CronExpr::next_after(Self, DateTime) -> DateTime?
pub fn CronExpr::next_n(Self, DateTime, Int) -> Array[DateTime]
pub fn CronExpr::describe_en(Self) -> String
pub fn CronExpr::describe_cn(Self) -> String

pub fn DateTime::new(Int, Int, Int, Int, Int) -> DateTime
pub fn DateTime::new_with_second(Int, Int, Int, Int, Int, Int) -> DateTime
pub fn DateTime::to_string_with_seconds(Self) -> String
pub fn parse_datetime(String) -> DateTime?

pub fn between(Array[CronField], DateTime, DateTime) -> Array[DateTime]
pub fn count_between(Array[CronField], DateTime, DateTime) -> Int
pub fn prev_before(Array[CronField], DateTime) -> DateTime?
pub fn normalize_expression(String) -> Result[String, CronError]
pub fn are_equivalent(Array[CronField], Array[CronField]) -> Bool

The generated public interface is available in pkg.generated.mbti.

CLI Usage

# Validate an expression
moon run cmd/main -- check "*/15 9-18 * * 1-5"

# Generate an English description
moon run cmd/main -- explain "0 9 * * 1-5"

# Generate a Chinese description
moon run cmd/main -- describe "0 9 * * 1-5" --cn

# Calculate future execution times
moon run cmd/main -- next "0 9 * * 1-5" --count 5 \
  --time "2026-07-25 12:00"

# Match a specific time
moon run cmd/main -- matches "0 9 * * 1-5" \
  --time "2026-07-27 09:00"

Validation Errors

MoonCron returns errors that identify the invalid field and constraint:

61 * * * *          -> invalid minute value 61: expected 0..59
*/0 * * * *         -> step value cannot be 0 in field 'minute'
1--5 * * * *        -> invalid range syntax in field 'minute'
* * * * * * *       -> expected 5 or 6 fields but got 7

Verification

Run the same checks used by the submission workflow:

moon fmt --check
moon check --target all --deny-warn
moon test --target all --deny-warn
moon info
moon package

Expected test result for each formal backend:

Total tests: 151, passed: 151, failed: 0.

The all target covers Wasm, Wasm-GC, JavaScript, and Native.

Project Structure

mooncron/
├── cmd/main/              # CLI package
├── docs/                  # Design and syntax documentation
├── *.mbt                  # Library source files
├── *_test.mbt             # Tests
├── moon.mod               # Module metadata
├── moon.pkg               # Root package configuration
├── ACCEPTANCE.md          # Acceptance checklist
├── PROJECT_APPLICATION.md # Competition application
└── LICENSE

Project Boundaries

MoonCron v0.1.0 intentionally does not provide:

  • Actual task execution or a background scheduler
  • Distributed scheduling or task persistence
  • A web UI or user system
  • Timezone or daylight-saving-time support
  • Quartz extensions (L, W, #)
  • A year field (7-field format)
  • Natural-language-to-cron conversion
  • AI integration

Roadmap

  • Timezone and daylight-saving-time support
  • Quartz extensions (L, W, #)
  • Year field support
  • Cron expression visualization
  • Natural-language-to-cron conversion

License

Apache-2.0

关于
125.0 KB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号