final ParameterCallback parameters)
throws EvaluationException
{
if (parameters.getParameterCount() != 3)
{
throw new EvaluationException(LibFormulaErrorValue.ERROR_ARGUMENTS_VALUE);
}
final TypeRegistry typeRegistry = context.getTypeRegistry();
final Date date1 = typeRegistry.convertToDate
(parameters.getType(0), parameters.getValue(0));
final Date date2 = typeRegistry.convertToDate
(parameters.getType(1), parameters.getValue(1));
final String formatCode = typeRegistry.convertToText
(parameters.getType(2), parameters.getValue(2));
if (date1 == null || date2 == null || formatCode == null || "".equals(
formatCode))
{
throw new EvaluationException(
LibFormulaErrorValue.ERROR_INVALID_ARGUMENT_VALUE);
}
final LocalizationContext localizationContext = context.getLocalizationContext();
final TimeZone timeZone = localizationContext.getTimeZone();
final Locale locale = localizationContext.getLocale();
final GregorianCalendar calandar1 =
new GregorianCalendar(timeZone, locale);
calandar1.setTime(date1);
final GregorianCalendar calandar2 =
new GregorianCalendar(timeZone, locale);
calandar2.setTime(date2);
int res;
if (DateDifFunction.YEARS_CODE.equals(formatCode))
{
res = calandar2.get(Calendar.YEAR) - calandar1.get(Calendar.YEAR);
}
else if (DateDifFunction.MONTHS_CODE.equals(formatCode))
{
final int month1 = calandar1.get(Calendar.MONTH);
final int month2 = calandar2.get(Calendar.MONTH);
final int year1 = calandar1.get(Calendar.YEAR);
final int year2 = calandar2.get(Calendar.YEAR);
res = (year2 - year1) * 12 +
month2 - month1;
}
else if (DateDifFunction.DAYS_IGNORING_MONTHS_YEARS.equals(formatCode))
{
// The number of days between Date1 and Date2, as if Date1 and
// Date2 were in the same month and the same year.
// Not sure what happens to leap years, so this solution may be invalid.
calandar1.set(Calendar.YEAR, calandar2.get(Calendar.YEAR));
calandar1.set(Calendar.MONTH, calandar2.get(Calendar.MONTH));
res = calandar2.get(Calendar.DAY_OF_MONTH) -
calandar1.get(Calendar.DAY_OF_MONTH);
}
else if (DateDifFunction.DAYS_CODE.equals(formatCode))
{
final int dayOfYear1 = calandar1.get(Calendar.DAY_OF_YEAR);
final int dayOfYear2 = calandar2.get(Calendar.DAY_OF_YEAR);
final int year1 = calandar1.get(Calendar.YEAR);
final int year2 = calandar2.get(Calendar.YEAR);
final GregorianCalendar workingCalandar =
new GregorianCalendar(timeZone, locale);
res = dayOfYear2 - dayOfYear1;
// run through the inner years, without counting the border years
// Always run from the lower to the higher, so that we prevent infinite
// loops ..
final int targetYear = Math.max(year1, year2);
for (int i = Math.min(year1, year2); i < targetYear; i++)
{
workingCalandar.set(Calendar.YEAR, i);
res += workingCalandar.getActualMaximum(Calendar.DAY_OF_YEAR);
}
}
else if (DateDifFunction.MONTHS_IGNORING_YEARS.equals(formatCode))
{
final int month1 = calandar1.get(Calendar.MONTH);
final int month2 = calandar2.get(Calendar.MONTH);
res = month2 - month1;
}
else if (DateDifFunction.DAYS_IGNORING_YEARS.equals(formatCode))
{
//Isn't that a stupid case? How could we count the days while ignoring
//how much days there are in each months without using the year?
// The number of days between Date1 and Date2, as if Date1 and Date2
// were in the same year.
// Not sure what happens to leap years, so this solution may be invalid.
calandar1.set(Calendar.YEAR, calandar2.get(Calendar.YEAR));
final int dayOne = calandar1.get(Calendar.DAY_OF_YEAR);
final int dayTwo = calandar2.get(Calendar.DAY_OF_YEAR);
res = Math.abs(dayOne - dayTwo);
}
else
{
throw new EvaluationException(
LibFormulaErrorValue.ERROR_INVALID_ARGUMENT_VALUE);
}
if (res < 0)
{
throw new EvaluationException(
LibFormulaErrorValue.ERROR_INVALID_ARGUMENT_VALUE);
}
return new TypeValuePair(NumberType.GENERIC_NUMBER, new Integer(res));
}