Set custom start/end time

Hi my values in the server have no time, but I’m wanting to visually render the tasks as starting at 9am and finishing at 5pm. When I do this from the dataset it’s fine, but as soon as I start dragging or editing the data it obviously loses this. Is there a way I can lock it so it visually always displays the start date at 8am and the end date as 5pm instead of 00:00:00? What’s the best approach?

As an alternative to this - I wouldn’t mind the default settings, but instead of having the time for the end date set to 00:00:00 is there a way for it to display as 23:59:59?

As it currently stands it looks like the task goes up to a date and doesn’t include it and that’s the primary issue my users are facing.

Hello,
You can set the start and end hours for tasks when they are loaded into Gantt using the onTaskLoading handler:

const startHour = 9;

gantt.attachEvent("onTaskLoading", function(task) {
    task.start_date = gantt.date.add(task.start_date, startHour, 'hour');
    task.end_date = gantt.calculateEndDate({start_date: task.start_date, duration: task.duration, task:task});

    return true;
});

You will also need to update the start and end hours when dragging the task using the onTaskDrag and onAfterTaskDrag handlers:

let newTaskStart = null;

gantt.attachEvent("onTaskDrag", function(id, mode, task, original) {
    const taskStart = task.start_date;
    newTaskStart = +taskStart - taskStart.getHours()*60*60*1000 - taskStart.getMinutes()*60*1000 - taskStart.getSeconds()*1000;
});

gantt.attachEvent("onAfterTaskDrag", function(id, mode, e) {
    const task = gantt.getTask(id);
    task.start_date = gantt.date.add(newTaskStart, startHour, 'hour');
    task.end_date = gantt.calculateEndDate({start_date: task.start_date, duration: task.duration, task:task});
    gantt.updateTask(id);
});

My test data looks like this:

const tasks = {
    data: [
        { id: 1, text: "Task #1",   start_date: "03-03-2023", duration: 8, open: true, type: "project" },
        { id: 2, text: "Task #1.1", start_date: "03-03-2023", duration: 8, parent: "1" },
        { id: 3, text: "Task #1.2", start_date: "04-03-2023", duration: 8, parent: "1" },
        { id: 4, text: "Task #1.3", start_date: "05-03-2023", duration: 8, parent: "1" }
    ],
    links: [
        { id: "23", source: "2", target: "3", type: "0" },
        { id: "34", source: "3", target: "4", type: "0" }
    ]
};

gantt.parse(tasks);

Please see an example: https://snippet.dhtmlx.com/p28leu8j. This is not a complete example, it only works when dragging the task and doesn’t work when resizing it. But based on it, you can modify it to suit your needs.

Also, when using a date with hour precision, you must set duration_unit = "hour".

Thanks mate - what about autoscheduling? It seems to set the tasks really out of whack.

Hello,

Since this functionality is not originally provided by Gantt, it may not work as you expect. To make it work with autoscheduling you can try the following:

Setting start and end hours for tasks as in the previous example:

const startHour = 9;

gantt.attachEvent("onTaskLoading", (task) => {
    task.start_date = gantt.date.add(task.start_date, startHour, 'hour');
    task.end_date = gantt.calculateEndDate({
        start_date: task.start_date,
        duration: task.duration,
        task:task
    });

    return true;
});

Then you need to set working time “9:00-17:00” using setWorkTime method:

gantt.config.work_time = true;
gantt.setWorkTime({ hours:["9:00-17:00"] });

Then, using the onBeforeTaskChanged and onBeforeTaskAutoSchedule handlers, cancel changes for the task, as well as autoschedule if the task start date falls on non-working hours:

let autoSchedule = true;

gantt.attachEvent("onBeforeTaskChanged", (id, mode, task) => {
    const changedTask = gantt.getTask(id);

    if (!gantt.isWorkTime(changedTask.start_date)) {
        autoSchedule = false;

        return false;
    }

    autoSchedule = true;

    return true;
});

gantt.attachEvent("onBeforeTaskAutoSchedule", (task, start, link, predecessor) => {
    if (autoSchedule) {
        return true;
    }

    return false;
});

Update the start and end hours when dragging the task, as in the previous example:

gantt.attachEvent("onAfterTaskDrag", (id, mode, e) => {
    const task = gantt.getTask(id);
    task.start_date = gantt.date.add(gantt.date.day_start(task.start_date), startHour, 'hour');
    task.end_date = gantt.calculateEndDate({
        start_date: task.start_date,
        duration: task.duration,
        task: task
    });
    gantt.updateTask(id);
});

And at the end, using the onAfterTaskAutoSchedule handler, you need to adjust the start time of the task if it exceeds 9:00:

gantt.attachEvent("onAfterTaskAutoSchedule", (task, start, link, predecessor) => {
    if (start.getHours() > startHour) {
        const successorTaskStartDay = gantt.date.day_start(start);  
        task.start_date = gantt.date.add(successorTaskStartDay, startHour, 'hour');
        task.end_date = gantt.calculateEndDate({start_date: task.start_date, duration: task.duration, task:task});
        gantt.updateTask(task.id);
    }
});

Styles for non-working hours can be set using the timeline_cell_class template:

gantt.templates.timeline_cell_class = (task, date) => {
    const css = [];

    if (date.getHours() == 8) {
        css.push("day_start");
    }
    if (date.getHours() == 16) {
        css.push("day_end");
    }
    if (!gantt.isWorkTime(date, 'day')) {
        css.push("week_end");
    } else if (!gantt.isWorkTime(date, 'hour')) {
        css.push("no_work_hour");
    }

    return css.join(" ");
};

Styles:

.gantt_task_cell.day_end, .gantt_task_cell.no_work_hour.day_start {
    border-right-color: #C7DFFF;
}

.gantt_task_cell.week_end.day_end, .gantt_task_cell.week_end.day_start {
    border-right-color: #E2E1E1;
}

.gantt_task_cell.week_end, .gantt_task_cell.no_work_hour {
    background-color: #F5F5F5;
}

.gantt_task_row.gantt_selected .gantt_task_cell.week_end {
    background-color: #F8EC9C;
}

Here is an example: https://snippet.dhtmlx.com/yh7efi0i. This is not a complete example, it only works when dragging the task and doesn’t work when resizing it. But based on it, you can modify it to suit your needs.
You can also contact the development department contact@dhtmlx.com if the proposed solution does not meet your expectations.