Worktime#

The working time of one calendar: daily hours, working weekdays and per-date exceptions. It's the worktime field of CalendarData. Build it with a struct literal, or start from Worktime::default(), which is the built-in schedule.

Declaration#

#[derive(Clone, Debug, Default)]
pub struct Worktime {
    pub hours: Option<Vec<TimeRange>>,
    pub days: Option<[bool; 7]>,
    pub dates: BTreeMap<chrono::NaiveDate, DayRule>,
}

Fields#

Field Type Default Description
hours Option<Vec<TimeRange>> None = 08:00-12:00, 13:00-17:00 Working hours of every working weekday. All working weekdays share the same hours.
days Option<[bool; 7]> None = Monday-Friday Working weekdays. Index 0 is Sunday, index 6 is Saturday. true marks a working day.
dates BTreeMap<chrono::NaiveDate, DayRule> empty Date exceptions. An entry replaces the weekday rule for that date.

hours#

pub hours: Option<Vec<TimeRange>>

Each TimeRange is one working interval within the day. The order of the ranges doesn't matter. An empty list means no working hours on any weekday, so only dates entries can add working time.

days#

pub days: Option<[bool; 7]>

A weekday marked false has no working time unless a dates entry overrides it.

dates#

pub dates: BTreeMap<chrono::NaiveDate, DayRule>

Per-date overrides, keyed by calendar date. The DayRule for a date wins over days and hours.

Validation#

A project with an invalid Worktime is rejected when it's loaded, with an InputError of kind Validation:

Problem Error path
A range in hours is outside 00:00-24:00 calendars[{i}].worktime.hours

Ranges in dates entries are checked as described on DayRule.

Example#

The example uses chrono for the date keys: cargo add chrono.

use std::collections::BTreeMap;

use chrono::NaiveDate;
use plen_core::{CalendarData, DayRule, TimeRange, Worktime};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut dates = BTreeMap::new();
    // Public holiday.
    dates.insert(NaiveDate::from_ymd_opt(2026, 12, 25).ok_or("bad date")?, DayRule::Off);
    // Short working Saturday, 09:00-13:00.
    dates.insert(
        NaiveDate::from_ymd_opt(2026, 12, 19).ok_or("bad date")?,
        DayRule::Hours(vec![TimeRange { start: 9 * 60, end: 13 * 60 }]),
    );

    let calendar = CalendarData {
        id: "office".into(),
        worktime: Some(Worktime {
            // 09:00-18:00, minutes from midnight.
            hours: Some(vec![TimeRange { start: 9 * 60, end: 18 * 60 }]),
            // Sunday..Saturday: Monday-Friday.
            days: Some([false, true, true, true, true, true, false]),
            dates,
        }),
    };

    println!("{calendar:?}");
    Ok(())
}