Programatically change date of task doesn't ignore weekends (Gantt multiple drag and drop)

I am changing the date of a task programatically like so

selectedTask.start_date = this.gantt.date.add(selectedTask.start_date, 1, 'day');

THe problem is it doesn’t ignore weekend. If it’s Friday it moves to Saturday.

I have used this config

gantt.config.work_time = true;  // removes non-working time from calculations 
gantt.config.skip_off_time = true;    // hides non-working time in the chart

but it does not remove the work time from calculations.

I’m using the latest pro version.

Here is a sample.

http://docs.dhtmlx.com/gantt/snippet/11d22976

In the sample move task 2 until task 1 hits the weekend.
When I set task 1 to either Monday or Friday if it lands on the weekend, the slack time between tasks is increased. This is not what I want. I’m programatically moving it like this because the requirements don’t allow me to have links and allow the default multi-drag duration functionality.

Here is my full implementation of gantt multiple drag and drop.

class GanttDragAndDrop {
    constructor() {
        this.PermissionUtils = new PermissionUtils();
        this.taskManager = new TaskManager();
        this.gantt = null;
        this.context = null;
        this.selectedTasks = [];
        this.originalDraggedTask = null;
        this.isDragging = false;
    }

    init(_context, _gantt) {
        this.context = _context;
        this.gantt = _gantt;

        this.onRowDragStart();
        this.onBeforeRowDragEnd();
        this.onBeforeTaskDrag();
        this.onTaskDrag();
        this.onAfterTaskDrag();
        this.onBeforeTaskMove();
        this.onRowDragEnd();
    }

    onBeforeRowDragEnd() {
        this.gantt.attachEvent("onBeforeRowDragEnd", function (id, mode, e) {
            let task = this.gantt.getTask(id);

            if (!this.PermissionUtils.hasPermission(this.PermissionUtils.ganttEditPermision))
                return false;
            if (task.type === this.gantt.config.types.productline || task.type === this.gantt.config.types.program)
                return false;
            return true;
        }.bind(this));
    }

    onRowDragStart() {
        gantt.attachEvent("onRowDragStart", function (id, target, e) {
            //any custom logic here
            return true;
        }.bind(this));
    }

    onBeforeTaskDrag() {
        this.gantt.attachEvent("onBeforeTaskDrag", function (id, mode, e) {

            if (!this.gantt.isSelectedTask(id))
                return false;

            if (!this.PermissionUtils.UserIsAffiliate())
                return false;

            let t = gantt.getTask(id);
            this.originalDraggedTask = {
                startDate: t.start_date,
                endDate: t.end_date,
                id: t.id,
                activityId: t.activityId
            }

            let tasks = this.gantt.getSelectedTasks();

            for (let i = 0; i < tasks.length; i++) {
                let task = gantt.getTask(tasks[i]);

                if (this.selectedTasks.findIndex(x => x.id.toString() === tasks[i]) === -1)
                    this.selectedTasks.push({
                        startDate: task.start_date,
                        endDate: task.end_date,
                        id: task.id,
                        activityId: task.activityId
                    });
            }


            return true;
        }.bind(this));
    }

    onTaskDrag() {
        this.gantt.attachEvent("onTaskDrag", function (id, mode, task, original) {
            if (!this.PermissionUtils.hasPermission(this.PermissionUtils.ganttEditPermision))
                return false;

            return true;
        }.bind(this));
    }

    onAfterTaskDrag() {
        this.gantt.attachEvent("onAfterTaskDrag", function (id, mode, e) {

            let task = gantt.getTask(id);

            let dragged_task = gantt.getTask(id);
            var modes = this.gantt.config.drag_mode;
            if (mode === modes.resize) {
                task.start_date = task.start_date;
                task.end_date = task.end_date;

                if (task.type === gantt.config.types.task && (task.start_date.getTime() >= task.end_date.getTime()))
                    task.end_date = this.gantt.date.add(task.start_date, 1, 'day');

            }

            if (mode === modes.move) {
                //difference in minutes
                let unit = 'minute';
                var diff = Math.round(Math.abs((dragged_task.start_date - this.originalDraggedTask.startDate) / 1000 / 60));
                if (task.start_date < this.originalDraggedTask.startDate)
                    diff = diff * -1;
                if (diff !== 0) {

                    for (let i = 0; i < this.selectedTasks.length; i++) {

                        if (this.selectedTasks[i].id.toString() !== id) {

                            let selectedTask = gantt.getTask(this.selectedTasks[i].id);
                            var oldDuration = gantt.calculateDuration(this.selectedTasks[i].startDate, this.selectedTasks[i].endDate);

                            selectedTask.start_date = this.gantt.date.add(selectedTask.start_date, diff, unit);

                            if (selectedTask.start_date.getDay() === 6) //saturday
                                selectedTask.start_date = this.gantt.date.add(selectedTask.start_date, 2, 'day');
                            else if (selectedTask.start_date.getDay() === 0) //sunday
                                selectedTask.start_date = this.gantt.date.add(selectedTask.start_date, 1, 'day');

                            selectedTask.end_date = this.gantt.calculateEndDate(selectedTask.start_date, oldDuration);
                            var newDuration = gantt.calculateDuration(selectedTask.start_date, selectedTask.end_date);

                            /////////////////////////////////////////////////////////
                            // be careful about how the gantt calculates the end date
                            // sometimes it's off by 1
                            //////////////////////////////////////////////////////////
                            while ((oldDuration < newDuration)) {
                                selectedTask.end_date = this.gantt.date.add(selectedTask.end_date, -1, 'day');
                                newDuration = gantt.calculateDuration(selectedTask.start_date, selectedTask.end_date);
                            }

                            while ((oldDuration > newDuration)) {
                                selectedTask.end_date = this.gantt.date.add(selectedTask.end_date, 1, 'day');
                                newDuration = gantt.calculateDuration(selectedTask.start_date, selectedTask.end_date);
                            }

                        }

                    }

                }
            }
            this.selectedTasks = [];
            let activities = [];
            var tasks = this.gantt.getSelectedTasks();

            for (let i = 0; i < tasks.length; i++) {
                let t = gantt.getTask(tasks[i]);

                if (t.end_date.getTime() < t.start_date.getTime())
                    t.end_date = t.start_date;
                
                t.end_date.setHours(0);
                activities.push(this.taskManager.createActivityDto(t));
            }

            this.context.setPvAStyles();

            gantt.refreshData();

            if (activities.length > 0 && !this.isDragging) {
                this.isDragging = true;
                Ajax.ajaxRequest(null, "/Activity/UpdateActivityBatch", activities, null, null, null, this.updateAfterDrag.bind(this));
            }

        }.bind(this));
    }

