Calendars

Bryntum Scheduler Pro has a powerful calendar system which defines when work on events can be performed.

The calendar implementation is very performant, even for a big number of calendars. This is achieved by using extensive caching of all data and using fast internal data structures.

Calendars can be assigned to a project as well as events and resources. By default, if an event or resource has no explicitly assigned calendar, it uses the calendar of the project. The default calendar of the project (which is used if not configured explicitly) uses 24/7/365 availability.

Calendars are organized in a tree store (see below for "parent calendars"), which is called calendar manager store. It is available as the calendarManagerStore property of the project.

Individual calendars are represented by the CalendarModel class.

Availability intervals

Internally, a calendar consists of a collection of availability intervals. The intervals have an isWorking field, which defines whether it represents a working time period (true value, is default) or non-working (a holiday or other day off, false value).

The interval is either static, like 2019/05/01 - 2019/05/02 or recurrent (repeating in time) - every year 05/01 - every year 05/02.

A static interval should have startDate and endDate values provided. A recurrent interval should fill the recurrentStartDate and recurrentEndDate fields.

Please note that a recurring interval can be limited to work in a certain time range only. In that case the range should be specified with startDate and endDate field values.

Here is for example an interval specifying 4 hours (08:00-12:00) per weekday Mon .. Fri which will be used only during June of 2025:

{
    "id"           : 999,
    "name"         : "4h / 5d calendar",
    "intervals"    : [
        {
            "startDate"          : "2025-06-01",
            "endDate"            : "2025-07-01",
            "recurrentStartDate" : "every weekday at 12:00",
            "recurrentEndDate"   : "every weekday at 08:00",
            "isWorking"          : false
        }
    ]
}

The value of the recurrentStartDate / recurrentEndDate fields should be specified in the format defined by the excellent library for recurrent events: later. Please refer to its documentation on details.

The working status of a timespan, which does not belong to any availability interval, is defined with the unspecifiedTimeIsWorking field of the calendar.

Intersecting intervals

Consider the following calendar definition with 2 intervals:

{
    id        : 1,
    name      : 'My Calendar',
    intervals : [
        {
            recurrentStartDate : 'at 08:00',
            recurrentEndDate   : 'at 16:00',
            isWorking          : true
        },
        {
            recurrentStartDate : 'on Sat',
            recurrentEndDate   : 'on Mon',
            isWorking          : false
        }
    ],
    unspecifiedTimeIsWorking : false
}

The intention is to define a calendar with "normal" working time 08:00-16:00 and non-working weekend days. However, the intervals intersects - for weekend days, the timespan 08:00-16:00 presents in both intervals, with the different isWorking flag.

Which interval "wins" in such case of intersection is defined by the following rules:

  • Intervals from the child calendar always wins over the parent's
  • Static intervals wins over the recurrent intervals (in the same calendar)
  • Between the static intervals of the calendar, the one with bigger priority field value wins over the one with smaller priority field value.
  • Between the static intervals of the calendar with the same priority, the one with bigger index wins over the one with smaller index ("last win")
  • Between the recurrent intervals of the calendar, the one with bigger priority field value wins over the one with smaller priority field value
  • Between the recurrent intervals of the calendar with the same priority, the ones with bigger index wins over the ones with smaller index ("last win")

Defining project calendar

Usually calendars are loaded to the project together with other data, such as events, resources, etc.

new SchedulerPro({
    // Project configuration
    project : {
        autoLoad  : true,
        transport : {
            load : {
                url : 'loadUrl'
            }
        }
    },
    // other Scheduler configuration
});

The response format should be:


{
    "success": true,
    "project": {
        // Set default project calendar
        "calendar": "weekends"
    },
    "calendars": {
        "rows": [
            // Calendar definition
            {
                "id": "weekends",
                "name": "Weekends",
                // Intervals to define all SA and SU as non-working days
                "intervals": [
                    {
                        "recurrentStartDate": "on Sat",
                        "recurrentEndDate": "on Mon",
                        "isWorking": false
                    }
                ]
            }
        ]
    },
    // other project data, for example events, resources, assignments, etc
}

However, it is possible to define calendars as inline data:

new SchedulerPro({
    // Project configuration
    project : {
        // Set default project calendar
        calendar             : 'weekends',
        // Inline calendar tree
        calendars : [
            // Calendar definition
            {
                id        : 'weekends',
                name      : 'Weekends',
                // Intervals to define all SA and SU as non-working days
                intervals : [
                    {
                        recurrentStartDate : 'on Sat',
                        recurrentEndDate   : 'on Mon',
                        isWorking          : false
                    }
                ]
            }
        ]
        // other Project configs, for example eventStore, resourceStore, assignmentStore, etc
    },
    // other Scheduler configuration
});
When using frameworks, it is recommended to use the ProjectModel component and pass its ref to the BryntumSchedulerPro. Learn more about loading inline data.

Parent calendars

Calendars are organized in a tree store, and thus a CalendarModel has a regular parent property inherited from the TreeNode mixin. It denotes a "parent" calendar, from which the current calendar inherits availability intervals. The intervals, defined in the current calendar overrides the intervals from any parent.

This structure allows very flexible definitions for calendars, from the most common ones at the top of the hierarchy to more specific at the bottom. A more specific calendar will only need to define data that is different from its parent.

Assigning a calendar through the API

To set the calendar of an entity using the data API, use the calendar field. It is available on the ProjectModel, EventModel and ResourceModel.

Assigning a calendar through the UI

To give user the ability to change the calendar of the event using the UI, you can use a ResourceCalendarColumn

Calendar column

Also the TaskEditor has a field for changing the calendar on the "Advanced" tab.

Calendar field

Scheduling logic when using Project, Event and Resource calenders

In Scheduler Pro there are three types of calendars:

  • Project calendar - Defines default availability.
  • Event calendar - Defines availability intervals when it is possible to work on an event. Defaults to project calendar.
  • Resource calendar - Defines availability intervals when a given resource can work. Defaults to project calendar.

When an event and a resource share the same calendar, it is very easy to tell working time from non-working time. But, if you assign a custom calendar to an event, it gets a bit more complicated. The event will then be scheduled in intersecting time intervals which are working in both calendars.

For example, let's say the project calendar defines Saturday and Sunday as non-working, the Event calendar says Mondays are non-working and the Resource calendar defines Tuesdays as non-working. Now let's say we want to schedule an event starting Thursday which should last three days. The event could be scheduled only on days allowed by both resource and event calendars. So it starts on Thursday, continues on Friday, skips Sat and Sun, then continues Mon and Tue, and finishes at the end of Wednesday. In the scheduling view it would appear that event lasts for 7 days.

Duration conversion

Previous versions of the Scheduler had properties responsible for duration conversions defined on calendars. In the Scheduler Pro they are defined on the project model (see hoursPerDay, daysPerWeek and daysPerMonth for details).