Hello,
Thank you for your patience while we investigated the duration calculation issue. You were on the right track with your implementation, and I’d like to clarify why the behavior occurred and how to resolve it properly.
Your initial approach is correct. However, the method used to subtract time had a problem:
const gridDateToStr = gantt.date.date_to_str("%D %d/%m/%Y");
gantt.templates.grid_date_format = (date, column) => {
if (column === "end_date") {
return gridDateToStr(new Date(date.valueOf() - 1)); // Subtracts 1 millisecond (not 1 day)
} else {
return gridDateToStr(date);
}
};
This code shifted the timestamp by 1 millisecond (not 1 day):
new Date(date.valueOf() - 1) // Subtracts 1 millisecond (not 1 day)
date.valueOf() returns a timestamp in milliseconds, from which we subtract 1 millisecond, which is why the day doesn’t roll back as we expect, and we get this: 3 April 16:00 → 3 April 15:59:59
instead of 3 April 16:00 → 2 April 16:00
.
To reliably subtract 1 day, use the built-in gantt.date.add() method:
gridDateToStr(gantt.date.add(date, -1, "day")); // Subtracts 1 full day
It ensures the subtraction accounts for 24 hours (not 1 ms).
Here’s a working example: DHTMLX Snippet Tool.
Option 2:
Or you can solve this issue using duration_unit + duration formatter. This approach avoids manual date math and gives you precise control over task durations.
- Configure storage unit (hours or minutes):
gantt.config.duration_unit = "hour";
gantt.config.duration_step = 1;
- Initialize the Duration Formatter:
const formatter = gantt.ext.formatters.durationFormatter({
enter: "day",
store: "hour",
format: "day",
short: true,
hoursPerDay: 8,
hoursPerWeek: 40,
});
This plugin allows you to manage how duration is stored and display it in units you need.
- Connect formatter to grid and lightbox. Since inline editing in Grid is enabled, you also need to add the
formatter
object to the durationEditor
object via the formatter attribute:
const durationEditor = {
type: "duration",
map_to: "duration",
formatter: formatter,
min: 0,
max: 100,
};
gantt.config.columns = [
{
name: "duration",
label: "Duration",
width: 100,
align: "center",
template: (task) => formatter.format(task.duration),
editor: durationEditor,
resize: true,
},
// ...
];
gantt.config.lightbox.sections = [
{ name: "description", map_to: "text", type: "textarea", height: 70 },
{ name: "time", map_to: "auto", type: "duration", formatter },
];
By default, both MS Project and dhtmlxGantt assume these working hours:
- 8:00–12:00, 13:00–17:00 → total 8 hours per day
So:
- If a user sets 8:00–16:00, that only includes 7 working hours (8:00–12:00, 13:00–16:00). To get a full 8 hours, the end time must be 17:00, not 16:00.
Please see how it can be implemented: DHTMLX Snippet Tool.
Thank you for reporting this issue. Let us know if this helps or if you need further assistance.
Best regards,
Valeria Ivashkevich
Support Engineer