将营业时间添加到Java DateTime

对于问题跟踪系统,我需要计算请求的响应时间。 响应时间的计时器应仅在工作时间运行。 我应该使用什么算法/库来完成这项任务? (当然,我知道Joda-Time或ObjectLab Kit,但找不到任何帮助我的任务。我错过了什么吗?)

例:

  • 营业时间:上午9点至下午5点(每天8小时)
  • 最长响应时间:16小时

该方法可能类似于:

DateTime calculateResponseTime(DateTime issueReportedAt) 

我将给出一些可能的输入和结果作为示例:

  • 星期一,2011-09-19,下午1:00 – >星期三,2011-09-21,下午1:00
  • 星期一,2011-09-19,6:05 pm – >星期四,2011-09-22,上午9:00
  • 星期五,2011-09-23,下午2:00 – >星期二,2011-09-27,下午2:00

您可以查看jBPM业务日历 。

另一个库允许您配置银行假期,但它没有营业时间的概念。

我认为Oleg的建议正在考虑jBPM实现此function的方式,以便为您自己的解决方案编写代码。 以下是我通过Google代码搜索从我发现的来源中大量借用的答案。

它没有考虑到假期,但我将把它作为锻炼给你。 我建议您使用网络服务每年更新限制日期列表吗? 祝你好运!

  int fromHour = 9; int fromMinute = 0; int toHour = 17; int toMinute = 0; long maxResponseTime = 16; Date calculateResponseTime(Date issueReportedAt, long responseHours) { Date end = null; Calendar responseTime = Calendar.getInstance(); responseTime.setTime(issueReportedAt); int hourOfDay = responseTime.get(Calendar.HOUR_OF_DAY); int dayOfWeek = responseTime.get(Calendar.DAY_OF_WEEK); if (hourOfDay < fromHour) { responseTime.set(Calendar.HOUR, fromHour); } if (hourOfDay >= toHour || dayOfWeek == 1) { responseTime.add(Calendar.DATE, 1); responseTime.set(Calendar.HOUR_OF_DAY, fromHour); responseTime.set(Calendar.MINUTE, fromMinute); } else if (dayOfWeek == 7) { responseTime.add(Calendar.DATE, 2); responseTime.set(Calendar.HOUR_OF_DAY, fromHour); responseTime.set(Calendar.MINUTE, fromMinute); } int hour = responseTime.get(Calendar.HOUR_OF_DAY); int minute = responseTime.get(Calendar.MINUTE); long dateMilliseconds = ((hour * 60) + minute) * 60 * 1000; long dayPartEndMilleseconds = ((toHour * 60) + toMinute) * 60 * 1000; long millisecondsInThisDayPart = dayPartEndMilleseconds - dateMilliseconds; long durationMilliseconds = responseHours * 60 * 60 * 1000; if (durationMilliseconds < millisecondsInThisDayPart) { end = new Date(responseTime.getTimeInMillis() + durationMilliseconds); } else { long remainder = (durationMilliseconds - millisecondsInThisDayPart) / 60 / 60 / 1000; Date dayPartEndDate = new Date(responseTime.getTimeInMillis() + durationMilliseconds); responseTime.setTime(dayPartEndDate); end = calculateResponseTime(responseTime.getTime(), remainder); } return end; } @Test public void testCalculateResponseTime() { Calendar issueReportedAt = Calendar.getInstance(); Calendar expectedResponseTime = Calendar.getInstance(); issueReportedAt.set(2011, 8, 19, 13, 0, 0); expectedResponseTime.set(2011, 8, 21, 13, 0, 0); assertTrue(expectedResponseTime.getTime().equals( calculateResponseTime(issueReportedAt.getTime(), maxResponseTime))); issueReportedAt.set(2011, 8, 19, 18, 5, 0); expectedResponseTime.set(2011, 8, 22, 9, 0, 0); assertTrue(expectedResponseTime.getTime().equals( calculateResponseTime(issueReportedAt.getTime(), maxResponseTime))); issueReportedAt.set(2011, 8, 23, 14, 0, 0); expectedResponseTime.set(2011, 8, 27, 14, 0, 0); assertTrue(expectedResponseTime.getTime().equals( calculateResponseTime(issueReportedAt.getTime(), maxResponseTime))); } 

您需要在Anils回答中向规范化部分添加一个额外的if情况,因为如果问题是在星期五上午10:00报告并且responseHours是10,那么在下一次递归调用中,issueReportedAt将是星期五晚上10点,女巫将被标准化为星期六晚上9点,女巫也是无效的。

 if (hourOfDay >= WorkingHours.TO_HOUR && dayOfWeek == Calendar.FRIDAY) { responseTime.add(Calendar.DATE, 3); responseTime.set(Calendar.HOUR_OF_DAY, WorkingHours.FROM_HOUR); responseTime.set(Calendar.MINUTE, WorkingHours.FROM_MINUTE); } 

下面的代码确实解决了这个问题

 public static Date addBusinessHours(Calendar startDate, int hours, int workingHourStart, int workingHourEnd){ System.out.println("Entering: Date Time " + startDate.getTime() + " | Remaining Hours: "+ hours + " | Working hours ("+workingHourStart+"-"+workingHourEnd+")"); if(hours == 0){ return startDate.getTime(); } int hourOfDay = startDate.get(Calendar.HOUR_OF_DAY); if(startDate.get(Calendar.MINUTE) > 0){ hourOfDay = hourOfDay +1; } int dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK); if(dayOfWeek == Calendar.SATURDAY){ startDate.add(Calendar.DATE, 2); startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); addBusinessHours(startDate, hours, workingHourStart, workingHourEnd); } if(dayOfWeek == Calendar.SUNDAY){ startDate.add(Calendar.DATE, 1); startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); addBusinessHours(startDate, hours, workingHourStart, workingHourEnd); } if(dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY){ if(hourOfDay < workingHourStart){ startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); hourOfDay = startDate.get(Calendar.HOUR_OF_DAY); dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK); addBusinessHours(startDate, hours, workingHourStart, workingHourEnd); } else if(hourOfDay >= workingHourEnd){ startDate.add(Calendar.DATE, 1); startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); hourOfDay = startDate.get(Calendar.HOUR_OF_DAY); dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK); addBusinessHours(startDate, hours, workingHourStart, workingHourEnd); } else if(hourOfDay >= workingHourStart && hourOfDay < workingHourEnd){ if(hours+hourOfDay <= workingHourEnd){ startDate.add(Calendar.HOUR_OF_DAY, hours); return startDate.getTime(); }else{ //System.out.println("¤¤" + startDate.getTime() ); startDate.add(Calendar.DATE, 1); //System.out.println("¤¤" + startDate.getTime() ); startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); //System.out.println("¤¤" + startDate.getTime() ); System.out.println("##"+hours+ "##"+ workingHourEnd + "##" + hourOfDay); int remaining_hours = hours - (workingHourEnd - hourOfDay); addBusinessHours(startDate, remaining_hours, workingHourStart, workingHourEnd); } } } return startDate.getTime(); }