Skip to main content

Adding calendar

Overview

The functionality is available in PRO Edition only

PRO

The Calendar module defines the working-time rules used by the Gantt chart. It provides all time-related calculations: how many hours are worked per day, which days are non-working, how task durations are computed, and how date arithmetic behaves in a project plan.

You can configure weekly schedules, introduce exceptions, or apply custom logic. The Gantt will automatically use this calendar to compute task start/end dates, shifts, progress updates, drag operations, and all duration-based calculations. By attaching a calendar to Gantt, you fully control its date-handling logic.

note

The Calendar operates at the day level. It allows you to set the number of working hours per day, but not the specific working hours schedule within the day (e.g., 09:00-13:00, 14:00-18:00).

The Calendar API description you can find here: Calendar.

Initializing the Calendar

Install and import the module:

import { Calendar } from "@svar/gantt-store"; 

Create a calendar instance:

const calendar = new Calendar();

Without configuration, the Calendar uses a standard 40-hour workweek (Mon-Fri).

Adding a default Calendar

You can attach a calendar directly to Gantt. This example shows a default configuration with a standard 8-hour working day for Monday-Friday:

import { useState } from "react";
import { Gantt } from "@svar/react-gantt";
import { Calendar } from "@svar/gantt-store";
import { getData } from "../data";

const { tasks: initialTasks, links: initialLinks } = getData();
const calendar = new Calendar({
weekHours: {
monday: 8,
tuesday: 8,
wednesday: 8,
thursday: 8,
friday: 8,
saturday: 0,
sunday: 0,
},
});

export default function Example() {
const [tasks] = useState(initialTasks);
const [links] = useState(initialLinks);

return <Gantt tasks={tasks} links={links} calendar={calendar} />;
}
info

You should always provide valid date values for Gantt tasks. If updating a task through the update-task action, provide all date fields: start, end, and duration. Calendar supports only durationUnit: "day".

Adding a custom Calendar

You can adjust the weekly schedule, working hours, or behavior to match project-specific requirements:

import { useState, useRef } from "react";
import { Gantt } from "@svar/react-gantt";
import { Calendar } from "@svar/gantt-store";
import { getData } from "../data";

export default function CustomCalendarExample() {
// Load initial project data
const { tasks: initialTasks, links: initialLinks } = getData();
const [tasks, setTasks] = useState(initialTasks);
const [links] = useState(initialLinks);

// Initialize custom calendar
const calendar = new Calendar({
name: "Part-time schedule",
weekHours: {
monday: 4,
tuesday: 4,
wednesday: 4,
thursday: 4,
friday: 4,
saturday: 0,
sunday: 0,
},
});

// Reference to Gantt API
const apiRef = useRef(null);

return (
<Gantt
ref={apiRef}
calendar={calendar}
tasks={tasks}
links={links}
/>
);
}

Using rules and exceptions

Rules allow overriding the default weekly schedule for specific dates or patterns. They are commonly used for holidays, special working days, or dynamic scheduling logic. The example below demonstrates:

  • creating a custom weekly schedule
  • adding one-time exceptions
  • enabling recurring “non-working Monday” rule from UI
  • adjusting tasks that fall onto non-working dates
import { useState, useRef } from "react";
import { Gantt } from "@svar/react-gantt";
import { Calendar } from "@svar/gantt-store";
import { Button } from "@svar-ui/react-core";
import { getData } from "../data";

export default function RulesAndExceptionsExample() {
const { tasks: initialTasks, links: initialLinks } = getData();
const [tasks, setTasks] = useState(initialTasks);
const [links] = useState(initialLinks);

const calendar = new Calendar({
weekHours: {
monday: 8,
tuesday: 8,
wednesday: 8,
thursday: 8,
friday: 8,
saturday: 0,
sunday: 0,
},
});

// Add one-time rule examples
calendar.addRule((date: Date) => {
const month = date.getMonth();
const day = date.getDate();

if (month === 3 && day === 3) return 0;
if (month === 3 && day === 7) return 8;
return undefined;
});

const apiRef = useRef<any>(null);

function addNewRule() {
calendar.addRule((date: Date) => {
const weekday = date.getDay();
if (weekday === 1) return 0; // make Mondays non-working
return undefined;
});

// Here we get serialized tasks and correct task start date using calendar methods
// Use the Gantt API via ref
if (apiRef.current) {
const serialized = apiRef.current.serialize();
const adjusted = serialized.map((task: any) => {
if (!calendar.isWorkingDay(task.start)) {
task.start = calendar.getNextWorkingDay(task.start);
}
return task;
});
setTasks(adjusted);
}
}

return (
<div className="rows">
<div className="bar">
<Button type="primary" onClick={addNewRule}>
Add rule
</Button>
</div>

<div className="gtcell">
<Gantt ref={apiRef} calendar={calendar} tasks={tasks} links={links} />
</div>
</div>
);
}

Rules are evaluated on top of the weekly schedule and always take priority, allowing your calendar to reflect real-world conditions such as holidays, shortened days, and dynamic scheduling rules.

info

Whenever new rules or exceptions are added, you should resend valid tasks back into Gantt. This ensures that task positions, start dates, and durations are recalculated correctly based on the new working-time logic.


Related articles: