diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/core/timer/BusinessCalendarImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/core/timer/BusinessCalendarImpl.java index fbb650e3c35..b22f48cbb35 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/core/timer/BusinessCalendarImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/core/timer/BusinessCalendarImpl.java @@ -193,7 +193,9 @@ public long calculateBusinessTimeAsDuration(String timeExpression) { Date calculatedDate = calculateBusinessTimeAsDate(timeExpression); - return (calculatedDate.getTime() - getCurrentTime()); + long calculatedDurationInMs = (calculatedDate.getTime() - getCurrentTime()); + logger.debug("calculateBusinessTimeAsDuration for expression {} returns {} seconds", timeExpression, (calculatedDurationInMs / 1000)); + return calculatedDurationInMs; } public Date calculateBusinessTimeAsDate(String timeExpression) { @@ -251,7 +253,9 @@ public Date calculateBusinessTimeAsDate(String timeExpression) { c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); } else if (currentCalHour < startHour) { - c.add(Calendar.HOUR_OF_DAY, startHour); + c.add(Calendar.HOUR_OF_DAY, startHour - currentCalHour); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); } // calculate remaining hours @@ -267,7 +271,9 @@ public Date calculateBusinessTimeAsDate(String timeExpression) { c.set(Calendar.HOUR_OF_DAY, startHour); c.add(Calendar.HOUR_OF_DAY, currentCalHour - endHour); } else if (currentCalHour < startHour) { - c.add(Calendar.HOUR_OF_DAY, startHour); + c.add(Calendar.HOUR_OF_DAY, startHour - currentCalHour); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); } // calculate minutes @@ -293,7 +299,9 @@ public Date calculateBusinessTimeAsDate(String timeExpression) { c.set(Calendar.HOUR_OF_DAY, startHour); c.add(Calendar.HOUR_OF_DAY, currentCalHour - endHour); } else if (currentCalHour < startHour) { - c.add(Calendar.HOUR_OF_DAY, startHour); + c.add(Calendar.HOUR_OF_DAY, startHour - currentCalHour); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); } // take under consideration weekend handleWeekend(c, false); diff --git a/jbpm/jbpm-flow/src/test/java/org/jbpm/process/core/timer/BusinessCalendarImplTest.java b/jbpm/jbpm-flow/src/test/java/org/jbpm/process/core/timer/BusinessCalendarImplTest.java index 3d398d753d1..40ad261bddf 100755 --- a/jbpm/jbpm-flow/src/test/java/org/jbpm/process/core/timer/BusinessCalendarImplTest.java +++ b/jbpm/jbpm-flow/src/test/java/org/jbpm/process/core/timer/BusinessCalendarImplTest.java @@ -368,6 +368,78 @@ public void testCalculateMinutesPassingWeekend() { assertThat(formatDate("yyyy-MM-dd HH:mm:ss", result)).isEqualTo(expectedDate); } + @Test + public void testCalculateMinutesBeforeStartHour() { + Properties config = new Properties(); + config.setProperty(BusinessCalendarImpl.HOURS_PER_DAY, "4"); + config.setProperty(BusinessCalendarImpl.START_HOUR, "14"); + config.setProperty(BusinessCalendarImpl.END_HOUR, "18"); + String currentDate = "2024-11-28 10:48:33.000"; + String duration = "10m"; + String expectedDate = "2024-11-28 14:10:00"; + + SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTimeAndMillis(currentDate).getTime()); + BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); + + Date result = businessCal.calculateBusinessTimeAsDate(duration); + + assertThat(formatDate("yyyy-MM-dd HH:mm:ss", result)).isEqualTo(expectedDate); + } + + @Test + public void testCalculateSecondsBeforeStartHour() { + Properties config = new Properties(); + config.setProperty(BusinessCalendarImpl.HOURS_PER_DAY, "4"); + config.setProperty(BusinessCalendarImpl.START_HOUR, "14"); + config.setProperty(BusinessCalendarImpl.END_HOUR, "18"); + String currentDate = "2024-11-28 10:48:33.000"; + String duration = "10s"; + String expectedDate = "2024-11-28 14:00:10"; + + SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTimeAndMillis(currentDate).getTime()); + BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); + + Date result = businessCal.calculateBusinessTimeAsDate(duration); + + assertThat(formatDate("yyyy-MM-dd HH:mm:ss", result)).isEqualTo(expectedDate); + } + + @Test + public void testCalculateMinutesBeforeEndHour() { + Properties config = new Properties(); + config.setProperty(BusinessCalendarImpl.HOURS_PER_DAY, "4"); + config.setProperty(BusinessCalendarImpl.START_HOUR, "14"); + config.setProperty(BusinessCalendarImpl.END_HOUR, "18"); + String currentDate = "2024-11-28 17:58:33.000"; + String duration = "10m"; + String expectedDate = "2024-11-29 14:08:33"; + + SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTimeAndMillis(currentDate).getTime()); + BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); + + Date result = businessCal.calculateBusinessTimeAsDate(duration); + + assertThat(formatDate("yyyy-MM-dd HH:mm:ss", result)).isEqualTo(expectedDate); + } + + @Test + public void testCalculateSecondsBeforeEndHour() { + Properties config = new Properties(); + config.setProperty(BusinessCalendarImpl.HOURS_PER_DAY, "4"); + config.setProperty(BusinessCalendarImpl.START_HOUR, "14"); + config.setProperty(BusinessCalendarImpl.END_HOUR, "18"); + String currentDate = "2024-11-28 17:59:33.000"; + String duration = "50s"; + String expectedDate = "2024-11-29 14:00:23"; + + SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTimeAndMillis(currentDate).getTime()); + BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); + + Date result = businessCal.calculateBusinessTimeAsDate(duration); + + assertThat(formatDate("yyyy-MM-dd HH:mm:ss", result)).isEqualTo(expectedDate); + } + private Date parseToDate(String dateString) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");