Index: src/main/java/org/jbpm/pvm/internal/cal/DayPart.java
===================================================================
--- src/main/java/org/jbpm/pvm/internal/cal/DayPart.java	(revision 6130)
+++ src/main/java/org/jbpm/pvm/internal/cal/DayPart.java	(working copy)
@@ -72,6 +72,37 @@
     return end;
   }
   
+  public Date subtract(Date date, long millis, boolean isBusinessTime) {
+	    Date end = null;
+	    
+	    BusinessCalendarImpl businessCalendarImpl = day.getBusinessCalendar();
+	    Calendar calendar = businessCalendarImpl.createCalendar();
+	    calendar.setTime(date);
+	    int hour = calendar.get(Calendar.HOUR_OF_DAY);
+	    int minute = calendar.get(Calendar.MINUTE);
+
+	    long dateMilliseconds = ((hour*60)+minute)*60*1000;
+	    long dayPartStartMilleseconds = ((fromHour*60)+fromMinute)*60*1000;
+	    long millisecondsInThisDayPart = dateMilliseconds - dayPartStartMilleseconds;
+	    	    
+	    if (millis <= millisecondsInThisDayPart) {
+	      end = new Date( date.getTime() - millis);
+	    } else {
+	      long remainderMillis = millis - millisecondsInThisDayPart;
+	      Date dayPartStartDate = new Date(date.getTime() - millis + remainderMillis);
+	      
+	      Object[] result = new Object[2];
+	      day.findPreviousDayPartStart(index, dayPartStartDate, result);
+	      Date previousDayPartStart = (Date) result[0];
+	      DayPart previousDayPart = (DayPart) result[1];
+	      
+	      end = previousDayPart.subtract(previousDayPartStart, remainderMillis, isBusinessTime);
+	    }
+	    
+	    return end;
+	  }
+  
+  
   public boolean isStartAfter(Date date) {
     Calendar calendar = day.getBusinessCalendar().createCalendar();
     calendar.setTime(date);
@@ -85,7 +116,21 @@
            );
   }
 
+  
+  public boolean isEndBefore(Date date) {
+	    Calendar calendar = day.getBusinessCalendar().createCalendar();
+	    calendar.setTime(date);
+	    int hour = calendar.get(Calendar.HOUR_OF_DAY);
+	    int minute = calendar.get(Calendar.MINUTE);
+	    
+	    return ( (toHour<hour)
+	             || ( (toHour==hour)
+	                  && (toMinute<=minute) 
+	                ) 
+	           );
+	  }  
 
+  
   public boolean includes(Date date) {
     Calendar calendar = day.getBusinessCalendar().createCalendar();
     calendar.setTime(date);
@@ -113,6 +158,16 @@
     return calendar.getTime();
   }
   
+  public Date getEndTime(Date date) {
+	    Calendar calendar = day.getBusinessCalendar().createCalendar();
+	    calendar.setTime(date);
+	    calendar.set(Calendar.HOUR_OF_DAY, toHour);
+	    calendar.set(Calendar.MINUTE, toMinute);
+	    calendar.set(Calendar.SECOND, 0);
+	    calendar.set(Calendar.MILLISECOND, 0);
+	    return calendar.getTime();
+  }
+	    
   public Day getDay() {
     return day;
   }
Index: src/main/java/org/jbpm/pvm/internal/cal/BusinessCalendarImpl.java
===================================================================
--- src/main/java/org/jbpm/pvm/internal/cal/BusinessCalendarImpl.java	(revision 6130)
+++ src/main/java/org/jbpm/pvm/internal/cal/BusinessCalendarImpl.java	(working copy)
@@ -55,6 +55,7 @@
   protected long monthInMillis = 30*dayInMillis; 
   protected long yearInMillis = 365*dayInMillis; 
 
+  //TODO: calculate these numbers based on  business 
   protected long businessDayInMillis = 8*hourInMillis; 
   protected long businessWeekInMillis = 40*hourInMillis; 
   protected long businessMonthInMillis = 21*dayInMillis; 
@@ -76,16 +77,27 @@
   }
   
   public Date subtract(Date date, String duration) {
-	if (duration.contains("business")) {
-	  throw new JbpmException("Duedate subtraction not supported for business durations");
-	}
     return subtract(date, new Duration(duration));
   }
 
   public Date subtract(Date date, Duration duration) {
 	Date end = null;
-    long millis = convertToMillis(duration);
-    end = new Date(date.getTime()-millis);
+    if (duration.isBusinessTime()) {
+        DayPart dayPart = findDayPart(date);
+        boolean isInbusinessHours = (dayPart!=null);
+        if (! isInbusinessHours) {
+          Object[] result = new Object[2];
+          Day day = findDay(date);
+          day.findPreviousDayPartStart(day.getDayParts().length, date, result);
+          date = (Date) result[0];
+          dayPart = (DayPart) result[1];
+        }
+        long millis = convertToMillis(duration);
+        end = dayPart.subtract(date, millis, duration.isBusinessTime());
+    } else {	
+	    long millis = convertToMillis(duration);
+	    end = new Date(date.getTime()-millis);
+    }
     if (end.before(Clock.getTime())) {
     	throw new JbpmException("Duedate "+ end+ " in the past");
     }
@@ -163,6 +175,23 @@
     }
     return date;
   }
+  
+  protected Date findStartOfPreviousDay(Date date) {
+	    Calendar calendar = createCalendar();
+	    calendar.setTime(date);
+	    calendar.add(Calendar.DATE, -1);
+	    calendar.set(Calendar.HOUR_OF_DAY, 23);
+	    calendar.set(Calendar.MINUTE, 59);
+	    calendar.set(Calendar.SECOND, 59);
+	    calendar.set(Calendar.MILLISECOND, 999);
+	    date = calendar.getTime();
+	    while(isHoliday(date)) {
+	      calendar.setTime(date);
+	      calendar.add(Calendar.DATE, -1);
+	      date = calendar.getTime();
+	    }
+	    return date;
+	  }  
 
   public Calendar createCalendar() {
     return new GregorianCalendar();
Index: src/main/java/org/jbpm/pvm/internal/cal/Day.java
===================================================================
--- src/main/java/org/jbpm/pvm/internal/cal/Day.java	(revision 6130)
+++ src/main/java/org/jbpm/pvm/internal/cal/Day.java	(working copy)
@@ -54,6 +54,25 @@
       nextDay.findNextDayPartStart(0, date, result);
     }
   }
+  
+  public void findPreviousDayPartStart(int dayPartIndex, Date date, Object[] result) {
+	    // if there is a day part in this day that starts before the given date
+	    if ( (dayParts!=null)
+	         && (dayPartIndex >= 0)
+	       ) {
+	      if (dayParts[dayPartIndex].isEndBefore(date)) {
+	        result[0] = dayParts[dayPartIndex].getEndTime(date);
+	        result[1] = dayParts[dayPartIndex];
+	      } else {
+	    	  findPreviousDayPartStart(dayPartIndex-1, date, result);
+	      }
+	    } else {
+	      // descend recursively
+	      date = businessCalendarImpl.findStartOfPreviousDay(date);
+	      Day previousDay = businessCalendarImpl.findDay(date);
+	      previousDay.findPreviousDayPartStart((previousDay.getDayParts()!=null ? previousDay.getDayParts().length-1 : 0), date, result);
+	    }
+	  }  
 
   public BusinessCalendarImpl getBusinessCalendar() {
     return businessCalendarImpl;
