| Crates.io | easy-schedule |
| lib.rs | easy-schedule |
| version | 0.11.3 |
| created_at | 2025-04-06 06:33:26.665705+00 |
| updated_at | 2025-07-05 12:39:05.730143+00 |
| description | A flexible task scheduler built on Tokio with multiple scheduling options and skip conditions |
| homepage | |
| repository | https://github.com/rain2307/easy-schedule |
| max_upload_size | |
| id | 1622667 |
| size | 98,332 |
A flexible and powerful task scheduler built on Tokio, providing multiple scheduling options with advanced skip conditions and timezone support.
wait(5), at(14:30)Add to your Cargo.toml:
[dependencies]
easy-schedule = "0.11"
tokio = { version = "1", features = ["full"] }
time = { version = "0.3", features = ["macros"] }
use easy_schedule::prelude::*;
use time::{Time, OffsetDateTime, macros::offset};
#[derive(Debug)]
struct MyTask {
name: String,
}
#[async_trait]
impl Notifiable for MyTask {
fn get_task(&self) -> Task {
Task::Wait(5, None) // Wait 5 seconds
}
async fn on_time(&self, cancel: CancellationToken) {
println!("{} executed!", self.name);
cancel.cancel(); // Stop after first execution
}
}
#[tokio::main]
async fn main() {
let scheduler = Scheduler::new();
scheduler.run(MyTask { name: "my_task".to_string() }).await;
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
scheduler.stop();
}
use easy_schedule::prelude::*;
use time::{Time, macros::time};
// Wait 30 seconds then execute once
let wait_task = Task::Wait(30, None);
let scheduler = Scheduler::new();
// Execute every 60 seconds
let interval_task = Task::Interval(60, None);
let scheduler = Scheduler::new();
// Execute daily at 9:00 AM
let at_task = Task::At(time!(09:00), None);
let scheduler = Scheduler::new();
// Execute once at specific datetime
let future = OffsetDateTime::now_utc() + time::Duration::minutes(5);
let once_task = Task::Once(future, None);
let scheduler = Scheduler::new();
use easy_schedule::prelude::*;
use time::macros::time;
let skip_rules = vec![
Skip::Day(vec![6, 7]), // Skip weekends
Skip::TimeRange(time!(22:00), time!(06:00)), // Skip night hours
Skip::Time(time!(12:00)), // Skip lunch time
];
let task = Task::Interval(3600, Some(skip_rules)); // Every hour, with skips
let scheduler = Scheduler::new();
use easy_schedule::prelude::*;
let task = Task::Interval(60, None);
let scheduler = Scheduler::new();
// Create a test task that implements Notifiable
struct TestTask(Task);
#[async_trait]
impl Notifiable for TestTask {
fn get_task(&self) -> Task { self.0.clone() }
async fn on_time(&self, _cancel: CancellationToken) {}
}
let test_task = TestTask(task);
if let Some(next_time) = scheduler.get_next_run_time(test_task) {
println!("Next execution: {}", next_time);
} else {
println!("Task will not run (likely skipped)");
}
use easy_schedule::prelude::*;
// Different timezone configurations
let utc_scheduler = Scheduler::with_timezone(0, 0); // UTC
let tokyo_scheduler = Scheduler::with_timezone(9, 0); // JST
let india_scheduler = Scheduler::with_timezone(5, 30); // IST
// Or use minute offsets directly
let custom_scheduler = Scheduler::with_timezone_minutes(330); // UTC+5:30
| Type | Description | Example |
|---|---|---|
Wait(seconds, skip) |
Execute once after delay | Task::Wait(30, None) |
Interval(seconds, skip) |
Execute repeatedly | Task::Interval(60, None) |
At(time, skip) |
Execute daily at time | Task::At(time!(14:30), None) |
Once(datetime, skip) |
Execute at exact datetime | Task::Once(datetime, None) |
| Skip Type | Description | Example |
|---|---|---|
Date(date) |
Skip specific date | Skip::Date(date!(2024-12-25)) |
DateRange(start, end) |
Skip date range | Skip::DateRange(start, end) |
Day(weekdays) |
Skip weekdays (1=Mon, 7=Sun) | Skip::Day(vec![6, 7]) |
DayRange(start, end) |
Skip weekday range | Skip::DayRange(1, 5) |
Time(time) |
Skip specific time | Skip::Time(time!(12:00)) |
TimeRange(start, end) |
Skip time range | Skip::TimeRange(time!(22:00), time!(06:00)) |
#[async_trait]
impl Notifiable for SmartTask {
async fn on_time(&self, cancel: CancellationToken) {
// Custom logic to decide when to stop
if self.should_stop() {
cancel.cancel();
}
}
}
let complex_skips = vec![
Skip::Day(vec![6, 7]), // No weekends
Skip::TimeRange(time!(01:00), time!(06:00)), // No early morning
Skip::Date(date!(2024-12-25)), // No Christmas
];
let task = Task::Interval(1800, Some(complex_skips)); // Every 30 minutes with conditions
Run the comprehensive test suite:
cargo test # Run all tests
cargo test --test skip_tests # Test skip functionality
cargo test --test task_tests # Test task parsing