CalendarData#

A named working-time calendar. Calendars go in ProjectData::calendars; tasks and resources point at them by id through their calendar_id fields. Build it with a struct literal.

Declaration#

pub struct CalendarData {
    pub id: Id,
    pub worktime: Option<Worktime>,
}

Fields#

Field Type Default Description
id Id required Calendar id, unique among the project's calendars. "global" replaces the built-in default calendar (Monday to Friday, 08:00-12:00 and 13:00-17:00).
worktime Option<Worktime> None Working hours, weekdays and date exceptions. None gives the built-in hours and weekdays with no exceptions.

id#

pub id: Id

The key that TaskData::calendar_id and ResourceData::calendar_id refer to. Without a calendar named "global", the project still has one: the built-in Monday to Friday, 08:00-12:00 and 13:00-17:00.

worktime#

pub worktime: Option<Worktime>

When the calendar works. None is the same as Some(Worktime::default()).

Errors#

A calendar fails validation with Error::Input at the path calendars[i] when:

  • its id repeats the id of an earlier calendar in the list
  • its worktime leaves no working time at all

Errors inside worktime are reported at calendars[i].worktime...; see Worktime and TimeRange.

To change a calendar, see SchedulingChanges.

Example#

A project-wide calendar that works Monday to Friday, 09:00-17:00, with one holiday, and a second calendar that keeps the default hours but works Saturdays:

use std::collections::BTreeMap;

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

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let holiday = NaiveDate::from_ymd_opt(2026, 8, 14).ok_or("invalid date")?;

    let global = CalendarData {
        id: "global".into(),
        worktime: Some(Worktime {
            hours: Some(vec![TimeRange { start: 9 * 60, end: 17 * 60 }]),
            days: Some([false, true, true, true, true, true, false]), // Sun..Sat
            dates: BTreeMap::from([(holiday, DayRule::Off)]),
        }),
    };

    let six_day = CalendarData {
        id: "six-day".into(),
        worktime: Some(Worktime {
            days: Some([false, true, true, true, true, true, true]),
            ..Default::default()
        }),
    };

    let data = ProjectData {
        calendars: vec![global, six_day],
        ..Default::default()
    };
    println!("{} calendars", data.calendars.len());
    Ok(())
}

NaiveDate comes from chrono (cargo add chrono).

For choosing which calendar a task or assignment works on, see Working time and calendars.

  • CalendarMode - decides whether task or resource calendars place the work
  • DayRule - a date exception inside a calendar's worktime
  • TaskData - tasks select a calendar through calendar_id
  • Working time and calendars - defining calendars and assigning them to tasks and resources