TTMSFNCGanttChart 1.3.3.7: work-day boundary compensation still incomplete

Component: tms.fnc.ganttchart 1.3.3.7 · Delphi 13.1 Florence, VCL, Win64

Thank you for the quick turnaround on 1.3.3.7. We have retested all four items. GetActualStartDateTimeByEnd no longer returns non-working days, the dependency recalculation works as described, and the sign error is gone.

Two observations remain, both about the 23:59:59 work-day boundary.


1. The compensation in GetActualStartDateTimeByEnd stops after the first iteration

Configuration: whWorkDaysOnly, working days Mon–Fri, no holidays in the tested range.

The new compensation reads:

tempTl := GetWorkTimeDifference(psd, tempD, AWorkTimePolicy);
if (Frac(tempD) = 0) and not IsWorkOrNotHoliday(IncSecond(tempD, -1)) then
  tempTl := IncSecond(tempTl);

It requires Frac(tempD) = 0. At the end of the same loop, tempD is reassigned:

tempD := GetPreviousWorkEndDateTime(psd, AWorkTimePolicy);

which returns a 23:59:59 value. From the second iteration onwards Frac(tempD) <> 0, so the compensation never fires again and one second is lost per additional non-working stretch.

Measured, reference Monday 24.08.2026 00:00, calling GetActualStartDateTimeByEnd with n = 1…15 working days:

n result
1–5 00:00:00 (exact)
6–9 23:59:59
10–14 23:59:58
15 23:59:57

Feeding the result back into GetActualEndDateTime with the same duration no longer returns the original reference. In our round-trip test 6 of 30 cases fail to close — from 23:59:58 onwards the value normalises to a different working day, so it is no longer only a matter of notation.

With a reference of Wednesday the same drift occurs but happens to stay recoverable, which is why it is easy to miss.


2. The GetDurationBetweenDateTimes fix does not apply when working hours are configured

The new call is guarded by:

if (AWorkTimePolicy = whWorkDaysOnly) and (FWorkingHours.Count = 0) then
  Inc(sec, WorkDayBoundarySeconds(AFirstDateTime, ASecondDateTime));

Our project has a single WorkingHours entry spanning the full day (00:00:00.00123:59:59.999), so FWorkingHours.Count = 1 and FDaySpan = 86399.

However, GetNextEnd applies the 23:59:59 clamp for whWorkDaysOnly regardless of whether working hours are configured. The boundary — and the lost second — therefore still occurs in our configuration, while the compensation is skipped.

Measured, task starting Friday, resized by dragging the right edge:

action DurationType Value ToString
enlarge Fri → Tue gdtSeconds 259198 3d
shrink Tue → Fri gdtWorkDays 0.999988 23h 59m 59s

These are byte-identical to what we measured on 1.3.3.6, i.e. unchanged by the update. 0.999988 is 86398/86399, which reproduces only with FDaySpan = 86399.

Would it be possible to apply the compensation whenever AWorkTimePolicy = whWorkDaysOnly, independently of FWorkingHours.Count?


Both points are handled by workarounds on our side, so there is no urgency. We are reporting them mainly because the two fixes are so close to complete.

Thanks again for the fast response last time.

Thank you for letting me know.

I've analysed the issue, and it will be fixed in the next release of TMS FNC Gantt Chart.