    updateAfterDrag() {
        this.isDragging = false;
        //this.gantt.render()
    }

    weekendDuration(myDate) {
        if (myDate.getDay() === 6)
            return 1
        else if (myDate.getDay() === 0)
            return 2;
        else 0;
    }

    onBeforeTaskMove() {
        gantt.attachEvent("onBeforeTaskMove", this.moveTask.bind(this));
    }

    moveTask(id, parent) {

        var task = this.gantt.getTask(id);
        let p = this.gantt.getTask(parent);

        //if (p.type === this.gantt.config.types.milestone || p.type === this.gantt.config.types.task) {
        //    if ((task.parent !== p.parent))
        //        return false;
        //}

        if (task.parent !== parent)
            return false;

        return true;



        //drag and drop anywhere

        //var parentTask = gantt.getTask(parent);
        //var task = gantt.getTask(id);
        //if (task.parent !== parent) {
        //    if (parentTask.type === gantt.config.types.subproject && (task.type === gantt.config.types.task || task.type === gantt.config.types.milestone)) {

        //        if (parentTask.subProjectId === null) {

        //            if (this.showErrorMessage) {
        //                gantt.message({ type: "error", text: "You must save before dragging this task to a newly created Sub Project.", expire: 4000 });
        //                this.showErrorMessage = false;
        //            }
        //            return false;
        //        }
        //        task.parent = parent;
        //        task.projectId = parentTask.projectId;
        //        task.subProjectId = parentTask.subProjectId;

        //        if (parentTask.type === gantt.config.types.subproject)
        //            task.parentId = parentTask.subProjectId;
        //    }
        //    else if ((task.type === gantt.config.types.subproject) && (parentTask.type === gantt.config.types.subproject || parentTask.type === gantt.config.types.project)) {
        //        if (parentTask.subProjectId === null || parentTask.projectId === null) {

        //            if (this.showErrorMessage) {
        //                gantt.message({ type: "error", text: "You must save before dragging this Sub Project to a newly created Project or SubProject.", expire: 4000 });
        //                 this.showErrorMessage = false;
        //            }
        //            return false;
        //        }

        //        task.projectId = parentTask.projectId;
        //        task.parent = parent;

        //        if (parentTask.type === gantt.config.types.project) {
        //            task.parentId = null;
        //        }
        //    }
        //    else
        //        return false;
        //}

        //gantt.updateTask(id);
        //return true;
    }

    onRowDragEnd() {
        this.gantt.attachEvent("onRowDragEnd", function (id, target) {
            this.context.setSortOrder(id);
            this.context.showErrorMessage = true;
        }.bind(this));
    }


}

Hello,
We are aware of the issue with the wrong total slack and free slack calculations. It will be fixed in future versions.

gantt.date.add method doesn’t consider the work time option, it is by design.
Instead of it, you can use gantt.calculateEndDate() method:
https://docs.dhtmlx.com/gantt/api__gantt_calculateenddate.html
For example:

gantt.calculateEndDate(task.start_date, 1);

Here is the updated snippet:
http://docs.dhtmlx.com/gantt/snippet/aa5f25ec

Thank you. I’ve come up with a solution to fix the slack by adding or subtracting weekend days based on if the drag is left or right.

For example here is a watered down version

task1 starts on Friday
task2 starts on Monday

task1 drags to Monday (3 day duration)

task2 programatically pushes to (Wednesday)

if(task1 is dragged over the weekend) 
   task2.start_date = task2.start_date - weekend Days

Basically I am doing that with multiple scenarios