Добавьте рабочие часы в Java DateTime - PullRequest
11 голосов
/ 18 сентября 2011

Для системы отслеживания ошибок мне нужно рассчитать время ответа на запрос.Таймер времени отклика должен работать только в рабочее время.Какой алгоритм / библиотеку я должен использовать для этой задачи?(Конечно, я знаю о Joda-Time или ObjectLab Kit, но не смог найти ничего, что помогло бы с моей задачей. Я что-то упустил?)

Пример:

  • Рабочее время: 9 утра - 5 вечера (8 часов в день)
  • Максимальное время ответа: 16 часов

Метод может выглядеть примерно так:

DateTime calculateResponseTime(DateTime issueReportedAt)

Я будупривести некоторые возможные входные данные и результаты в качестве примера:

  • Пн, 2011-09-19, 13:00 -> Ср, 2011-09-21, 1:00 ПП * 10101 *
  • Пн,2011-09-19, 18:05 -> Четверг, 2011-09-22, 9:00 утра * 019*
  • Пт, 2011-09-23, 14:00 -> Вт, 2011-09-27, 200:00

Ответы [ 4 ]

2 голосов
/ 19 сентября 2011

Я думаю, что Олег предлагал взглянуть на то, как jBPM реализует эту функциональность для вдохновения в разработку собственного решения. Ниже мой ответ заимствован из источника, который я нашел, выполнив Поиск кода 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)));

}
2 голосов
/ 18 сентября 2011

Вы можете взглянуть на бизнес-календарь jBPM .

Другая библиотека позволяет настраивать банковские праздники, но в ней нет понятия рабочих часов.

0 голосов
/ 17 октября 2017

Ниже код решает эту проблему

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();
}
0 голосов
/ 23 июля 2016

Необходимо добавить дополнительный регистр if к части нормализации из ответа Anils, потому что, если проблема сообщается в пятницу в 10:00 утра, а responseHours - 10, то в следующем рекурсивном вызове issueReportedAt будет в пятницу, 22:00. Ведьма будет нормализована до субботы 21:00, ведьма также недействительна.

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...