forked from Proxmox/proxmox
proxmox-time: calendar-events: make compute_next_event a method
and deprecated the standalone function Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
032787a6a3
commit
a96e9fb724
@ -35,139 +35,148 @@ pub struct CalendarEvent {
|
||||
pub(crate) year: Vec<DateTimeValue>,
|
||||
}
|
||||
|
||||
impl CalendarEvent {
|
||||
/// Computes the next timestamp after `last`. If `utc` is false, the local
|
||||
/// timezone will be used for the calculation.
|
||||
pub fn compute_next_event(&self, last: i64, utc: bool) -> Result<Option<i64>, Error> {
|
||||
let last = last + 1; // at least one second later
|
||||
|
||||
let all_days = self.days.is_empty() || self.days.is_all();
|
||||
|
||||
let mut t = TmEditor::with_epoch(last, utc)?;
|
||||
|
||||
let mut count = 0;
|
||||
|
||||
loop {
|
||||
// cancel after 1000 loops
|
||||
if count > 1000 {
|
||||
return Ok(None);
|
||||
} else {
|
||||
count += 1;
|
||||
}
|
||||
|
||||
if !self.year.is_empty() {
|
||||
let year: u32 = t.year().try_into()?;
|
||||
if !DateTimeValue::list_contains(&self.year, year) {
|
||||
if let Some(n) = DateTimeValue::find_next(&self.year, year) {
|
||||
t.add_years((n - year).try_into()?)?;
|
||||
continue;
|
||||
} else {
|
||||
// if we have no valid year, we cannot find a correct timestamp
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !self.month.is_empty() {
|
||||
let month: u32 = t.month().try_into()?;
|
||||
if !DateTimeValue::list_contains(&self.month, month) {
|
||||
if let Some(n) = DateTimeValue::find_next(&self.month, month) {
|
||||
t.add_months((n - month).try_into()?)?;
|
||||
} else {
|
||||
// if we could not find valid month, retry next year
|
||||
t.add_years(1)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if !self.day.is_empty() {
|
||||
let day: u32 = t.day().try_into()?;
|
||||
if !DateTimeValue::list_contains(&self.day, day) {
|
||||
if let Some(n) = DateTimeValue::find_next(&self.day, day) {
|
||||
t.add_days((n - day).try_into()?)?;
|
||||
} else {
|
||||
// if we could not find valid mday, retry next month
|
||||
t.add_months(1)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if !all_days {
|
||||
// match day first
|
||||
let day_num: u32 = t.day_num().try_into()?;
|
||||
let day = WeekDays::from_bits(1 << day_num).unwrap();
|
||||
if !self.days.contains(day) {
|
||||
if let Some(n) = ((day_num + 1)..7)
|
||||
.find(|d| self.days.contains(WeekDays::from_bits(1 << d).unwrap()))
|
||||
{
|
||||
// try next day
|
||||
t.add_days((n - day_num).try_into()?)?;
|
||||
} else {
|
||||
// try next week
|
||||
t.add_days((7 - day_num).try_into()?)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// this day
|
||||
if !self.hour.is_empty() {
|
||||
let hour = t.hour().try_into()?;
|
||||
if !DateTimeValue::list_contains(&self.hour, hour) {
|
||||
if let Some(n) = DateTimeValue::find_next(&self.hour, hour) {
|
||||
// test next hour
|
||||
t.set_time(n.try_into()?, 0, 0)?;
|
||||
} else {
|
||||
// test next day
|
||||
t.add_days(1)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// this hour
|
||||
if !self.minute.is_empty() {
|
||||
let minute = t.min().try_into()?;
|
||||
if !DateTimeValue::list_contains(&self.minute, minute) {
|
||||
if let Some(n) = DateTimeValue::find_next(&self.minute, minute) {
|
||||
// test next minute
|
||||
t.set_min_sec(n.try_into()?, 0)?;
|
||||
} else {
|
||||
// test next hour
|
||||
t.set_time(t.hour() + 1, 0, 0)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// this minute
|
||||
if !self.second.is_empty() {
|
||||
let second = t.sec().try_into()?;
|
||||
if !DateTimeValue::list_contains(&self.second, second) {
|
||||
if let Some(n) = DateTimeValue::find_next(&self.second, second) {
|
||||
// test next second
|
||||
t.set_sec(n.try_into()?)?;
|
||||
} else {
|
||||
// test next min
|
||||
t.set_min_sec(t.min() + 1, 0)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let next = t.into_epoch()?;
|
||||
return Ok(Some(next));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify the format of the [CalendarEvent]
|
||||
pub fn verify_calendar_event(i: &str) -> Result<(), Error> {
|
||||
parse_calendar_event(i)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute the next event
|
||||
/// Compute the next event. Use [CalendarEvent::compute_next_event] instead.
|
||||
#[deprecated="use method 'compute_next_event' of CalendarEvent instead"]
|
||||
pub fn compute_next_event(
|
||||
event: &CalendarEvent,
|
||||
last: i64,
|
||||
utc: bool,
|
||||
) -> Result<Option<i64>, Error> {
|
||||
|
||||
let last = last + 1; // at least one second later
|
||||
|
||||
let all_days = event.days.is_empty() || event.days.is_all();
|
||||
|
||||
let mut t = TmEditor::with_epoch(last, utc)?;
|
||||
|
||||
let mut count = 0;
|
||||
|
||||
loop {
|
||||
// cancel after 1000 loops
|
||||
if count > 1000 {
|
||||
return Ok(None);
|
||||
} else {
|
||||
count += 1;
|
||||
}
|
||||
|
||||
if !event.year.is_empty() {
|
||||
let year: u32 = t.year().try_into()?;
|
||||
if !DateTimeValue::list_contains(&event.year, year) {
|
||||
if let Some(n) = DateTimeValue::find_next(&event.year, year) {
|
||||
t.add_years((n - year).try_into()?)?;
|
||||
continue;
|
||||
} else {
|
||||
// if we have no valid year, we cannot find a correct timestamp
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !event.month.is_empty() {
|
||||
let month: u32 = t.month().try_into()?;
|
||||
if !DateTimeValue::list_contains(&event.month, month) {
|
||||
if let Some(n) = DateTimeValue::find_next(&event.month, month) {
|
||||
t.add_months((n - month).try_into()?)?;
|
||||
} else {
|
||||
// if we could not find valid month, retry next year
|
||||
t.add_years(1)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if !event.day.is_empty() {
|
||||
let day: u32 = t.day().try_into()?;
|
||||
if !DateTimeValue::list_contains(&event.day, day) {
|
||||
if let Some(n) = DateTimeValue::find_next(&event.day, day) {
|
||||
t.add_days((n - day).try_into()?)?;
|
||||
} else {
|
||||
// if we could not find valid mday, retry next month
|
||||
t.add_months(1)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if !all_days { // match day first
|
||||
let day_num: u32 = t.day_num().try_into()?;
|
||||
let day = WeekDays::from_bits(1<<day_num).unwrap();
|
||||
if !event.days.contains(day) {
|
||||
if let Some(n) = ((day_num+1)..7)
|
||||
.find(|d| event.days.contains(WeekDays::from_bits(1<<d).unwrap()))
|
||||
{
|
||||
// try next day
|
||||
t.add_days((n - day_num).try_into()?)?;
|
||||
} else {
|
||||
// try next week
|
||||
t.add_days((7 - day_num).try_into()?)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// this day
|
||||
if !event.hour.is_empty() {
|
||||
let hour = t.hour().try_into()?;
|
||||
if !DateTimeValue::list_contains(&event.hour, hour) {
|
||||
if let Some(n) = DateTimeValue::find_next(&event.hour, hour) {
|
||||
// test next hour
|
||||
t.set_time(n.try_into()?, 0, 0)?;
|
||||
} else {
|
||||
// test next day
|
||||
t.add_days(1)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// this hour
|
||||
if !event.minute.is_empty() {
|
||||
let minute = t.min().try_into()?;
|
||||
if !DateTimeValue::list_contains(&event.minute, minute) {
|
||||
if let Some(n) = DateTimeValue::find_next(&event.minute, minute) {
|
||||
// test next minute
|
||||
t.set_min_sec(n.try_into()?, 0)?;
|
||||
} else {
|
||||
// test next hour
|
||||
t.set_time(t.hour() + 1, 0, 0)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// this minute
|
||||
if !event.second.is_empty() {
|
||||
let second = t.sec().try_into()?;
|
||||
if !DateTimeValue::list_contains(&event.second, second) {
|
||||
if let Some(n) = DateTimeValue::find_next(&event.second, second) {
|
||||
// test next second
|
||||
t.set_sec(n.try_into()?)?;
|
||||
} else {
|
||||
// test next min
|
||||
t.set_min_sec(t.min() + 1, 0)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let next = t.into_epoch()?;
|
||||
return Ok(Some(next))
|
||||
}
|
||||
event.compute_next_event(last, utc)
|
||||
}
|
||||
|
||||
/// Parse a [CalendarEvent]
|
||||
|
@ -23,7 +23,7 @@ fn test_compute_next_event() -> Result<(), Error> {
|
||||
Err(err) => bail!("parsing '{}' failed - {}", v, err),
|
||||
};
|
||||
|
||||
match compute_next_event(&event, last, true) {
|
||||
match event.compute_next_event(last, true) {
|
||||
Ok(Some(next)) => {
|
||||
if next == expect {
|
||||
println!("next {:?} => {}", event, next);
|
||||
@ -49,7 +49,7 @@ fn test_compute_next_event() -> Result<(), Error> {
|
||||
Err(err) => bail!("parsing '{}' failed - {}", v, err),
|
||||
};
|
||||
|
||||
match compute_next_event(&event, last, true)? {
|
||||
match event.compute_next_event(last, true)? {
|
||||
None => Ok(()),
|
||||
Some(next) => bail!(
|
||||
"compute next for '{}' succeeded, but expected fail - result {}",
|
||||
|
Loading…
Reference in New Issue
Block a user