joniles/mpxj

getDate Infinite Loop

caliworks opened this issue · 2 comments

I'm getting an infinite loop in the ProjectCalendar.getDate method.

In helper getDateFromNegativeDuration (or getDateFromPositiveDuration), the variable currentDateWorkingMilliseconds is always zero when the date working hours ends at midnight. When cal variable is set with LocalTimeHelper.setTime, it uses .getFinishTime to set the end of the working day. However, if the end of the working day is midnight, then finish time is set for 00:00, which effectively becomes the beginning of the work day. So when currentDateWorkingMilliseconds is recalculated, it is zero, because currentDateStart is now the same as cal.

I have a project calendar that is all night shifts (12AM to 4:30AM, 8:30AM to Midnight), 7 days a week. So the loop gets stuck because there is never a date that has a positive value for currentDateWorkingMilliseconds. The cal date just keeps going down forever.

private LocalDateTime getDateFromNegativeDuration(LocalDateTime startDate, Duration duration) {
    ProjectProperties properties = this.getParentFile().getProjectProperties();
    long remainingMilliseconds = -Math.round(NumberHelper.round(duration.convertUnits(TimeUnit.MINUTES, properties).getDuration(), 2.0) * 60000.0);
    LocalDateTime cal = startDate;

    while(true) {
        while(remainingMilliseconds > 0L) {
            LocalDateTime currentDateStart = LocalDateTimeHelper.getDayStartDate(cal);
            long currentDateWorkingMilliseconds = Math.round(this.getWork(currentDateStart, cal, TimeUnit.MINUTES).getDuration() * 60000.0);
            if (remainingMilliseconds > currentDateWorkingMilliseconds) {
                remainingMilliseconds -= currentDateWorkingMilliseconds;
                int nonWorkingDayCount = 0;

                DayOfWeek day;
                do {
                    cal = cal.minusDays(1L);
                    day = cal.getDayOfWeek();
                    ++nonWorkingDayCount;
                    if (nonWorkingDayCount > 1000) {
                        cal = startDate.plusDays(1L);
                        remainingMilliseconds = 0L;
                        break;
                    }
                } while(!this.isWorkingDate(LocalDateHelper.getLocalDate(cal), day));

                cal = LocalTimeHelper.setTime(cal, this.getFinishTime(LocalDateHelper.getLocalDate(cal)));

Hi, thanks for opening the issue. I believe I have fixed the problem, the changes have been merged and will be part of the next release.

awesome thanks joniles!!