Calendar Settings in ASP.NET MVC Gantt Chart Control
The Gantt Chart control supports advanced calendar configuration through the CalendarSettings property, enabling management of working hours, holidays, and task-specific scheduling. Calendar settings control how the Gantt Chart calculates task duration, determines working days, and schedules dependencies.
The CalendarSettings property contains two key configurations:
- Project Calendar: Defines working hours and holidays for the entire project, applied to all tasks by default
- Task Calendars: Defines custom working days and holidays for specific tasks, enabling team-specific or shift-based scheduling
Project calendar
The CalendarSettings.projectCalendar defines the default working hours and non-working days for the entire project. All tasks follow the project calendar unless assigned a task-specific calendar.
Configure project working hours and exceptions
Working hours are defined per day using start and end times. The following example configures the project to have working hours from 9:00 AM to 5:00 PM with a lunch break from 12:00 PM to 1:00 PM. Calendar exceptions allow overriding working hours for specific dates, enabling custom scheduling for special working days or non-working days that don’t fit the standard holiday definition:
@(Html.EJS().Gantt("Gantt")
.DataSource((IEnumerable<object>)ViewBag.DataSource)
.Height("450px")
.ProjectStartDate("04/01/2019")
.ProjectEndDate("04/30/2019")
.TaskFields(task => task
.Id("TaskId")
.Name("TaskName")
.StartDate("StartDate")
.Duration("Duration")
.ParentID("ParentId"))
.LabelSettings(label => label.LeftLabel("TaskName"))
.CalendarSettings(calendar => calendar.ProjectCalendar(project =>
project
.WorkingTime(new List<object>
{
new { from = 9, to = 12 },
new { from = 13, to = 17 }
})
.Exceptions(new List<object>
{
new
{
from = new DateTime(2026, 4, 6),
to = new DateTime(2026, 4, 6),
name = "Extended Working Day",
isWorking = true,
workingTime = new List<object>
{
new { from = 8, to = 18 }
}
}
})))
.Render())using System;
using System.Collections.Generic;
using System.Web.Mvc;
namespace MVCSamples.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.DataSource = new List<TaskData>()
{
new TaskData
{
TaskId = 1,
TaskName = "Project Planning",
StartDate = new DateTime(2026, 4, 2),
Duration = 3
},
new TaskData
{
TaskId = 2,
TaskName = "Requirements Analysis",
StartDate = new DateTime(2026, 4, 5),
Duration = 2,
ParentId = 1
},
new TaskData
{
TaskId = 3,
TaskName = "Design",
StartDate = new DateTime(2026, 4, 7),
Duration = 4,
ParentId = 1
},
new TaskData
{
TaskId = 4,
TaskName = "Development",
StartDate = new DateTime(2026, 4, 11),
Duration = 5
},
new TaskData
{
TaskId = 5,
TaskName = "Testing",
StartDate = new DateTime(2026, 4, 16),
Duration = 3
}
};
return View();
}
}
public class TaskData
{
public int TaskId { get; set; }
public string TaskName { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public int? Duration { get; set; }
public int? ParentId { get; set; }
}
}Define project holidays
Holidays are non-working dates that exclude time from task calculations. The following example defines holidays for April 10 and April 17, excluding these dates from task scheduling calculations:
@Html.EJS().Gantt("Gantt")
.DataSource((IEnumerable<object>)ViewBag.DataSource)
.Height("550px")
.TaskFields(ts => ts
.Id("TaskId")
.Name("TaskName")
.StartDate("StartDate")
.EndDate("EndDate")
.Duration("Duration")
.Progress("Progress")
.Dependency("Predecessor")
.ParentId("ParentId"))
.Columns(col =>
{
col.Field("TaskId").Add();
col.Field("TaskName").HeaderText("Name").Width(250).Add();
col.Field("StartDate").Add();
col.Field("Duration").Add();
})
.CalendarSettings(cal => cal
.ProjectCalendar(pc => pc
.Holidays(hol =>
{
hol.From(new DateTime(2026, 4, 10)).To(new DateTime(2026, 4, 10)).Add();
hol.From(new DateTime(2026, 4, 17)).To(new DateTime(2026, 4, 17)).Add();
})))
.Render()public IActionResult Index()
{
ViewBag.DataSource = GanttData.ProjectNewData();
return View();
}Task calendars
Task calendars enable specific tasks to use custom working days and holidays instead of the project calendar. This is useful for managing work across different shifts, regions, or external teams with different availability.
Assign task-specific calendars with exceptions
To assign a custom calendar to a task, first define the calendar in CalendarSettings.TaskCalendar, then reference it using the CalendarId property in the task data. Calendar exceptions allow defining specific dates with custom working days, enabling team-specific scheduling adjustments such as split shifts or holidays that differ from the main schedule.
When a task is assigned a calendar through CalendarId, that task follows only the assigned task calendar. The assigned task calendar overrides the project calendar for that task. Working days, holidays, and calendar exceptions defined in the assigned calendar are used when calculating the task schedule and working duration. Other task calendars are not considered when scheduling that task.
The following example defines two task calendars with different working days, task-specific exceptions, and assigns them to specific tasks:
@using Syncfusion.EJ2.Gantt
@(Html.EJS().Gantt("Gantt")
.DataSource((IEnumerable<object>)ViewBag.DataSource)
.Height("450px")
.ProjectStartDate("04/01/2019")
.ProjectEndDate("04/30/2019")
.TaskFields(ts => ts
.Id("TaskId")
.Name("TaskName")
.StartDate("StartDate")
.Duration("Duration")
.CalendarId("CalendarId"))
.LabelSettings(ls => ls.LeftLabel("TaskName"))
.CalendarSettings(cs => cs
.ProjectCalendar(pc => pc.WorkingTime(new List<object>
{
new { from = 9, to = 17 }
}))
.TaskCalendars(new List<object>
{
new
{
calendarId = "day-shift",
workingTime = new[]
{
new { from = 9, to = 17 }
},
holidays = new object[] { },
exceptions = new[]
{
new
{
from = new DateTime(2026, 4, 9),
to = new DateTime(2026, 4, 9),
label = "Team Meeting Day"
}
}
},
new
{
calendarId = "night-shift",
workingTime = new[]
{
new { from = 17, to = 9 }
},
holidays = new object[] { },
exceptions = new[]
{
new
{
from = new DateTime(2026, 4, 10),
to = new DateTime(2026, 4, 10),
name = "Maintenance Window",
isWorking = true,
workingTime = new[]
{
new { from = 18, to = 8 }
}
}
}
}
}))
.Render())public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.DataSource = GetTaskCollection();
return View();
}
public static List<GanttDataSource> GetTaskCollection()
{
return new List<GanttDataSource>()
{
new GanttDataSource
{
TaskId = 1,
TaskName = "Development Team Work",
StartDate = new DateTime(2026, 4, 2),
Duration = 5,
CalendarId = "day-shift"
},
new GanttDataSource
{
TaskId = 2,
TaskName = "Night Shift Support",
StartDate = new DateTime(2026, 4, 2),
Duration = 5,
CalendarId = "night-shift"
},
new GanttDataSource
{
TaskId = 3,
TaskName = "Standard Hours",
StartDate = new DateTime(2026, 4, 2),
Duration = 5
}
};
}
public class GanttDataSource
{
public int TaskId { get; set; }
public string TaskName { get; set; }
public DateTime? StartDate { get; set; }
public int? Duration { get; set; }
public string CalendarId { get; set; }
}
}Define task calendar holidays
Task calendars can include holidays that override project calendar holidays for the assigned task. These holidays are considered when calculating the task schedule and working duration. The following example configures a task calendar with specific holidays:
@using Syncfusion.EJ2.Gantt
@(Html.EJS().Gantt("Gantt")
.DataSource((IEnumerable<object>)ViewBag.DataSource)
.Height("450px")
.ProjectStartDate("04/01/2019")
.ProjectEndDate("04/30/2019")
.TaskFields(ts => ts
.Id("TaskId")
.Name("TaskName")
.StartDate("StartDate")
.Duration("Duration")
.CalendarId("CalendarId"))
.LabelSettings(ls => ls.LeftLabel("TaskName"))
.CalendarSettings(cs => cs
.ProjectCalendar(pc => pc
.WorkingTime(new List<object>
{
new { from = 9, to = 17 }
})
.Holidays(new List<object>
{
new
{
from = new DateTime(2019, 4, 10),
to = new DateTime(2019, 4, 10),
label = "Regional Holiday"
}
}))
.TaskCalendars(new List<object>
{
new
{
calendarId = "local-team",
holidays = new[]
{
new
{
from = new DateTime(2019, 4, 5),
to = new DateTime(2019, 4, 5),
label = "Local Holiday"
}
}
},
new
{
calendarId = "offshore-team",
holidays = new[]
{
new
{
from = new DateTime(2019, 4, 8),
to = new DateTime(2019, 4, 8),
label = "Offshore Holiday"
}
}
}
}))
.Render())public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.DataSource = GetTaskCollection();
return View();
}
public static List<GanttDataSource> GetTaskCollection()
{
return new List<GanttDataSource>()
{
new GanttDataSource
{
TaskId = 1,
TaskName = "Local Team Work",
StartDate = new DateTime(2026, 4, 2),
Duration = 5,
CalendarId = "local-team"
},
new GanttDataSource
{
TaskId = 2,
TaskName = "Offshore Team Work",
StartDate = new DateTime(2026, 4, 2),
Duration = 5,
CalendarId = "offshore-team"
}
};
}
public class GanttDataSource
{
public int TaskId { get; set; }
public string TaskName { get; set; }
public DateTime? StartDate { get; set; }
public int? Duration { get; set; }
public string CalendarId { get; set; }
}
}Configure hours per day for task durations
The HoursPerDay property defines the number of hours used to represent one day when calculating task durations. Changing HoursPerDay recalculates day-based duration values using the existing working duration of the task. This affects how duration is displayed and calculated in days, but does not modify the task’s start date, end date, or underlying working duration.
For example, a task with 32 hours of working duration is displayed as 4 days when HoursPerDay is set to 8. If HoursPerDay is changed to 16, the same task is displayed as 2 days. The task schedule remains unchanged because the underlying working duration is not modified.
The following example demonstrates how changing HoursPerDay affects duration calculations.
@using Syncfusion.EJ2.Gantt
@using Syncfusion.EJ2.Buttons
@(Html.EJS().Button("updateHoursPerDay")
.Content("Update Hours Per Day")
.Render())
@(Html.EJS().Gantt("Gantt")
.DataSource((IEnumerable<object>)ViewBag.DataSource)
.Height("450px")
.HoursPerDay(8)
.ProjectStartDate("04/01/2026")
.ProjectEndDate("04/30/2026")
.TaskFields(ts => ts
.Id("TaskId")
.Name("TaskName")
.StartDate("StartDate")
.Duration("Duration")
.ParentID("ParentId"))
.LabelSettings(ls => ls.LeftLabel("TaskName"))
.CalendarSettings(new
{
projectCalendar = new
{
workingTime = new object[]
{
new { from = 9, to = 12 },
new { from = 13, to = 17 }
},
exceptions = new object[]
{
new
{
from = new DateTime(2026, 4, 6),
to = new DateTime(2026, 4, 6),
label = "Extended Working Day"
}
}
}
})
.Render())
<script>
document.getElementById('updateHoursPerDay').addEventListener('click', function () {
var gantt = document.getElementById('Gantt').ej2_instances[0];
gantt.hoursPerDay = 16;
});
</script>public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.DataSource = GetTaskCollection();
return View();
}
public static List<GanttDataSource> GetTaskCollection()
{
return new List<GanttDataSource>()
{
new GanttDataSource
{
TaskId = 1,
TaskName = "Project Planning",
StartDate = new DateTime(2026, 4, 2),
Duration = 3
},
new GanttDataSource
{
TaskId = 2,
TaskName = "Requirements Analysis",
StartDate = new DateTime(2026, 4, 5),
Duration = 2,
ParentId = 1
},
new GanttDataSource
{
TaskId = 3,
TaskName = "Design",
StartDate = new DateTime(2026, 4, 7),
Duration = 4,
ParentId = 1
},
new GanttDataSource
{
TaskId = 4,
TaskName = "Development",
StartDate = new DateTime(2026, 4, 11),
Duration = 5
},
new GanttDataSource
{
TaskId = 5,
TaskName = "Testing",
StartDate = new DateTime(2026, 4, 16),
Duration = 3
}
};
}
public class GanttDataSource
{
public int TaskId { get; set; }
public string TaskName { get; set; }
public DateTime? StartDate { get; set; }
public int? Duration { get; set; }
public int? ParentId { get; set; }
}
}Note: The default
hoursPerDayvalue is 8 hours. When a task has 4 days duration with thehoursPerDayvalue of 6, the total working hours = 4 days × 6 hours = 24 hours. If the calendar’s working time is configured as 24 hours (0:00 to 24:00), these 24 hours fit within a single calendar day, so the task displays as 1 calendar day on the chart, even though the duration specification is 4 days.
Impact on task scheduling
Calendar settings directly affect how task duration is calculated and when tasks are scheduled:
- Working hours: Task durations ignore non-working hours. A 2-day task completed during 9 AM-5 PM working hours uses the same elapsed time as a 2-day task across multiple days with shorter working hours
- Holidays: Tasks skip over holiday dates, extending the end date accordingly to maintain the required working duration
-
Weekends: By default, weekends are treated as non-working days when
IncludeWeekendis set to false - Task dependencies: Dependency calculations use the predecessor task’s calendar to determine when the successor task can start
- Task calendars: Tasks without an assigned task calendar follow the project calendar. Tasks with an assigned task calendar use the working hours, holidays, and exceptions defined in that calendar for scheduling and duration calculations.
-
Duration calculations: Changing
HoursPerDayrecalculates day-based duration values without changing the scheduled start and end dates.