Adding fractional time to a Calendar

In assisting the refactoring of an application dealing with time, I discovered that the client needs to do the very common thing of adding fractions (hundredths) of hours. Rather than sprinkle bits of math around the code, I decided the prudent thing to do is to create and extention of a Calendar object that can add doubles and BigDecimals.

Examples of this case occur when someone wants to be able to add up an employee's time with a calculator. It is generally easier to use 3.5 for three and a half hours when adding to other time quantities. So, in order to collect input in such a format and add it to a time entity (Calendar) a little bit of effort is in order. Fortuneately, the GregorianCalendar object uses milliseconds for date storage and the math to sum fractions of hours with this is simple.

I am only bothering with extending the GregorianCalendar to add fractional minutes and hours in this case. There probably isn't much use for this in other fields and even doing it with minutes may be overkill. Besides, adding support for other fields is trivial (as the code below demonstrates).

I know this bit of code is pretty trivial but, after digging through tons of code that does string conversions to get the same effect, I decided that this has to be posted somewhere.


import java.math.BigDecimal;
import java.util.GregorianCalendar;

/**
* @author Paul E. Davis
*/
public class TimePlusCalendar extends GregorianCalendar {

  private final static BigDecimal NADA = new BigDecimal(0);
  private final static double D_MULTIPL_HOUR = 60 * 60 * 1000;
  private final static double D_MULTIPL_MIN = 60 * 1000;
  private final static BigDecimal MULTIPL_HOUR =
   new BigDecimal(D_MULTIPL_HOUR);
  private final static BigDecimal MULTIPL_MIN =
   new BigDecimal(D_MULTIPL_MIN);

  private TimePlusCalendar() {
   super();
  }

  public void add(int field, double amount){
    complete();
    long delta;
    switch (field)
    {
      case HOUR :
        delta = (long)(amount * D_MULTIPL_HOUR);
        break;
      case MINUTE :
        delta = (long)(amount * D_MULTIPL_MIN);
        break;
      default :
        throw new IllegalArgumentException("Only Calendar.HOUR " +
          "and Calendar.MINUTE supported for this operation");
    }
    setTimeInMillis(time + delta);
  }
  public void add(int field, BigDecimal amount)
  {
    BigDecimal delta = NADA;
    complete();
    switch (field)
    {
      case HOUR :
        delta = amount.multiply(MULTIPL_HOUR);
        break;
      case MINUTE :
        delta = amount.multiply(MULTIPL_MIN);
        break;
      default :
        throw new IllegalArgumentException("Only Calendar.HOUR " +
          "and Calendar.MINUTE supported for this operation");
    }
    setTimeInMillis(time + delta.longValue());
  }
}


Sponsors:

About willCode4Beer