blob: 9b3b9ac6f41edc0414c12608e62d6eca019d7024 [file] [log] [blame]
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime
{
public class Days360 : ExcelFunction
{
private enum Days360Calctype
{
European,
Us
}
public override CompileResult Execute(IEnumerable<FunctionArgument> arguments, ParsingContext context)
{
ValidateArguments(arguments, 2);
var numDate1 = ArgToDecimal(arguments, 0);
var numDate2 = ArgToDecimal(arguments, 1);
var dt1 = System.DateTime.FromOADate(numDate1);
var dt2 = System.DateTime.FromOADate(numDate2);
var calcType = Days360Calctype.Us;
if (arguments.Count() > 2)
{
var european = ArgToBool(arguments, 2);
if(european) calcType = Days360Calctype.European;
}
var startYear = dt1.Year;
var startMonth = dt1.Month;
var startDay = dt1.Day;
var endYear = dt2.Year;
var endMonth = dt2.Month;
var endDay = dt2.Day;
if (calcType == Days360Calctype.European)
{
if (startDay == 31) startDay = 30;
if (endDay == 31) endDay = 30;
}
else
{
var calendar = new GregorianCalendar();
var nDaysInFeb = calendar.IsLeapYear(dt1.Year) ? 29 : 28;
// If the investment is EOM and (Date1 is the last day of February) and (Date2 is the last day of February), then change D2 to 30.
if (startMonth == 2 && startDay == nDaysInFeb && endMonth == 2 && endDay == nDaysInFeb)
{
endDay = 30;
}
// If the investment is EOM and (Date1 is the last day of February), then change D1 to 30.
if (startMonth == 2 && startDay == nDaysInFeb)
{
startDay = 30;
}
// If D2 is 31 and D1 is 30 or 31, then change D2 to 30.
if (endDay == 31 && (startDay == 30 || startDay == 31))
{
endDay = 30;
}
// If D1 is 31, then change D1 to 30.
if (startDay == 31)
{
startDay = 30;
}
}
var result = (endYear*12*30 + endMonth*30 + endDay) - (startYear*12*30 + startMonth*30 + startDay);
return CreateResult(result, DataType.Integer);
}
private int GetNumWholeMonths(System.DateTime dt1, System.DateTime dt2)
{
var startDate = new System.DateTime(dt1.Year, dt1.Month, 1).AddMonths(1);
var endDate = new System.DateTime(dt2.Year, dt2.Month, 1);
return ((endDate.Year - startDate.Year)*12) + (endDate.Month - startDate.Month);
}
}
}