use chrono::Utc;
use cron_parser::parse;
use std::env;
fn main() {
let mut args = env::args();
let bin_name = args.next().unwrap_or_else(|| "parse".to_string());
let Some(cron_expr) = args.next() else {
print_usage_and_exit(&bin_name);
};
if cron_expr == "--help" || cron_expr == "-h" {
print_usage_and_exit(&bin_name);
}
let mut count: usize = 5;
let mut rest = args.peekable();
while let Some(arg) = rest.next() {
match arg.as_str() {
"--count" | "-n" => {
let Some(value) = rest.next() else {
eprintln!("Missing value for {arg}");
print_usage_and_exit(&bin_name);
};
count = value.parse::<usize>().unwrap_or_else(|_| {
eprintln!("Invalid value for {arg}: {value}");
print_usage_and_exit(&bin_name);
});
}
"--help" | "-h" => print_usage_and_exit(&bin_name),
_ => {
eprintln!("Unknown argument: {arg}");
print_usage_and_exit(&bin_name);
}
}
}
let now = Utc::now();
println!("Cron expression: {cron_expr}");
println!("Current time: {}", now.format("%Y-%m-%d %H:%M:%S %Z"));
println!();
match parse(&cron_expr, &now) {
Ok(mut next) => {
println!("Next {count} execution times:");
println!("-----------------------------------------------------");
for i in 1..=count {
println!("{:2}. {}", i, next.format("%Y-%m-%d %H:%M:%S %Z"));
match parse(&cron_expr, &next) {
Ok(n) => next = n,
Err(e) => {
eprintln!("\nError calculating next occurrence: {e:?}");
break;
}
}
}
}
Err(e) => {
eprintln!("Error parsing cron expression: {e:?}");
eprintln!();
eprintln!("Common issues:");
eprintln!(" - Invalid field values (e.g., minute > 59)");
eprintln!(" - Invalid range (e.g., 10-5)");
eprintln!(" - Invalid step (e.g., */0)");
eprintln!(" - Wrong number of fields (must be exactly 5)");
std::process::exit(1);
}
}
}
fn print_usage_and_exit(bin_name: &str) -> ! {
eprintln!("Usage: {bin_name} <cron-expression> [--count <n>]");
eprintln!();
eprintln!("Examples:");
eprintln!(" {bin_name} \"*/5 * * * *\"");
eprintln!(" {bin_name} \"0 0 * * *\"");
eprintln!(" {bin_name} \"0 9 * * 1-5\" --count 10");
eprintln!();
eprintln!("Cron expression format:");
eprintln!(" ┌───────────────────── minute (0 - 59)");
eprintln!(" │ ┌─────────────────── hour (0 - 23)");
eprintln!(" │ │ ┌───────────────── dom (1 - 31) day of month");
eprintln!(" │ │ │ ┌─────────────── month (1 - 12)");
eprintln!(" │ │ │ │ ┌───────────── dow (0 - 6 or Sun - Sat) day of week");
eprintln!(" │ │ │ │ │");
eprintln!(" * * * * *");
std::process::exit(1);
}