将工作时间添加到Java DateTime
对于问题跟踪系统,我需要计算请求的响应时间。响应时间计时器应仅在工作时间内运行。此任务应使用什么算法/库?(当然,我知道Joda Time或ObjectLab Kit,但找不到任何有助于我完成任务的东西。我是否遗漏了什么?) 例如:将工作时间添加到Java DateTime,java,algorithm,date,Java,Algorithm,Date,对于问题跟踪系统,我需要计算请求的响应时间。响应时间计时器应仅在工作时间内运行。此任务应使用什么算法/库?(当然,我知道Joda Time或ObjectLab Kit,但找不到任何有助于我完成任务的东西。我是否遗漏了什么?) 例如: 营业时间:上午9时至下午5时(每天8小时) 最长响应时间:16小时 该方法可能类似于: DateTime calculateResponseTime(DateTime issueReportedAt) 我将给出一些可能的输入和结果作为示例: 2011年9月1
- 营业时间:上午9时至下午5时(每天8小时)
- 最长响应时间:16小时
DateTime calculateResponseTime(DateTime issueReportedAt)
我将给出一些可能的输入和结果作为示例:
- 2011年9月19日星期一下午1:00->2011年9月21日星期三下午1:00
- 2011年9月19日星期一下午6:05->2011年9月22日星期四上午9:00
- 2011年9月23日星期五下午2:00->2011年9月27日星期二下午2:00
另一个允许您配置银行假期,但它没有工作时间的概念。我认为Oleg的建议是查看jBPM实现此功能的方式,以获得编写您自己的解决方案的灵感。下面是我的答案,大量借用了我通过做一个调查发现的来源 它没有考虑到假期,但我会留给你作为练习。我是否可以建议每年使用一次更新限制日期列表?祝你好运
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)));
}
int fromHour=9;
int frommin=0;
整小时=17;
int-toMinute=0;
长最大响应时间=16;
日期计算响应时间(日期发布报告,长响应小时){
日期结束=空;
Calendar responseTime=Calendar.getInstance();
响应时间设置时间(发布报告数据);
int hourOfDay=responseTime.get(日历小时);
int dayOfWeek=responseTime.get(Calendar.dayOfWeek);
如果(小时日<小时){
responseTime.set(Calendar.HOUR,fromHour);
}
如果(hourOfDay>=toHour | | dayOfWeek==1){
responseTime.add(Calendar.DATE,1);
responseTime.set(日历.HOUR,fromHour);
responseTime.set(Calendar.MINUTE,fromMinute);
}否则如果(星期五==7){
添加(Calendar.DATE,2);
responseTime.set(日历.HOUR,fromHour);
responseTime.set(Calendar.MINUTE,fromMinute);
}
int hour=responseTime.get(日历.hour,OF,OF,OF,DAY);
int minute=responseTime.get(Calendar.minute);
长日期毫秒=((小时*60)+分钟)*60*1000;
长DayPartEndMillesons=((toHour*60)+toMinute)*60*1000;
此DayPart中的长毫秒=DayPartEndMills
-日期毫秒;
长持续时间毫秒=响应小时数*60*60*1000;
if(持续时间毫秒<毫秒此日期部分){
end=新日期(responseTime.getTimeInMillis()
+持续时间(毫秒);
}否则{
长余数=(持续毫秒-毫秒在这一天的部分)/60/60/1000;
Date dayPartEndDate=新日期(responseTime.getTimeInMillis()
+持续时间(毫秒);
responseTime.setTime(dayPartEndDate);
end=calculateResponseTime(responseTime.getTime(),余数);
}
返回端;
}
@试验
public void testCalculateResponseTime(){
Calendar issueReportedAt=Calendar.getInstance();
Calendar expectedResponseTime=Calendar.getInstance();
发布报告数据集(2011,8,19,13,0,0);
expectedResponseTime.set(2011,8,21,13,0,0);
assertTrue(expectedResponseTime.getTime().equals(
calculateResponseTime(IssuereReportedat.getTime(),
最大响应时间);
发布报告数据集(2011,8,19,18,5,0);
expectedResponseTime.set(2011,8,22,9,0,0);
assertTrue(expectedResponseTime.getTime().equals(
calculateResponseTime(IssuereReportedat.getTime(),
最大响应时间);
发布报告数据集(2011,8,23,14,0,0);
expectedResponseTime.set(2011,8,27,14,0,0);
assertTrue(expectedResponseTime.getTime().equals(
calculateResponseTime(IssuereReportedat.getTime(),
最大响应时间);
}
您需要在Anils答案的规范化部分添加一个额外的if case,因为如果问题在星期五上午10:00报告,响应时间为10小时,那么在下一个递归调用中,IssuerReportedat将在星期五晚上10点,witch将规范化为星期六晚上9:00,witch也无效
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();
}
public static Date addBusinessHours(日历开始日期、整数小时、整数工作小时开始、整数工作小时结束){
System.out.println(“输入:日期时间”+startDate.getTime()+”|剩余小时数:“+Hours+”|工作小时数(“+workingHourStart+”-“+workinghourrend+”));
如果(小时==0){
返回startDate.getTime();
}
int hourOfDay=startDate.get(日历小时);
如果(开始日期获取(日历分钟)>0){
hourOfDay=hourOfDay+1;
}
int dayOfWeek=startDate.get(Calendar.DAY,OF WEEK);
如果(dayOfWeek==日历。星期六){
startDate.add(Calendar.DATE,2);
startDate.set(日历小时,工作小时开始);
开始日期设置(日历分钟,0);
开始日期设置(日历秒,0);
添加营业时间(开始日期、小时数、工作小时数开始、工作小时数);
}
if(dayOfWeek==日历。星期日){
startDate.add(Calendar.DATE,1);
startDate.set(日历小时,工作小时开始);
开始日期设置(日历分钟,0);
开始日期设置(日历秒,0);
添加营业时间(开始日期、小时数、工作小时数开始、工作小时数);
}
如果(dayOfWeek!=Calendar.SATURDAY&&dayOfWeek!=Calendar.SUNDAY){
if(小时天数<工作小时开始){
startDate.set(日历小时,工作小时开始);
开始日期设置(日历分钟,0);
开始日期设置(日历秒,0);
hourOfDay=startDate.get(日历小时);
dayOfWeek=startDate.get(校准