cloudflare / saffron

The cron parser powering Cron Triggers on Cloudflare Workers
BSD 3-Clause "New" or "Revised" License
238 stars 16 forks source link

Add future time limit iter API #15

Closed ObsidianMinor closed 3 years ago

ObsidianMinor commented 3 years ago

Closes #14

This also refactors future time matching.

Example:

use saffron::Cron;
use chrono::prelude::*;

let cron = "*/10 * * * *".parse::<Cron>().expect("Couldn't parse expression!");
let start = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0);

// effectively the same as iter_from
let _ = cron.clone().iter(start..);

// all matching times in the next 30 minutes
let _ = cron.clone().iter(start..(start + chrono::Duration::from_secs(60 * 30)));
adamchalmers commented 3 years ago

Hi! Quick question on the overall API design before I look into the implementation. Is there a reason you can't just use take_while? IMO it'd be nice to reuse the standard iterator methods, and you could achieve the goal of getting a finite number of next trigger timestamps without writing any extra code.

Here's an example using the take_while API:

use chrono::prelude::*;
use chrono::Duration;
use saffron::Cron;

fn main() {
    let cron = "*/10 * * * *"
        .parse::<Cron>()
        .expect("Couldn't parse expression!");
    let start = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0);

    // all matching times in the next 30 minutes
    for trigger in cron
        .clone()
        .iter_from(start)
        .take_while(|t| *t < start + Duration::minutes(30))
    {
        println!("{}", trigger);
    }
}

That code outputs this:

1970-01-01 00:00:00 UTC
1970-01-01 00:10:00 UTC
1970-01-01 00:20:00 UTC
ObsidianMinor commented 3 years ago

We coouuullldd but to me it's nicer to read and understand iter(start..(start + Duration::minutes(30)). Plus: