[jbpm-commits] JBoss JBPM SVN: r6628 - in jbpm3/branches/jbpm-3.2-soa/modules/core/src: main/resources/org/jbpm/calendar and 3 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Fri Aug 27 02:48:54 EDT 2010


Author: alex.guizar at jboss.com
Date: 2010-08-27 02:48:53 -0400 (Fri, 27 Aug 2010)
New Revision: 6628

Added:
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm1776/
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java
Modified:
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/BusinessCalendar.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Day.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/DayPart.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Duration.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Holiday.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/resources/org/jbpm/calendar/jbpm.business.calendar.properties
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/BusinessCalendarTest.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/DayPartTest.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/DayTest.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/HolidayTest.java
Log:
JBPM-1776 deliver expected results from business time substraction;
update business calendar properties to 2010 u.s. holidays

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/BusinessCalendar.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/BusinessCalendar.java	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/BusinessCalendar.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -95,10 +95,16 @@
     Date end = null;
     if (duration.isBusinessTime()) {
       DayPart dayPart = findDayPart(date);
-      boolean isInbusinessHours = (dayPart != null);
-      if (!isInbusinessHours) {
+      if (dayPart == null) {
+        // outside business hours
+        Day day = findDay(date);
         Object[] result = new Object[2];
-        findDay(date).findNextDayPartStart(0, date, result);
+        if (duration.isNegative()) {
+          day.findPreviousDayPartEnd(date, result);
+        }
+        else {
+          day.findNextDayPartStart(0, date, result);
+        }
         date = (Date) result[0];
         dayPart = (DayPart) result[1];
       }
@@ -118,6 +124,7 @@
     calendar.set(Calendar.MINUTE, 0);
     calendar.set(Calendar.SECOND, 0);
     calendar.set(Calendar.MILLISECOND, 0);
+
     date = calendar.getTime();
     while (isHoliday(date)) {
       calendar.setTime(date);
@@ -127,6 +134,24 @@
     return date;
   }
 
+  Date findEndOfPreviousDay(Date date) {
+    Calendar calendar = getCalendar();
+    calendar.setTime(date);
+    calendar.add(Calendar.DATE, -1);
+    calendar.set(Calendar.HOUR_OF_DAY, 23);
+    calendar.set(Calendar.MINUTE, 0);
+    calendar.set(Calendar.SECOND, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+
+    date = calendar.getTime();
+    while (isHoliday(date)) {
+      calendar.setTime(date);
+      calendar.add(Calendar.DATE, -1);
+      date = calendar.getTime();
+    }
+    return date;
+  }
+
   public Day findDay(Date date) {
     Calendar calendar = getCalendar();
     calendar.setTime(date);
@@ -142,34 +167,30 @@
   }
 
   private DayPart findDayPart(Date date) {
-    DayPart dayPart = null;
     if (!isHoliday(date)) {
       Day day = findDay(date);
-      for (int i = 0; ((i < day.dayParts.length) && (dayPart == null)); i++) {
-        DayPart candidate = day.dayParts[i];
-        if (candidate.includes(date)) dayPart = candidate;
+      for (int i = 0; i < day.dayParts.length; i++) {
+        DayPart dayPart = day.dayParts[i];
+        if (dayPart.includes(date)) return dayPart;
       }
     }
-    return dayPart;
+    return null;
   }
 
   public DayPart findNextDayPart(Date date) {
-    DayPart nextDayPart = null;
-    while (nextDayPart == null) {
-      nextDayPart = findDayPart(date);
-      if (nextDayPart == null) {
-        date = findStartOfNextDay(date);
-        Object result[] = new Object[2];
-        Day day = findDay(date);
-        day.findNextDayPartStart(0, date, result);
-        nextDayPart = (DayPart) result[1];
-      }
+    DayPart nextDayPart = findDayPart(date);
+    if (nextDayPart == null) {
+      date = findStartOfNextDay(date);
+      Day day = findDay(date);
+      Object result[] = new Object[2];
+      day.findNextDayPartStart(0, date, result);
+      nextDayPart = (DayPart) result[1];
     }
     return nextDayPart;
   }
 
   public boolean isInBusinessHours(Date date) {
-    return (findDayPart(date) != null);
+    return findDayPart(date) != null;
   }
 
   public static Calendar getCalendar() {

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Day.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Day.java	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Day.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -35,20 +35,21 @@
 
   private static final long serialVersionUID = 1L;
 
-  DayPart[] dayParts;
-  BusinessCalendar businessCalendar;
+  final DayPart[] dayParts;
+  private final BusinessCalendar businessCalendar;
 
+  private static final String[] WEEK_DAY_KEYS = {
+    null, "weekday.sunday", "weekday.monday", "weekday.tuesday", "weekday.wednesday",
+    "weekday.thursday", "weekday.friday", "weekday.saturday"
+  };
+
   public static Day[] parseWeekDays(Properties calendarProperties,
     BusinessCalendar businessCalendar) {
-    DateFormat dateFormat = new SimpleDateFormat(calendarProperties.getProperty("hour.format"));
-    String[] weekDayKeys = {
-      null, "weekday.sunday", "weekday.monday", "weekday.tuesday", "weekday.wednesday",
-      "weekday.thursday", "weekday.friday", "weekday.saturday"
-    };
+    DateFormat timeFormat = new SimpleDateFormat(calendarProperties.getProperty("hour.format"));
 
-    Day[] weekDays = new Day[weekDayKeys.length];
+    Day[] weekDays = new Day[WEEK_DAY_KEYS.length];
     for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) {
-      weekDays[i] = new Day(calendarProperties.getProperty(weekDayKeys[i]), dateFormat,
+      weekDays[i] = new Day(calendarProperties.getProperty(WEEK_DAY_KEYS[i]), timeFormat,
         businessCalendar);
     }
     return weekDays;
@@ -70,11 +71,12 @@
   }
 
   public void findNextDayPartStart(int dayPartIndex, Date date, Object[] result) {
-    // if there is a day part in this day that starts after the given date
+    // if there is a day part that starts after the given date
     if (dayPartIndex < dayParts.length) {
-      if (dayParts[dayPartIndex].isStartAfter(date)) {
-        result[0] = dayParts[dayPartIndex].getStartTime(date);
-        result[1] = dayParts[dayPartIndex];
+      DayPart dayPart = dayParts[dayPartIndex];
+      if (dayPart.isStartAfter(date)) {
+        result[0] = dayPart.getStartTime(date);
+        result[1] = dayPart;
       }
       else {
         findNextDayPartStart(dayPartIndex + 1, date, result);
@@ -87,4 +89,27 @@
       nextDay.findNextDayPartStart(0, date, result);
     }
   }
+
+  void findPreviousDayPartEnd(Date date, Object[] result) {
+    findPreviousDayPartEnd(dayParts.length - 1, date, result);
+  }
+
+  void findPreviousDayPartEnd(int dayPartIndex, Date date, Object[] result) {
+    // if there is a day part that ends before the given date
+    if (dayPartIndex >= 0) {
+      DayPart dayPart = dayParts[dayPartIndex];
+      if (dayPart.endsBefore(date)) {
+        result[0] = dayPart.getEndTime(date);
+        result[1] = dayPart;
+      }
+      else {
+        findPreviousDayPartEnd(dayPartIndex - 1, date, result);
+      }
+    }
+    else {
+      date = businessCalendar.findEndOfPreviousDay(date);
+      Day previousDay = businessCalendar.findDay(date);
+      previousDay.findPreviousDayPartEnd(date, result);
+    }
+  }
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/DayPart.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/DayPart.java	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/DayPart.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -23,120 +23,137 @@
 
 import java.io.Serializable;
 import java.text.*;
-import java.text.DateFormat;
 import java.util.*;
 
 /**
- * is part of a day that can for example be used to represent business hours. 
- *
+ * is part of a day that can for example be used to represent business hours.
+ * 
  */
 public class DayPart implements Serializable {
 
   private static final long serialVersionUID = 1L;
-  
-  int fromHour = -1;
-  int fromMinute = -1;
-  int toHour = -1;
-  int toMinute = -1;
-  Day day = null;
-  int index = -1;
 
-  public DayPart(String dayPartText, DateFormat dateFormat, Day day, int index) {
-    this.day = day;
-    this.index = index;
-    
-    int separatorIndex = dayPartText.indexOf('-');
-    if (separatorIndex==-1) throw new IllegalArgumentException("improper format of daypart '"+dayPartText+"'");
-    String fromText = dayPartText.substring(0, separatorIndex).trim().toLowerCase(); 
-    String toText = dayPartText.substring(separatorIndex+1).trim().toLowerCase();
-    
-    try {
-      Date from = dateFormat.parse(fromText);
-      Date to = dateFormat.parse(toText);
-      
-      Calendar calendar = BusinessCalendar.getCalendar();
-      calendar.setTime(from);
-      fromHour = calendar.get(Calendar.HOUR_OF_DAY);
-      fromMinute = calendar.get(Calendar.MINUTE);
+  final int startHour;
+  final int startMinute;
+  final int endHour;
+  final int endMinute;
 
-      calendar.setTime(to);
-      toHour = calendar.get(Calendar.HOUR_OF_DAY);
-      if (toHour==0) {
-        toHour=24;
-      }
-      toMinute = calendar.get(Calendar.MINUTE);
+  final Day day;
+  final int index;
 
-    } catch (ParseException e) {
-      throw new IllegalArgumentException("improper format of daypart '" + dayPartText + "'");
+  public DayPart(String dayPartText, DateFormat timeFormat, Day day, int index) {
+    // parse start time
+    ParsePosition parsePosition = new ParsePosition(Duration.indexOfNonWhite(dayPartText, 0));
+    Date startTime = timeFormat.parse(dayPartText, parsePosition);
+    if (startTime == null) {
+      throw new IllegalArgumentException("failed to parse day part start time: " + dayPartText);
     }
+
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.setTime(startTime);
+    startHour = calendar.get(Calendar.HOUR_OF_DAY);
+    startMinute = calendar.get(Calendar.MINUTE);
+
+    // check time separator
+    int separatorIndex = Duration.indexOfNonWhite(dayPartText, parsePosition.getIndex());
+    if (dayPartText.charAt(separatorIndex) != '-') {
+      throw new IllegalArgumentException("missing '-' in day part: " + dayPartText);
+    }
+
+    // parse end time
+    parsePosition.setIndex(separatorIndex + 1);
+    Date endTime = timeFormat.parse(dayPartText, parsePosition);
+    if (endTime == null) {
+      throw new IllegalArgumentException("failed to parse day part end time: " + dayPartText);
+    }
+    calendar.setTime(endTime);
+    int hour = calendar.get(Calendar.HOUR_OF_DAY);
+    endHour = hour == 0 ? 24 : hour;
+    endMinute = calendar.get(Calendar.MINUTE);
+
+    this.day = day;
+    this.index = index;
   }
 
   public Date add(Date date, Duration duration) {
-    Date end = null;
-    
     Calendar calendar = BusinessCalendar.getCalendar();
     calendar.setTime(date);
     int hour = calendar.get(Calendar.HOUR_OF_DAY);
     int minute = calendar.get(Calendar.MINUTE);
+    long durationMillis = duration.getMilliseconds();
 
-    long millisInThisDayPart = (toHour - hour) * Duration.HOUR + (toMinute - minute) * Duration.MINUTE;
-    long durationMillis = duration.getMilliseconds();
-    
-    if (durationMillis <= millisInThisDayPart) {
-      end = duration.addTo(date);
-    } else {
-      Duration remainder = new Duration(durationMillis - millisInThisDayPart);
-      Date dayPartEndDate = new Date(date.getTime() + millisInThisDayPart);
-      
+    if (duration.isNegative()) {
+      long dayPartMillis = (startHour - hour) * Duration.HOUR + (startMinute - minute)
+        * Duration.MINUTE;
+      if (durationMillis >= dayPartMillis) return duration.addTo(date);
+
+      Duration remainder = new Duration(durationMillis - dayPartMillis);
+      Date dayPartStartDate = new Date(date.getTime() + dayPartMillis);
+
       Object[] result = new Object[2];
-      day.findNextDayPartStart(index+1, dayPartEndDate, result);
+      day.findPreviousDayPartEnd(index - 1, dayPartStartDate, result);
+      Date previousDayPartEnd = (Date) result[0];
+      DayPart previousDayPart = (DayPart) result[1];
+
+      return previousDayPart.add(previousDayPartEnd, remainder);
+    }
+    else {
+      long dayPartMillis = (endHour - hour) * Duration.HOUR + (endMinute - minute)
+        * Duration.MINUTE;
+      if (durationMillis <= dayPartMillis) return duration.addTo(date);
+
+      Duration remainder = new Duration(durationMillis - dayPartMillis);
+      Date dayPartEndDate = new Date(date.getTime() + dayPartMillis);
+
+      Object[] result = new Object[2];
+      day.findNextDayPartStart(index + 1, dayPartEndDate, result);
       Date nextDayPartStart = (Date) result[0];
       DayPart nextDayPart = (DayPart) result[1];
-      
-      end = nextDayPart.add(nextDayPartStart, remainder);
+
+      return nextDayPart.add(nextDayPartStart, remainder);
     }
-    
-    return end;
   }
-  
-  public boolean isStartAfter(Date date) {
+
+  public boolean isStartAfter(Date time) {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.setTime(date);
+    calendar.setTime(time);
+
     int hour = calendar.get(Calendar.HOUR_OF_DAY);
-    int minute = calendar.get(Calendar.MINUTE);
-    
-    return ( (hour<fromHour)
-             || ( (hour==fromHour)
-                  && (minute<=fromMinute) 
-                ) 
-           );
+    return startHour > hour
+      || (startHour == hour && startMinute >= calendar.get(Calendar.MINUTE));
   }
 
+  boolean endsBefore(Date time) {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.setTime(time);
 
-  public boolean includes(Date date) {
+    int hour = calendar.get(Calendar.HOUR_OF_DAY);
+    return endHour < hour || (endHour == hour && endMinute <= calendar.get(Calendar.MINUTE));
+  }
+
+  public boolean includes(Date time) {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.setTime(date);
+    calendar.setTime(time);
     int hour = calendar.get(Calendar.HOUR_OF_DAY);
     int minute = calendar.get(Calendar.MINUTE);
-    
-    return ( ( (fromHour<hour)
-               || ( (fromHour==hour)
-                   && (fromMinute<=minute) 
-                 )
-             ) &&
-             ( (hour<toHour)
-               || ( (hour==toHour)
-                    && (minute<=toMinute) 
-                  )
-             )
-           );
+
+    return (startHour < hour || (startHour == hour && startMinute <= minute))
+      && (hour < endHour || (hour == endHour && minute <= endMinute));
   }
 
-  public Date getStartTime(Date date) {
+  public Date getStartTime(Date time) {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.setTime(date);
-    calendar.set(Calendar.HOUR_OF_DAY, fromHour);
-    calendar.set(Calendar.MINUTE, fromMinute);
+    calendar.setTime(time);
+    calendar.set(Calendar.HOUR_OF_DAY, startHour);
+    calendar.set(Calendar.MINUTE, startMinute);
     return calendar.getTime();
   }
+
+  Date getEndTime(Date time) {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.setTime(time);
+    calendar.set(Calendar.HOUR_OF_DAY, endHour);
+    calendar.set(Calendar.MINUTE, endMinute);
+    return calendar.getTime();
+  }
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Duration.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Duration.java	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Duration.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -32,8 +32,6 @@
 import java.util.Map;
 import java.util.Properties;
 
-import org.jbpm.JbpmException;
-
 /**
  * interprets textual descriptions of a duration.
  * <p>
@@ -41,11 +39,11 @@
  * Where
  * <ul>
  * <li>&lt;quantity&gt; is a piece of text that is parsable with
- * <code>NumberFormat.getNumberInstance().parse(quantity)</code>. </li>
+ * <code>NumberFormat.getNumberInstance().parse(quantity)</code>.</li>
  * <li>&lt;unit&gt; is one of {second, seconds, minute, minutes, hour, hours, day, days, week,
- * weeks, month, months, year, years}. </li>
+ * weeks, month, months, year, years}.</li>
  * <li>And adding the optional indication <code>business</code> means that only business hours
- * should be taken into account for this duration. </li>
+ * should be taken into account for this duration.</li>
  * </ul>
  * </p>
  */
@@ -174,8 +172,8 @@
   }
 
   /**
-   * creates a duration from a textual description. syntax: {number} space {unit} where number is
-   * parsable to a java.lang.Number and unit is one of
+   * creates a duration from a textual description. syntax: {number} space {unit} where number
+   * is parsable to a java.lang.Number and unit is one of
    * <ul>
    * <li>second</li>
    * <li>seconds</li>
@@ -194,28 +192,26 @@
    * </ul>
    */
   public Duration(String duration) {
-    if (duration == null)
-      throw new JbpmException("duration is null");
-
     int index = indexOfNonWhite(duration, 0);
     char lead = duration.charAt(index);
-    if (lead == '+' || lead == '-')
-      ++index;
+    if (lead == '+' || lead == '-') ++index;
 
     // parse quantity
     NumberFormat format = NumberFormat.getNumberInstance(Locale.US);
     index = indexOfNonWhite(duration, index);
     ParsePosition position = new ParsePosition(index);
     Number quantity = format.parse(duration, position);
-    if (quantity == null)
-      throw new IllegalArgumentException("improper format of duration '" + duration + "'");
+    if (quantity == null) {
+      throw new IllegalArgumentException("failed to parse amount: " + duration);
+    }
 
     String unitText = duration.substring(position.getIndex()).trim();
     if (unitText.startsWith("business")) {
       // parse unit
       Long unit = (Long) businessAmounts.get(unitText);
-      if (unit == null)
-        throw new IllegalArgumentException("improper format of duration '" + duration + "'");
+      if (unit == null) {
+        throw new IllegalArgumentException("no such time unit: " + unitText);
+      }
 
       field = Calendar.MILLISECOND;
       amount = multiply(quantity, unit.longValue());
@@ -224,8 +220,9 @@
     else {
       // parse unit
       Integer unit = (Integer) calendarFields.get(unitText);
-      if (unit == null)
-        throw new IllegalArgumentException("improper format of duration '" + duration + "'");
+      if (unit == null) {
+        throw new IllegalArgumentException("no such time unit: " + unitText);
+      }
 
       // is quantity exactly representable as int?
       if (quantity instanceof Long && isInteger(quantity.longValue())) {
@@ -252,23 +249,25 @@
           amount = (long) (quantity.doubleValue() * WEEK);
           break;
         default:
-          throw new IllegalArgumentException("fractional amount not supported for unit '"
-              + unitText
-              + "'");
+          throw new IllegalArgumentException("fractional amount not supported for time unit: "
+            + unitText);
         }
       }
     }
 
-    if (lead == '-')
-      amount = -amount;
+    if (lead == '-') amount = -amount;
   }
 
-  private static int indexOfNonWhite(String str, int fromIndex) {
+  boolean isNegative() {
+    return amount < 0;
+  }
+
+  static int indexOfNonWhite(String str, int fromIndex) {
     int off = fromIndex;
-    int len = str.length();
-    while (off < len && str.charAt(off) <= ' ')
-      off++;
-    return off;
+    for (int len = str.length(); off < len; off++) {
+      if (str.charAt(off) != ' ') return off;
+    }
+    return -1;
   }
 
   private static boolean isInteger(long number) {
@@ -276,8 +275,7 @@
   }
 
   public Date addTo(Date date) {
-    if (field == Calendar.MILLISECOND)
-      return new Date(date.getTime() + amount);
+    if (field == Calendar.MILLISECOND) return new Date(date.getTime() + amount);
 
     Calendar calendar = BusinessCalendar.getCalendar();
     calendar.setTime(date);
@@ -300,9 +298,8 @@
     case Calendar.WEEK_OF_MONTH:
       return amount * WEEK;
     default:
-      throw new IllegalStateException("calendar field '"
-          + field
-          + "' does not have a fixed duration");
+      throw new IllegalStateException("calendar field '" + field
+        + "' does not have a fixed duration");
     }
   }
 

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Holiday.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Holiday.java	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/calendar/Holiday.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -23,7 +23,7 @@
 
 import java.io.Serializable;
 import java.text.DateFormat;
-import java.text.ParseException;
+import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -32,28 +32,26 @@
 import java.util.List;
 import java.util.Properties;
 
-import org.jbpm.JbpmException;
-
 /**
  * identifies a continuous set of days.
  */
 public class Holiday implements Serializable {
-  
+
   private static final long serialVersionUID = 1L;
-  
-  Date fromDay = null;
-  Date toDay = null;
-  BusinessCalendar businessCalendar = null;
 
-  public static List parseHolidays(Properties calendarProperties, BusinessCalendar businessCalendar) {
+  final Date startDate;
+  final Date endDate;
+
+  public static List parseHolidays(Properties calendarProperties,
+    BusinessCalendar businessCalendar) {
     List holidays = new ArrayList();
-    
+
     DateFormat dateFormat = new SimpleDateFormat(calendarProperties.getProperty("day.format"));
-    Iterator iter = calendarProperties.keySet().iterator();
-    while (iter.hasNext()) {
+    for (Iterator iter = calendarProperties.keySet().iterator(); iter.hasNext();) {
       String key = (String) iter.next();
       if (key.startsWith("holiday")) {
-        Holiday holiday = new Holiday(calendarProperties.getProperty(key), dateFormat, businessCalendar);
+        Holiday holiday = new Holiday(calendarProperties.getProperty(key), dateFormat,
+          businessCalendar);
         holidays.add(holiday);
       }
     }
@@ -62,33 +60,37 @@
   }
 
   public Holiday(String holidayText, DateFormat dateFormat, BusinessCalendar businessCalendar) {
-    this.businessCalendar = businessCalendar;
-    try {
-      int separatorIndex = holidayText.indexOf('-');
-      if (separatorIndex==-1) {
-        fromDay = dateFormat.parse(holidayText.trim());
-        toDay = fromDay;
-      } else {
-        String fromText = holidayText.substring(0, separatorIndex).trim();
-        String toText = holidayText.substring(separatorIndex+1).trim();
-        fromDay = dateFormat.parse(fromText);
-        toDay = dateFormat.parse(toText);
+    ParsePosition parsePosition = new ParsePosition(Duration.indexOfNonWhite(holidayText, 0));
+    startDate = dateFormat.parse(holidayText, parsePosition);
+    if (startDate == null) {
+      throw new IllegalArgumentException("failed to parse holiday start date: " + holidayText);
+    }
+
+    Date end;
+    int separatorIndex = Duration.indexOfNonWhite(holidayText, parsePosition.getIndex());
+    if (separatorIndex != -1) {
+      if (holidayText.charAt(separatorIndex) != '-') {
+        throw new IllegalArgumentException("expected '-' in holiday date range: " + holidayText);
       }
-      // now we are going to set the toDay to the end of the day, rather then the beginning.
-      // we take the start of the next day as the end of the toDay.
-      Calendar calendar = BusinessCalendar.getCalendar();
-      calendar.setTime(toDay);
-      calendar.add(Calendar.DATE, 1);
-      toDay = calendar.getTime();
-      
-    } catch (ParseException e) {
-      throw new JbpmException("couldn't parse holiday '"+holidayText+"'", e);
+
+      parsePosition.setIndex(Duration.indexOfNonWhite(holidayText, separatorIndex + 1));
+      end = dateFormat.parse(holidayText, parsePosition);
+      if (end == null) {
+        throw new IllegalArgumentException("failed to parse holiday end date: " + holidayText);
+      }
     }
+    else {
+      end = startDate;
+    }
+    // now set endDate to the end of the day, rather then the beginning
+    // take the start of the next day as the end of the endDate
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.setTime(end);
+    calendar.add(Calendar.DATE, 1);
+    endDate = calendar.getTime();
   }
 
   public boolean includes(Date date) {
-    return ( (fromDay.getTime()<=date.getTime())
-             && (date.getTime()<toDay.getTime())
-           );
+    return startDate.getTime() <= date.getTime() && date.getTime() < endDate.getTime();
   }
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/resources/org/jbpm/calendar/jbpm.business.calendar.properties
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/resources/org/jbpm/calendar/jbpm.business.calendar.properties	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/resources/org/jbpm/calendar/jbpm.business.calendar.properties	2010-08-27 06:48:53 UTC (rev 6628)
@@ -15,19 +15,29 @@
 # holiday ::= <holiday-period>
 # holiday-period ::= <start-day> [- <end-day>]
 # start-day and end-day must be in the day.format
-# below are the belgian official holidays
-holiday.1=  01/01/2005 # nieuwjaar (saturday)
-holiday.2=  27/03/2005 # pasen (sunday)
-holiday.3=  28/03/2005 # paasmaandag
-holiday.4=  01/05/2005 # feest van de arbeid (sunday)
-holiday.5=  05/05/2005 # hemelvaart 
-holiday.6=  15/05/2005 # pinksteren (sunday)
-holiday.7=  16/05/2005 # pinkstermaandag 
-holiday.8=  21/07/2005 # my birthday 
-holiday.9=  15/08/2005 # moederkesdag 
-holiday.10= 01/11/2005 # allerheiligen 
-holiday.11= 11/11/2005 # wapenstilstand 
-holiday.12= 25/12/2005 # kerstmis (sunday)
+# below are the u.s. official holidays
+# new year's day
+holiday.1=  01/01/2010
+# birthday of martin luther king
+holiday.2=  18/01/2010
+# washington's birthday
+holiday.3=  15/02/2010
+# memorial day
+holiday.4=  31/05/2010
+# independence day
+holiday.5=  05/07/2010
+# labor day 
+holiday.6=  06/09/2010
+# columbus day
+holiday.7=  11/10/2010
+# veterans day 
+holiday.8=  11/11/2010
+# thanksgiving day 
+holiday.9=  25/11/2010
+# day after thanksgiving
+holiday.10= 26/11/2010
+# christmas day 
+holiday.11= 24/12/2010 
 
 # typical workday excluding breaks
 business.day.expressed.in.hours=             7.5

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/BusinessCalendarTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/BusinessCalendarTest.java	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/BusinessCalendarTest.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -30,58 +30,29 @@
 
   static BusinessCalendar businessCalendar = new BusinessCalendar();
 
-  public void testNonBusinessDurationAddition() throws Exception {
+  public void testNonBusinessSecondAddition() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 10);
-    calendar.set(Calendar.MINUTE, 30);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2005, Calendar.APRIL, 7, 10, 30, 0);
     calendar.set(Calendar.MILLISECOND, 0);
     Date start = calendar.getTime();
 
-    Date twentySecondsLater = 
-      businessCalendar.add(start, new Duration("20 seconds"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 10);
-    calendar.set(Calendar.MINUTE, 30);
-    calendar.set(Calendar.SECOND, 20);
-    calendar.set(Calendar.MILLISECOND, 0);
+    calendar.add(Calendar.SECOND, 20);
     Date expected = calendar.getTime();
 
-    assertEquals(expected, twentySecondsLater);
+    Date actual = businessCalendar.add(start, new Duration("20 seconds"));
+    assertEquals(expected, actual);
   }
 
-  public void testNonBusinessDurationAdditionOverNonBusinessTime() throws Exception {
+  public void testNonBusinessMinuteAddition() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 11);
-    calendar.set(Calendar.MINUTE, 55);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2005, Calendar.APRIL, 7, 11, 55, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveBeforeTwelve = calendar.getTime();
+    Date start = calendar.getTime();
 
-    Date tenMinutesLaterThenFiveBeforeTwelve = 
-      businessCalendar.add(fiveBeforeTwelve, new Duration("10 minutes"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 12);
-    calendar.set(Calendar.MINUTE, 5);
-    calendar.set(Calendar.SECOND, 0);
-    calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveAfterTwelve = calendar.getTime();
+    calendar.add(Calendar.MINUTE, 10);
+    Date expected = calendar.getTime();
 
-    assertEquals(fiveAfterTwelve, tenMinutesLaterThenFiveBeforeTwelve);
+    assertEquals(expected, businessCalendar.add(start, new Duration("10 minutes")));
   }
 
   public void testNonBusinessFractionalDurationAddition() {
@@ -90,13 +61,11 @@
     calendar.set(Calendar.MILLISECOND, 125);
     Date start = calendar.getTime();
 
-    Date fiveWeeksLater = businessCalendar.add(start, new Duration("7.75 hours"));
-
-    calendar.set(Calendar.HOUR_OF_DAY, 14);
-    calendar.set(Calendar.MINUTE, 15);
+    calendar.add(Calendar.HOUR, 7);
+    calendar.add(Calendar.MINUTE, 45);
     Date expected = calendar.getTime();
 
-    assertEquals(expected, fiveWeeksLater);
+    assertEquals(expected, businessCalendar.add(start, new Duration("7.75 hours")));
   }
 
   public void testNonBusinessDayAddition() {
@@ -105,7 +74,7 @@
     calendar.set(Calendar.MILLISECOND, 125);
     Date start = calendar.getTime();
 
-    calendar.set(Calendar.DAY_OF_MONTH, 15);
+    calendar.add(Calendar.DAY_OF_MONTH, 10);
     Date expected = calendar.getTime();
 
     assertEquals(expected, businessCalendar.add(start, new Duration("10 days")));
@@ -117,8 +86,7 @@
     calendar.set(Calendar.MILLISECOND, 125);
     Date start = calendar.getTime();
 
-    calendar.set(Calendar.MONTH, Calendar.MARCH);
-    calendar.set(Calendar.DAY_OF_MONTH, 11);
+    calendar.add(Calendar.WEEK_OF_YEAR, 5);
     Date expected = calendar.getTime();
 
     assertEquals(expected, businessCalendar.add(start, new Duration("5 weeks")));
@@ -130,7 +98,7 @@
     calendar.set(Calendar.MILLISECOND, 125);
     Date start = calendar.getTime();
 
-    calendar.set(Calendar.MONTH, Calendar.MAY);
+    calendar.add(Calendar.MONTH, 3);
     Date expected = calendar.getTime();
 
     assertEquals(expected, businessCalendar.add(start, new Duration("3 months")));
@@ -142,227 +110,128 @@
     calendar.set(Calendar.MILLISECOND, 125);
     Date start = calendar.getTime();
 
-    calendar.set(Calendar.YEAR, 2009);
+    calendar.add(Calendar.YEAR, 1);
     Date expected = calendar.getTime();
 
     assertEquals(expected, businessCalendar.add(start, new Duration("1 year")));
   }
 
-  public void testBusinessDurationAdditionInBusinessTime() throws Exception {
+  public void testBusinessDurationAdditionOverBusinessTime() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 11);
-    calendar.set(Calendar.MINUTE, 55);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2005, Calendar.APRIL, 7, 11, 55, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveBeforeTwelve = calendar.getTime();
+    Date start = calendar.getTime();
 
-    Date oneMinuteLaterThenFiveBeforeTwelve = 
-      businessCalendar.add(fiveBeforeTwelve, new Duration("1 business minute"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 11);
-    calendar.set(Calendar.MINUTE, 56);
-    calendar.set(Calendar.SECOND, 0);
-    calendar.set(Calendar.MILLISECOND, 0);
-    Date fourBeforeTwelve = calendar.getTime();
+    calendar.add(Calendar.MINUTE, 1);
+    Date expected = calendar.getTime();
 
-    assertEquals(fourBeforeTwelve, oneMinuteLaterThenFiveBeforeTwelve);
+    assertEquals(expected, businessCalendar.add(start, new Duration("1 business minute")));
   }
 
   public void testBusinessDurationAdditionOverLunchBreak() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 11);
-    calendar.set(Calendar.MINUTE, 55);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2005, Calendar.APRIL, 7, 11, 55, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveBeforeTwelve = calendar.getTime();
+    Date start = calendar.getTime();
 
-    Date tenBusinessMinutesAfterFiveBeforeTwelve = 
-      businessCalendar.add(fiveBeforeTwelve, new Duration("10 business minutes"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 12);
-    calendar.set(Calendar.MINUTE, 35);
-    calendar.set(Calendar.SECOND, 0);
-    calendar.set(Calendar.MILLISECOND, 0);
-    Date twelveThirtyfive = calendar.getTime();
+    calendar.add(Calendar.MINUTE, 10);
+    // lunch break spans 30 minutes
+    calendar.add(Calendar.MINUTE, 30);
+    Date expected = calendar.getTime();
 
-    assertEquals(twelveThirtyfive, tenBusinessMinutesAfterFiveBeforeTwelve);
+    assertEquals(expected, businessCalendar.add(start, new Duration("10 business minutes")));
   }
 
   public void testBusinessDurationAdditionOverDayBreak() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 16);
-    calendar.set(Calendar.MINUTE, 55);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2005, Calendar.APRIL, 7, 16, 55, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveBeforeFive = calendar.getTime();
+    Date start = calendar.getTime();
 
-    Date tenBusinessMinutesAfterFiveBeforeFive = 
-      businessCalendar.add(fiveBeforeFive, new Duration("10 business minutes"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 8);
-    calendar.set(Calendar.HOUR_OF_DAY, 9);
-    calendar.set(Calendar.MINUTE, 5);
-    calendar.set(Calendar.SECOND, 0);
-    calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveAfterNineNextDay = calendar.getTime();
+    calendar.add(Calendar.MINUTE, 10);
+    // there are 16 hours between 17:00 and 9:00
+    calendar.add(Calendar.HOUR, 16);
+    Date expected = calendar.getTime();
 
-    assertEquals(fiveAfterNineNextDay, tenBusinessMinutesAfterFiveBeforeFive);
+    assertEquals(expected, businessCalendar.add(start, new Duration("10 business minutes")));
   }
 
-  public void testBusinessDurationAdditionOverHolidayBreak() throws Exception {
+  public void testBusinessDurationAdditionOverHoliday() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.MAY);
-    calendar.set(Calendar.DAY_OF_MONTH, 4);
-    calendar.set(Calendar.HOUR_OF_DAY, 16);
-    calendar.set(Calendar.MINUTE, 55);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2010, Calendar.NOVEMBER, 10, 16, 55, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveBeforeFive = calendar.getTime();
+    Date start = calendar.getTime();
 
-    Date tenBusinessMinutesAfterFiveBeforeFive = 
-      businessCalendar.add(fiveBeforeFive, new Duration("10 business minutes"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.MAY);
-    calendar.set(Calendar.DAY_OF_MONTH, 6);
-    calendar.set(Calendar.HOUR_OF_DAY, 9);
-    calendar.set(Calendar.MINUTE, 5);
-    calendar.set(Calendar.SECOND, 0);
-    calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveAfterNineTwoDaysLater = calendar.getTime();
+    calendar.add(Calendar.MINUTE, 10);
+    // there are 16 hours between 17:00 and 9:00
+    calendar.add(Calendar.HOUR, 16);
+    // holiday
+    calendar.add(Calendar.DAY_OF_MONTH, 1);
+    Date expected = calendar.getTime();
 
-    assertEquals(fiveAfterNineTwoDaysLater, tenBusinessMinutesAfterFiveBeforeFive);
+    assertEquals(expected, businessCalendar.add(start, new Duration("10 business minutes")));
   }
 
-  public void testBusinessDurationAdditionOverWeekendBreak() throws Exception {
+  public void testBusinessDurationAdditionOverWeekend() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 8);
-    calendar.set(Calendar.HOUR_OF_DAY, 16);
-    calendar.set(Calendar.MINUTE, 55);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2005, Calendar.APRIL, 8, 16, 55, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveBeforeFive = calendar.getTime();
+    Date start = calendar.getTime();
 
-    Date tenBusinessMinutesAfterFiveBeforeFive = 
-      businessCalendar.add(fiveBeforeFive, new Duration("10 business minutes"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 11);
-    calendar.set(Calendar.HOUR_OF_DAY, 9);
-    calendar.set(Calendar.MINUTE, 5);
-    calendar.set(Calendar.SECOND, 0);
-    calendar.set(Calendar.MILLISECOND, 0);
-    Date fiveAfterNineAfterTheWeekend = calendar.getTime();
+    calendar.add(Calendar.MINUTE, 10);
+    // there are 16 hours between 17:00 and 9:00
+    calendar.add(Calendar.HOUR, 16);
+    // weekend
+    calendar.add(Calendar.DAY_OF_MONTH, 2);
+    Date expected = calendar.getTime();
 
-    assertEquals(fiveAfterNineAfterTheWeekend, tenBusinessMinutesAfterFiveBeforeFive);
+    assertEquals(expected, businessCalendar.add(start, new Duration("10 business minutes")));
   }
 
   public void testTwoBusinessHoursOverLunch() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 11);
-    calendar.set(Calendar.MINUTE, 15);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2005, Calendar.APRIL, 7, 11, 15, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    Date quarterPastTwelve = calendar.getTime(); 
+    Date start = calendar.getTime();
 
-    Date twoBusinessHoursAfterFiveBeforeFive = 
-      businessCalendar.add(quarterPastTwelve, new Duration("2 business hours"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 7);
-    calendar.set(Calendar.HOUR_OF_DAY, 13);
-    calendar.set(Calendar.MINUTE, 45);
-    calendar.set(Calendar.SECOND, 0);
-    calendar.set(Calendar.MILLISECOND, 0);
-    Date rightAfterLunch = calendar.getTime();
+    calendar.add(Calendar.HOUR, 2);
+    // lunch break spans 30 minutes
+    calendar.add(Calendar.MINUTE, 30);
+    Date expected = calendar.getTime();
 
-    assertEquals(rightAfterLunch, twoBusinessHoursAfterFiveBeforeFive);
+    assertEquals(expected, businessCalendar.add(start, new Duration("2 business hours")));
   }
 
-  public void testBusinessDurationAdditionStartingOutsideBusinessHours() throws Exception {
+  public void testBusinessDurationAdditionOutsideBusinessHours() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 8);
-    calendar.set(Calendar.HOUR_OF_DAY, 12);
-    calendar.set(Calendar.MINUTE, 15);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2005, Calendar.APRIL, 8, 12, 15, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    Date quarterPastTwelve = calendar.getTime();
+    Date start = calendar.getTime();
 
-    Date tenBusinessMinutesAfterQuarterPastTwelve = 
-      businessCalendar.add(quarterPastTwelve, new Duration("30 business minutes"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 8);
-    calendar.set(Calendar.HOUR_OF_DAY, 13);
-    calendar.set(Calendar.MINUTE, 0);
-    calendar.set(Calendar.SECOND, 0);
-    calendar.set(Calendar.MILLISECOND, 0);
-    Date oneOClock = calendar.getTime();
+    calendar.add(Calendar.MINUTE, 30);
+    // lunch break ends at 12:30
+    calendar.add(Calendar.MINUTE, 15);
+    Date expected = calendar.getTime();
 
-    assertEquals(oneOClock, tenBusinessMinutesAfterQuarterPastTwelve);
+    assertEquals(expected, businessCalendar.add(start, new Duration("30 business minutes")));
   }
 
-  public void testBusinessDurationAdditionStartingOutsideBusinessHoursAndOverWeekend()
-      throws Exception {
+  public void testBusinessDurationAdditionOutsideBusinessHoursOverWeekend() throws Exception {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 8);
-    calendar.set(Calendar.HOUR_OF_DAY, 12);
-    calendar.set(Calendar.MINUTE, 15);
-    calendar.set(Calendar.SECOND, 0);
+    calendar.set(2005, Calendar.APRIL, 8, 12, 15, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    Date quarterPastTwelve = calendar.getTime();
+    Date start = calendar.getTime();
 
-    Date fiveBusinessHoursAfterQuarterPastTwelve = 
-      businessCalendar.add(quarterPastTwelve, new Duration("5 business hours"));
-    
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 11);
-    calendar.set(Calendar.HOUR_OF_DAY, 9);
-    calendar.set(Calendar.MINUTE, 30);
-    calendar.set(Calendar.SECOND, 0);
-    calendar.set(Calendar.MILLISECOND, 0);
-    Date halfPastNineAfterTheWeekend = calendar.getTime();
+    calendar.add(Calendar.HOUR, 5);
+    // lunch break ends at 12:30
+    calendar.add(Calendar.MINUTE, 15);
+    // there are 16 hours between 17:00 and 9:00
+    calendar.add(Calendar.HOUR, 16);
+    // weekend
+    calendar.add(Calendar.DAY_OF_MONTH, 2);
+    Date expected = calendar.getTime();
 
-    assertEquals(halfPastNineAfterTheWeekend, fiveBusinessHoursAfterQuarterPastTwelve);
+    assertEquals(expected, businessCalendar.add(start, new Duration("5 business hours")));
   }
 
   public void testBusinessFractionalDurationAddition() {
@@ -371,8 +240,12 @@
     calendar.set(Calendar.MILLISECOND, 0);
     Date start = calendar.getTime();
 
-    calendar.set(Calendar.DAY_OF_MONTH, 8);
-    calendar.set(Calendar.MINUTE, 45);
+    calendar.add(Calendar.HOUR, 7);
+    calendar.add(Calendar.MINUTE, 45);
+    // lunch break spans 30 minutes
+    calendar.add(Calendar.MINUTE, 30);
+    // there are 16 hours between 17:00 and 9:00
+    calendar.add(Calendar.HOUR, 16);
     Date expected = calendar.getTime();
 
     assertEquals(expected, businessCalendar.add(start, new Duration("7.75 business hours")));
@@ -405,12 +278,12 @@
 
   public void testBusinessMonthAddition() {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(2005, Calendar.FEBRUARY, 7, 9, 30, 0);
+    calendar.set(2010, Calendar.FEBRUARY, 8, 9, 30, 0);
     calendar.set(Calendar.MILLISECOND, 0);
     Date start = calendar.getTime();
 
     calendar.set(Calendar.MONTH, Calendar.MAY);
-    calendar.set(Calendar.DAY_OF_MONTH, 9);
+    calendar.set(Calendar.DAY_OF_MONTH, 7);
     Date expected = calendar.getTime();
 
     assertEquals(expected, businessCalendar.add(start, new Duration("3 business months")));
@@ -418,12 +291,12 @@
 
   public void testBusinessYearAddition() {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(2005, Calendar.FEBRUARY, 7, 9, 30, 0);
+    calendar.set(2010, Calendar.FEBRUARY, 8, 9, 30, 0);
     calendar.set(Calendar.MILLISECOND, 0);
     Date start = calendar.getTime();
 
-    calendar.set(Calendar.YEAR, 2006);
-    calendar.set(Calendar.DAY_OF_MONTH, 6);
+    calendar.set(Calendar.YEAR, 2011);
+    calendar.set(Calendar.DAY_OF_MONTH, 9);
     Date expected = calendar.getTime();
 
     assertEquals(expected, businessCalendar.add(start, new Duration("1 business year")));
@@ -431,48 +304,37 @@
 
   public void testNextDayStart() {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 8);
-    calendar.set(Calendar.HOUR_OF_DAY, 13);
-    calendar.set(Calendar.MINUTE, 15);
-    Date justAfterLunchOnAprilEight2005 = calendar.getTime();
-    Date startOfNextDay = businessCalendar.findStartOfNextDay(justAfterLunchOnAprilEight2005);
+    calendar.set(2005, Calendar.APRIL, 8, 13, 15);
+    Date fridayAfterLunch = calendar.getTime();
 
-    calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 9);
+    calendar.add(Calendar.DAY_OF_MONTH, 1);
     calendar.set(Calendar.HOUR_OF_DAY, 0);
     calendar.set(Calendar.MINUTE, 0);
     calendar.set(Calendar.SECOND, 0);
     calendar.set(Calendar.MILLISECOND, 0);
-    assertEquals(calendar.getTime(), startOfNextDay);
+    Date nextDay = calendar.getTime();
+
+    assertEquals(nextDay, businessCalendar.findStartOfNextDay(fridayAfterLunch));
   }
 
   public void testDayOfWeek() {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 8);
-    calendar.set(Calendar.HOUR_OF_DAY, 13);
-    calendar.set(Calendar.MINUTE, 15);
-    Date justAfterLunchOnAprilEight2005 = calendar.getTime();
+    calendar.set(2005, Calendar.APRIL, 8, 13, 15);
+    Date fridayAfterLunch = calendar.getTime();
 
-    Day day = businessCalendar.findDay(justAfterLunchOnAprilEight2005);
+    Day day = businessCalendar.findDay(fridayAfterLunch);
     assertSame(businessCalendar.getWeekDays()[Calendar.FRIDAY], day);
   }
 
   public void testFindNextDayPart() {
     Calendar calendar = BusinessCalendar.getCalendar();
-    calendar.set(Calendar.YEAR, 2005);
-    calendar.set(Calendar.MONTH, Calendar.APRIL);
-    calendar.set(Calendar.DAY_OF_MONTH, 8);
-    calendar.set(Calendar.HOUR_OF_DAY, 21);
-    calendar.set(Calendar.MINUTE, 15);
-    Date outsideBusinessHours = calendar.getTime();
+    calendar.set(2005, Calendar.APRIL, 8, 21, 15);
+    Date fridayNight = calendar.getTime();
 
-    BusinessCalendar bc = new BusinessCalendar();
-    bc.findNextDayPart(outsideBusinessHours);
+    DayPart dayPart = businessCalendar.findNextDayPart(fridayNight);
+    assertEquals(9, dayPart.startHour);
+    assertEquals(0, dayPart.startMinute);
+    assertEquals(businessCalendar.getWeekDays()[Calendar.MONDAY], dayPart.day);
+    assertEquals(0, dayPart.index);
   }
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/DayPartTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/DayPartTest.java	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/DayPartTest.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -31,28 +31,28 @@
   public void testDayPartParsing() {
     DateFormat dateFormat = new SimpleDateFormat("HH:mm");
     DayPart dayPart = new DayPart("9:00-12:15", dateFormat, null, 0);
-    assertEquals(9, dayPart.fromHour);
-    assertEquals(0, dayPart.fromMinute);
-    assertEquals(12, dayPart.toHour);
-    assertEquals(15, dayPart.toMinute);
+    assertEquals(9, dayPart.startHour);
+    assertEquals(0, dayPart.startMinute);
+    assertEquals(12, dayPart.endHour);
+    assertEquals(15, dayPart.endMinute);
   }
 
   public void testDayPartWithSpacesParsing() {
     DateFormat dateFormat = new SimpleDateFormat("HH:mm");
     DayPart dayPart = new DayPart(" 9:00 - 12:15 ", dateFormat, null, 0);
-    assertEquals(9, dayPart.fromHour);
-    assertEquals(0, dayPart.fromMinute);
-    assertEquals(12, dayPart.toHour);
-    assertEquals(15, dayPart.toMinute);
+    assertEquals(9, dayPart.startHour);
+    assertEquals(0, dayPart.startMinute);
+    assertEquals(12, dayPart.endHour);
+    assertEquals(15, dayPart.endMinute);
   }
 
   public void testDayPartAmPmParsing() {
     DateFormat dateFormat = new SimpleDateFormat("hh'h'mma");
     DayPart dayPart = new DayPart("9h00am-12h15pm", dateFormat, null, 0);
-    assertEquals(9, dayPart.fromHour);
-    assertEquals(0, dayPart.fromMinute);
-    assertEquals(12, dayPart.toHour);
-    assertEquals(15, dayPart.toMinute);
+    assertEquals(9, dayPart.startHour);
+    assertEquals(0, dayPart.startMinute);
+    assertEquals(12, dayPart.endHour);
+    assertEquals(15, dayPart.endMinute);
   }
   
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/DayTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/DayTest.java	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/DayTest.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -33,10 +33,10 @@
     Day day = new Day("9:00-12:15", dateFormat, null);
     assertEquals(1, day.dayParts.length);
     DayPart dayPart = day.dayParts[0];
-    assertEquals(9, dayPart.fromHour);
-    assertEquals(0, dayPart.fromMinute);
-    assertEquals(12, dayPart.toHour);
-    assertEquals(15, dayPart.toMinute);
+    assertEquals(9, dayPart.startHour);
+    assertEquals(0, dayPart.startMinute);
+    assertEquals(12, dayPart.endHour);
+    assertEquals(15, dayPart.endMinute);
   }
 
   public void testDayMultipleDayPartsParsing() {
@@ -44,10 +44,10 @@
     Day day = new Day("9:00-12:15 & 13:00-17:00", dateFormat, null);
     assertEquals(2, day.dayParts.length);
     DayPart dayPart = day.dayParts[1];
-    assertEquals(13, dayPart.fromHour);
-    assertEquals(0, dayPart.fromMinute);
-    assertEquals(17, dayPart.toHour);
-    assertEquals(0, dayPart.toMinute);
+    assertEquals(13, dayPart.startHour);
+    assertEquals(0, dayPart.startMinute);
+    assertEquals(17, dayPart.endHour);
+    assertEquals(0, dayPart.endMinute);
   }
 
   public void testEmptyDayParsing() {
@@ -61,14 +61,14 @@
     Day day = new Day("8:00-12:30 & 13:30-24:00", dateFormat, null);
     assertEquals(2, day.dayParts.length);
     DayPart dayPart = day.dayParts[0];
-    assertEquals(8, dayPart.fromHour);
-    assertEquals(0, dayPart.fromMinute);
-    assertEquals(12, dayPart.toHour);
-    assertEquals(30, dayPart.toMinute);
+    assertEquals(8, dayPart.startHour);
+    assertEquals(0, dayPart.startMinute);
+    assertEquals(12, dayPart.endHour);
+    assertEquals(30, dayPart.endMinute);
     dayPart = day.dayParts[1];
-    assertEquals(13, dayPart.fromHour);
-    assertEquals(30, dayPart.fromMinute);
-    assertEquals(24, dayPart.toHour);
-    assertEquals(0, dayPart.toMinute);
+    assertEquals(13, dayPart.startHour);
+    assertEquals(30, dayPart.startMinute);
+    assertEquals(24, dayPart.endHour);
+    assertEquals(0, dayPart.endMinute);
   }
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/HolidayTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/HolidayTest.java	2010-08-25 12:52:13 UTC (rev 6627)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/calendar/HolidayTest.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -44,7 +44,7 @@
     calendar.set(Calendar.MILLISECOND, 0);
     Date expectedFromDay = calendar.getTime();
 
-    assertEquals(expectedFromDay, holiday.fromDay);
+    assertEquals(expectedFromDay, holiday.startDate);
     
     calendar.set(Calendar.YEAR, 2005);
     calendar.set(Calendar.MONTH, Calendar.JULY);
@@ -55,7 +55,7 @@
     calendar.set(Calendar.MILLISECOND, 0);
     Date expectedToDay = calendar.getTime();
 
-    assertEquals(expectedToDay, holiday.toDay);
+    assertEquals(expectedToDay, holiday.endDate);
   }
 
   public void testHolidayMulitDayParsing() throws Exception {
@@ -72,7 +72,7 @@
     calendar.set(Calendar.MILLISECOND, 0);
     Date expectedFromDay = calendar.getTime();
 
-    assertEquals(expectedFromDay, holiday.fromDay);
+    assertEquals(expectedFromDay, holiday.startDate);
     
     calendar.set(Calendar.YEAR, 2005);
     calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);
@@ -83,6 +83,6 @@
     calendar.set(Calendar.MILLISECOND, 0);
     Date expectedToDay = calendar.getTime();
 
-    assertEquals(expectedToDay, holiday.toDay);
+    assertEquals(expectedToDay, holiday.endDate);
   }
 }

Added: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java	2010-08-27 06:48:53 UTC (rev 6628)
@@ -0,0 +1,244 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.jbpm1776;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.jbpm.AbstractJbpmTestCase;
+import org.jbpm.calendar.BusinessCalendar;
+import org.jbpm.calendar.Duration;
+
+/**
+ * Business time substraction delivers unexpected results.
+ * 
+ * @see <a href="https://jira.jboss.org/browse/JBPM-1776">JBPM-1776</a>
+ * @author Alejandro Guizar
+ */
+public class JBPM1776Test extends AbstractJbpmTestCase {
+
+  static BusinessCalendar businessCalendar = new BusinessCalendar();
+
+  public void testNonBusinessSecondSubstraction() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.APRIL, 7, 10, 30, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.SECOND, -20);
+    Date expected = calendar.getTime();
+
+    Date actual = businessCalendar.add(start, new Duration("-20 seconds"));
+    assertEquals(expected, actual);
+  }
+
+  public void testNonBusinessMinuteSubstraction() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.APRIL, 7, 11, 55, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.MINUTE, -10);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-10 minutes")));
+  }
+
+  public void testNonBusinessFractionalDurationSubstraction() {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
+    calendar.set(Calendar.MILLISECOND, 125);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.HOUR, -7);
+    calendar.add(Calendar.MINUTE, -45);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-7.75 hours")));
+  }
+
+  public void testNonBusinessDaySubstraction() {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.FEBRUARY, 5, 6, 30, 45);
+    calendar.set(Calendar.MILLISECOND, 125);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.DAY_OF_MONTH, -10);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-10 days")));
+  }
+
+  public void testNonBusinessWeekSubstraction() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
+    calendar.set(Calendar.MILLISECOND, 125);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.WEEK_OF_YEAR, -5);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-5 weeks")));
+  }
+
+  public void testNonBusinessMonthSubstraction() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
+    calendar.set(Calendar.MILLISECOND, 125);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.MONTH, -3);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-3 months")));
+  }
+
+  public void testNonBusinessYearSubstraction() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
+    calendar.set(Calendar.MILLISECOND, 125);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.YEAR, -1);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-1 year")));
+  }
+
+  public void testBusinessDurationSubstractionOverBusinessTime() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.APRIL, 7, 11, 55, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.MINUTE, -1);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-1 business minute")));
+  }
+
+  public void testBusinessDurationSubstractionOverLunchBreak() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.APRIL, 7, 12, 35, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.MINUTE, -10);
+    // lunch break spans 30 minutes
+    calendar.add(Calendar.MINUTE, -30);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
+  }
+
+  public void testBusinessDurationSubstractionOverDayBreak() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.APRIL, 8, 9, 5, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.MINUTE, -10);
+    // there are 16 hours between 17:00 and 9:00
+    calendar.add(Calendar.HOUR, -16);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
+  }
+
+  public void testBusinessDurationSubstractionOverHoliday() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2010, Calendar.NOVEMBER, 12, 9, 5, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.MINUTE, -10);
+    // there are 16 hours between 17:00 and 9:00
+    calendar.add(Calendar.HOUR, -16);
+    // holiday
+    calendar.add(Calendar.DAY_OF_MONTH, -1);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
+  }
+
+  public void testBusinessDurationSubstractionOverWeekend() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.APRIL, 11, 9, 5, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.MINUTE, -10);
+    // there are 16 hours between 17:00 and 9:00
+    calendar.add(Calendar.HOUR, -16);
+    // weekend
+    calendar.add(Calendar.DAY_OF_MONTH, -2);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
+  }
+
+  public void testTwoBusinessHoursOverLunch() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.APRIL, 7, 13, 45, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.HOUR, -2);
+    // lunch break spans 30 minutes
+    calendar.add(Calendar.MINUTE, -30);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-2 business hours")));
+  }
+
+  public void testBusinessDurationSubstractionOutsideBusinessHours() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.APRIL, 8, 12, 15, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.MINUTE, -30);
+    // lunch break ends at 12:30
+    calendar.add(Calendar.MINUTE, -15);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-30 business minutes")));
+  }
+
+  public void testBusinessDurationSubstractionOutsideBusinessHoursOverWeekend() throws Exception {
+    Calendar calendar = BusinessCalendar.getCalendar();
+    calendar.set(2005, Calendar.APRIL, 11, 12, 15, 0);
+    calendar.set(Calendar.MILLISECOND, 0);
+    Date start = calendar.getTime();
+
+    calendar.add(Calendar.HOUR, -5);
+    // lunch break ends at 12:30
+    calendar.add(Calendar.MINUTE, -15);
+    // there are 16 hours between 17:00 and 9:00
+    calendar.add(Calendar.HOUR, -16);
+    // weekend
+    calendar.add(Calendar.DAY_OF_MONTH, -2);
+    Date expected = calendar.getTime();
+
+    assertEquals(expected, businessCalendar.add(start, new Duration("-5 business hours")));
+  }
+}


Property changes on: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the jbpm-commits mailing list