BusinessCalendarImpl implements BusinessCalendar { public Date calculateBusinessTimeAsDate(String timeExpression) { timeExpression = adoptISOFormat(timeExpression); String trimmed = timeExpression.trim(); int weeks = 0; int days = 0; int hours = 0; int min = 0; int sec = 0; if( trimmed.length() > 0 ) { Matcher mat = PatternConstants.SIMPLE_TIME_DATE_MATCHER.matcher(trimmed ); if ( mat.matches() ) { weeks = (mat.group( SIM_WEEK ) != null) ? Integer.parseInt( mat.group( SIM_WEEK ) ) : 0; days = (mat.group( SIM_DAY ) != null) ? Integer.parseInt( mat.group( SIM_DAY ) ) : 0; hours = (mat.group( SIM_HOU ) != null) ? Integer.parseInt( mat.group( SIM_HOU ) ) : 0; min = (mat.group( SIM_MIN ) != null) ? Integer.parseInt( mat.group( SIM_MIN ) ) : 0; sec = (mat.group( SIM_SEC ) != null) ? Integer.parseInt( mat.group( SIM_SEC ) ) : 0; } } int time = 0; Calendar c = new GregorianCalendar(); if (timezone != null) { c.setTimeZone(TimeZone.getTimeZone(timezone)); } if (this.clock != null) { c.setTimeInMillis(this.clock.getCurrentTime()); } int numberOfWeeks = days/daysPerWeek + weeks; if (numberOfWeeks > 0) { c.add(Calendar.WEEK_OF_YEAR, numberOfWeeks); } handleWeekend(c, hours > 0 || min > 0); hours += (days - (numberOfWeeks * daysPerWeek)) * hoursInDay; int numberOfDays = hours/hoursInDay; if (numberOfDays > 0) { for (int i = 0; i < numberOfDays; i++) { c.add(Calendar.DAY_OF_YEAR, 1); handleWeekend(c, false); handleHoliday(c, hours > 0 || min > 0); } } int currentCalHour = c.get(Calendar.HOUR_OF_DAY); if (currentCalHour >= endHour) { c.add(Calendar.DAY_OF_YEAR, 1); c.add(Calendar.HOUR_OF_DAY, startHour-currentCalHour); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); } else if (currentCalHour < startHour) { c.add(Calendar.HOUR_OF_DAY, startHour); } time = hours - (numberOfDays * hoursInDay); c.add(Calendar.HOUR, time); handleWeekend(c, true); handleHoliday(c, hours > 0 || min > 0); currentCalHour = c.get(Calendar.HOUR_OF_DAY); if (currentCalHour >= endHour) { c.add(Calendar.DAY_OF_YEAR, 1); 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); } int numberOfHours = min/60; if (numberOfHours > 0) { c.add(Calendar.HOUR, numberOfHours); min = min-(numberOfHours * 60); } c.add(Calendar.MINUTE, min); int numberOfMinutes = sec/60; if (numberOfMinutes > 0) { c.add(Calendar.MINUTE, numberOfMinutes); sec = sec-(numberOfMinutes * 60); } c.add(Calendar.SECOND, sec); currentCalHour = c.get(Calendar.HOUR_OF_DAY); if (currentCalHour >= endHour) { c.add(Calendar.DAY_OF_YEAR, 1); 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); } handleWeekend(c, false); handleHoliday(c, false); return c.getTime(); } BusinessCalendarImpl();  BusinessCalendarImpl(Properties configuration);  BusinessCalendarImpl(Properties configuration, SessionClock clock); long calculateBusinessTimeAsDuration(String timeExpression); Date calculateBusinessTimeAsDate(String timeExpression); static final String DAYS_PER_WEEK; static final String HOURS_PER_DAY; static final String START_HOUR; static final String END_HOUR; static final String HOLIDAYS; static final String HOLIDAY_DATE_FORMAT; static final String WEEKEND_DAYS; static final String TIMEZONE; }
@Test public void testCalculateMinutesPassingOverHoliday() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.HOLIDAYS, "2012-05-12:2012-05-19"); String expectedDate = "2012-05-21 09:15"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-11 16:45").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("30m"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateDays() { Properties config = new Properties(); String expectedDate = "2012-05-14 09:00"; SessionPseudoClock clock = new StaticPseudoClock(parseToDate("2012-05-04").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("6d"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateDaysStartingInWeekend() { Properties config = new Properties(); String expectedDate = "2012-05-09 09:00"; SessionPseudoClock clock = new StaticPseudoClock(parseToDate("2012-05-05").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("2d"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateDaysCustomWorkingDays() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.DAYS_PER_WEEK, "4"); config.setProperty(BusinessCalendarImpl.WEEKEND_DAYS, Calendar.FRIDAY + ","+Calendar.SATURDAY + "," +Calendar.SUNDAY); String expectedDate = "2012-05-15 14:30"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-03 14:30").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("6d"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateDaysMiddleDay() { Properties config = new Properties(); String expectedDate = "2012-05-11 12:27"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-03 12:27").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("6d"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateDaysHoursMinutes() { Properties config = new Properties(); String expectedDate = "2012-05-14 14:20"; SessionPseudoClock clock = new StaticPseudoClock(parseToDate("2012-05-04").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("6d4h80m"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateTimeDaysHoursMinutesHolidays() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.HOLIDAYS, "2012-05-10:2012-05-19"); String expectedDate = "2012-05-21 14:20"; SessionPseudoClock clock = new StaticPseudoClock(parseToDate("2012-05-04").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("6d4h80m"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateTimeDaysHoursMinutesSingleDayHolidays() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.HOLIDAYS, "2012-05-07"); String expectedDate = "2012-05-08 13:20"; SessionPseudoClock clock = new StaticPseudoClock(parseToDate("2012-05-04").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("1d4h20m"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateTimeDaysHoursMinutesSingleDayHolidaysInMiddleOfWeek() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.HOLIDAYS, "2012-05-09"); String expectedDate = "2012-05-10 15:30"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-08 11:10").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("1d4h20m"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateDaysPassingOverHolidayAtYearEnd() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.HOLIDAYS, "2012-12-31:2013-01-01"); String expectedDate = "2013-01-04 09:15"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-12-28 16:45").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("2d30m"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateDaysPassingOverHolidayAtYearEndWithWildcards() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.HOLIDAYS, "*-12-31:*-01-01"); String expectedDate = "2013-01-02 09:15"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-12-28 16:45").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("2d30m"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateISOHours() { Properties config = new Properties(); String expectedDate = "2012-05-04 16:45"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-04 13:45").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("PT3H"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateISODaysAndHours() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.HOLIDAYS, "2012-05-09"); String expectedDate = "2012-05-10 15:30"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-08 11:10").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("P1DT4H20M"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testSingleHolidayWithinGivenTime() { final Properties props = new Properties(); props.put(BusinessCalendarImpl.HOLIDAYS, "2015-01-13"); String expectedDate = "2015-01-15 11:38"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTimeAndMillis("2015-01-08 11:38:30.198").getTime()); BusinessCalendarImpl businessCalendarImpl = new BusinessCalendarImpl(props, clock); Date result = businessCalendarImpl.calculateBusinessTimeAsDate("4d"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateMillisecondsAsDefault() { Properties config = new Properties(); String expectedDate = "2012-05-04 16:45:10.000"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTimeAndMillis("2012-05-04 16:45:00.000").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("10000"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm:ss.SSS", result)); }
@Test public void testCalculateMinutesPassingAfterHour() { Properties config = new Properties(); String currentDate = "2018-05-02 19:51:33"; String expectedDate = "2018-05-03 09:01:00"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime(currentDate).getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("1m"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm:ss", result)); }
@Test public void testCalculateMinutesPassingHoliday() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.DAYS_PER_WEEK, "5"); config.setProperty(BusinessCalendarImpl.HOURS_PER_DAY, "8"); config.setProperty(BusinessCalendarImpl.START_HOUR, "9"); config.setProperty(BusinessCalendarImpl.END_HOUR, "18"); config.setProperty(BusinessCalendarImpl.WEEKEND_DAYS, "1,7"); config.setProperty(BusinessCalendarImpl.HOLIDAYS, "2018-04-30,2018-05-03:2018-05-05"); config.setProperty(BusinessCalendarImpl.HOLIDAY_DATE_FORMAT, "yyyy-MM-dd"); String currentDate = "2018-05-03 13:51:33"; String duration = "10m"; String expectedDate = "2018-05-07 09:10:00"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime(currentDate).getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate(duration); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm:ss", result)); }
@Test public void testCalculateMinutesPassingWeekend() { Properties config = new Properties(); String currentDate = "2018-05-06 13:51:33"; String duration = "10m"; String expectedDate = "2018-05-07 09:10:00"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime(currentDate).getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate(duration); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm:ss", result)); }
@Test public void testCalculateHours() { Properties config = new Properties(); String expectedDate = "2012-05-04 16:45"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-04 13:45").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("3h"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateHoursCustomWorkingHours() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.HOURS_PER_DAY, "6"); String expectedDate = "2012-05-04 15:45"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-03 13:45").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("8h"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateHoursPassingOverWeekend() { Properties config = new Properties(); String expectedDate = "2012-05-07 12:45"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-04 13:45").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("7h"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateHoursPassingOverCustomDefinedWeekend() { Properties config = new Properties(); config.setProperty(BusinessCalendarImpl.WEEKEND_DAYS, Calendar.FRIDAY + ","+Calendar.SATURDAY); String expectedDate = "2012-05-06 12:45"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-03 13:45").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("7h"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }
@Test public void testCalculateMinutesPassingOverWeekend() { Properties config = new Properties(); String expectedDate = "2012-05-07 09:15"; SessionPseudoClock clock = new StaticPseudoClock(parseToDateWithTime("2012-05-04 16:45").getTime()); BusinessCalendarImpl businessCal = new BusinessCalendarImpl(config, clock); Date result = businessCal.calculateBusinessTimeAsDate("30m"); assertEquals(expectedDate, formatDate("yyyy-MM-dd HH:mm", result)); }