zslayton / cron

A cron expression parser in Rust
Apache License 2.0
357 stars 69 forks source link

Adding examples for using cron with timezone #109

Open stevenhansel opened 2 years ago

stevenhansel commented 2 years ago

It would be nice if we have some examples for running cron with timezones because I definitely would be helped if there are some examples for that. I would be glad to add some examples if this issue is approved.

Here's a really rough example I have come up with:

I want the cron parser to run every 00:00 AM in GMT+7 (Jakarta time)

let schedule = Schedule::from_str("0 0 0 * * *").unwrap();
let today_utc = (Utc::today() - chrono::Duration::days(1))
    .and_time(NaiveTime::from_hms(17, 0, 0))
    .unwrap();

if let Some(event) = schedule.after(&today_utc).take(1).next() {
    println!("next tick: {}", event);
}

The output is next tick: 2022-09-09 00:00:00 WIB

Also, there is definitely a hurdle with the timezones because if I want to get 00:00 AM in GMT+7 that means I have to run it at 17:00 UTC. But, for areas that have daylight saving time like Adelaide, this won't work because the time difference changes over time. I think we need to add a support for adjusting with timezone, e.g.

Schedule::from_str("0 0 0 * * *").with_timezone(chrono_tz::Asia::Jakarta).unwrap()
Thorongil80 commented 11 months ago

Hi, should you not simply feed a Jakarta time zone "today" to after()?

let schedule = Schedule::from_str("0 0 0 * * *").unwrap();

let now_jakarta = Utc::now().with_timezone(chrono_tz::Asia::Jakarta).unwrap();

if let Some(event) = schedule.after(&now_jakarta).take(1).next() {
    println!("next tick: {}", event);
}

??

I am going to try to implement time zone support in our application that uses cron for scheduling. The application runs on ahost which has its system time set to Utc and the application internally uses Utc for date and time processing. But we want to be able to say "this cron schedule here is to be executed in xy time", e.g. "Europe/Berlin".

As to my understanding, the "event" that comes back from schedule.after() will then be a DateTime<chrono_tz::Asia::Jakarta> - which you just need to convert to a DateTime if you wish so.

The cron expression evaluator uses to my understanding the same data type that is fed in and calculates internally with naivetime.

A lot more telling is the upcoming(&TimeZone) iterator. This calculates from now but uses given time zone. I try to use that in my code for clarity, not the "after()", but that should behave the same I guess.

So to my understanding, the cron crate should have proper time zone support already? And sorry, no, your static calculation above is far away from proper time zone calculation - as you noticed already you do not know about DST in different parts of the world. This is already a given if you use the proper time conversions already built into chrono and chrono-tz.....

Thorongil80 commented 11 months ago

it works just like said. You give DateTime<Tz> to after() or you give Tz to upcoming().

cron calculates then in the given Time Zone. Tz being a Time Zone of chrono_tc