CronTab

A lightweight, thread-safe cron job scheduler for Rust with support for both sync and async execution.
Features
- ⚡ Sync & Async - Choose the execution mode that fits your application
- 🌍 Timezone Aware - Full timezone support via chrono
- 🎯 Second Precision - 7-field cron expressions with second-level scheduling
- ⏰ One-Time Execution - Schedule tasks to run once at a specific time or after a delay
- 🔧 Runtime Control - Add, remove, start, and stop jobs dynamically
- 🛡️ Thread Safe - Built with Rust's safety guarantees
Installation
Add to your Cargo.toml:
[dependencies]
cron_tab = { version = "0.2", features = ["sync", "async"] }
Usage
Synchronous Jobs
use chrono::Utc;
use cron_tab::Cron;
fn main() {
let mut cron = Cron::new(Utc);
cron.add_fn("* * * * * * *", || {
println!("Running every second!");
}).unwrap();
cron.start();
std::thread::sleep(std::time::Duration::from_secs(10));
cron.stop();
}
Asynchronous Jobs
use chrono::Utc;
use cron_tab::AsyncCron;
#[tokio::main]
async fn main() {
let mut cron = AsyncCron::new(Utc);
cron.add_fn("0 * * * * * *", || async {
println!("Running every minute!");
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
}).await.unwrap();
cron.start().await;
tokio::time::sleep(tokio::time::Duration::from_secs(60)).await;
cron.stop().await;
}
Cron Expression Format
CronTab uses 7-field cron expressions with second precision:
sec min hour day month weekday year
* * * * * * *
Field ranges:
sec: 0-59
min: 0-59
hour: 0-23
day: 1-31
month: 1-12
weekday: 0-6 (Sunday=0)
year: 1970-3000
Common patterns:
| Expression |
Description |
* * * * * * * |
Every second |
0 * * * * * * |
Every minute |
0 0 * * * * * |
Every hour |
0 0 0 * * * * |
Daily at midnight |
0 0 9 * * MON-FRI * |
Weekdays at 9 AM |
0 30 14 * * * * |
Daily at 2:30 PM |
Advanced Examples
One-Time Execution
Schedule tasks to run exactly once at a specific time or after a delay:
use chrono::{Duration, Utc};
use cron_tab::Cron;
fn main() {
let mut cron = Cron::new(Utc);
cron.add_fn_after(std::time::Duration::from_secs(5), || {
println!("This runs once after 5 seconds");
}).unwrap();
let target_time = Utc::now() + Duration::seconds(10);
cron.add_fn_once(target_time, || {
println!("This runs once at the specified time");
}).unwrap();
cron.start();
std::thread::sleep(std::time::Duration::from_secs(12));
cron.stop();
}
Async One-Time Execution
use chrono::{Duration, Utc};
use cron_tab::AsyncCron;
#[tokio::main]
async fn main() {
let mut cron = AsyncCron::new(Utc);
cron.add_fn_after(std::time::Duration::from_secs(5), || async {
println!("Async task runs once after 5 seconds");
}).await.unwrap();
let target_time = Utc::now() + Duration::seconds(10);
cron.add_fn_once(target_time, || async {
println!("Async task runs once at the specified time");
}).await.unwrap();
cron.start().await;
tokio::time::sleep(std::time::Duration::from_secs(12)).await;
cron.stop().await;
}
Managing Jobs Dynamically
use chrono::Utc;
use cron_tab::Cron;
fn main() {
let mut cron = Cron::new(Utc);
cron.start();
let job_id = cron.add_fn("*/5 * * * * * *", || {
println!("Running every 5 seconds");
}).unwrap();
std::thread::sleep(std::time::Duration::from_secs(15));
cron.remove(job_id);
cron.stop();
}
Shared State in Async Jobs
use std::sync::Arc;
use chrono::Utc;
use cron_tab::AsyncCron;
use tokio::sync::Mutex;
#[tokio::main]
async fn main() {
let mut cron = AsyncCron::new(Utc);
let counter = Arc::new(Mutex::new(0));
let counter_clone = counter.clone();
cron.add_fn("* * * * * * *", move || {
let counter = counter_clone.clone();
async move {
let mut count = counter.lock().await;
*count += 1;
println!("Count: {}", *count);
}
}).await.unwrap();
cron.start().await;
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
cron.stop().await;
}
Using Custom Timezones
use chrono::FixedOffset;
use cron_tab::Cron;
fn main() {
let tokyo_tz = FixedOffset::east_opt(9 * 3600).unwrap();
let mut cron = Cron::new(tokyo_tz);
cron.add_fn("0 0 9 * * * *", || {
println!("Good morning from Tokyo!");
}).unwrap();
cron.start();
}
Feature Flags
Choose the features you need:
cron_tab = "0.2"
cron_tab = { version = "0.2", features = ["async"] }
cron_tab = { version = "0.2", features = ["all"] }
Examples
Run the included examples:
cargo run --example simple --features sync
cargo run --example async_simple --features async
cargo run --example one_time_execution --features sync
cargo run --example async_one_time_execution --features async
Testing
cargo test --all-features
cargo test --features sync
cargo test --features async
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Run
cargo fmt and cargo clippy --all-features
- Submit a pull request
For major changes, open an issue first to discuss your proposal.
License
MIT License - see LICENSE for details.
Links