1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! This crate allows to parse a cron-like, human-readable expression.
//! The resulting object can be turned into an iterator to compute the next date
//! (as a `time::OffsetDateTime`) one at a time. By default dates are computed
//! in the current local offset, but the iterator can be configured to use other
//! offsets.
//!
//! # Example
//! ```rust
//! use cron_lingo::Schedule;
//! use std::str::FromStr;
//! use time::macros::offset;
//!
//! fn main() -> Result<(), cron_lingo::error::Error> {
//!     // Create a schedule from an expression and iterate.
//!     let expr = "at 6:30 AM on Mondays and Thursdays";
//!     let schedule1 = Schedule::from_str(expr)?;
//!     assert!(schedule1.iter()?.next().is_some());
//!
//!     // Create another schedule, add it to the first, and then iterate.
//!     let schedule2 = Schedule::from_str("at 8 PM on the first Sunday")?;
//!     let mut combination = schedule1 + schedule2;
//!     assert!(combination.iter()?.next().is_some());
//!
//!     // Finally add another to the existing collection of schedules.
//!     let schedule3 = Schedule::from_str("at 12:00 PM on the last Friday")?;
//!     combination += schedule3;
//!     assert!(combination.iter()?.next().is_some());
//!
//!     // The examples above assume that the current local offset is to
//!     // be used to determine the dates, but dates can also be computed
//!     // in different offsets.
//!     let expr = "at 6:30 AM on Mondays and Thursdays";
//!     let schedule = Schedule::from_str(expr)?;
//!     assert!(schedule.iter()?.assume_offset(offset!(+3)).next().is_some());
//!     Ok(())
//! }
//! ```
//!
//! # Expression syntax
//!
//! A single expression consists of three parts:
//! a time specification, and optionally a weekday and week specification.
//!
//! > \<time spec\> [\<weekday spec\>] [\<week spec\>]
//!
//! Here are a few random examples of complete expressions:
//!
//! * at 1 AM
//! * 6 PM on Saturdays and Sundays
//! * at 2 PM (Mondays, Thursdays) in even weeks
//! * at 6:45 PM on Wednesdays in odd weeks
//! * at 6:30 AM on Mondays
//! * at 6 AM, 6 PM (Mondays)
//! * at 8 AM on the first Sunday
//!
//! This table gives some more examples for each type of specification in a block:
//!
//! | Times                  | Weekday (optional)           | Week (optional)  |
//! | ---------------------- | ---------------------------- | ---------------- |
//! | at every full hour     | on Mondays and Tuesdays      | in odd weeks     |
//! | at 7:30 AM and 7:30 PM | on Tuesdays, Saturdays       | in even weeks    |
//! | at 6 AM, 6 PM and 8 PM | on Fridays                   |                  |
//! | at 6 AM, 12 AM, 6 PM   |                              |                  |
//! | at 8:30 AM             |                              | in odd weeks     |
//! | at 8 AM                | on Wednesdays                |                  |
//! | at 08 AM               | on the first Monday          |                  |
//! | at 08 PM               | on the 4th Friday            | in even weeks    |
//! | at 08 PM               | on Wednesdays and Sundays    |                  |
//! | at 5:45 AM             | (Mondays and Thursdays)      |                  |
//! | at 6 AM and 6 PM       | (first Sunday)               |                  |
//! | at 1:15 PM             | (1st Monday and 2nd Friday)  |                  |
//! | at 1 PM                | on the third Monday          |                  |
//! | at 1:50 PM             | on the 3rd Monday            |                  |
//! | at 1 PM                | on the 4th Saturday          |                  |
//! | at 6 PM                | on the last Monday           |                  |
//!
//! ## Ruleset
//!
//! The examples above cover the basic rules of the expression syntax to a certain (and for most use cases
//! probably sufficient) extent.
//! Nevertheless, here is a list of "rules" that an expression must comply with and that you might find useful to avoid mistakes:
//!
//! ### Times specification
//!
//! * must start with _at_
//! * then follows either _every full hour_ OR a list of distinct _times_
//! * a _time_ adheres to the 12-hour-clock, so a number from 1 to 12 followed by _AM_ or _PM_ (uppercase!), e.g. 1 AM or 1 PM
//! * a time may also contain _minutes_ from 00 to 59 (separated from the hour by a _colon_). Omitting the minutes means
//! _on the hour_, e.g. 8 PM == 8:00 PM
//! * distinct times are concatenated by _commata_ or _and_
//!
//! ### Weekday specification
//!
//! * is _optional_
//! * succeeds the _time spec_
//! * consists of a list of _weekdays_ with optional _modifiers_ to select only specific weekdays in a month.
//! * the list either starts with _on_ OR is enclosed by simple braces _()_ for compactness
//! * a weekday must be one of [ Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday ] appended with an ***s*** if e.g. _every_ Monday is to be included OR a weekday preceded by a modifier [ first | 1st | second | 2nd | third | 3rd | fourth | 4th | last ] in order to include only specific weekdays in a month.
//!
//! ### Week specification
//!
//! * is _optional_
//! * must be one of _in even weeks_ / _in odd weeks_
pub mod error;
mod parse;
pub mod schedule;
mod types;

pub use self::schedule::Schedule;