blob: 429191e5d3f5674198bfac0e778ba884d170bc7e [file] [log] [blame]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using OfficeOpenXml.Utils;
namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime
{
public class Workday : ExcelFunction
{
public override CompileResult Execute(IEnumerable<FunctionArgument> arguments, ParsingContext context)
{
ValidateArguments(arguments, 2);
var startDate = System.DateTime.FromOADate(ArgToInt(arguments, 0));
var nWorkDays = ArgToInt(arguments, 1);
var resultDate = System.DateTime.MinValue;
var workdaysCounted = 0;
var tmpDate = startDate;
// first move forward to the first monday
while (tmpDate.DayOfWeek != DayOfWeek.Monday && (nWorkDays - workdaysCounted) > 0)
{
if (!IsHoliday(tmpDate)) workdaysCounted++;
tmpDate = tmpDate.AddDays(1);
}
// then calculate whole weeks
var nWholeWeeks = (nWorkDays - workdaysCounted) / 5;
tmpDate = tmpDate.AddDays(nWholeWeeks * 7);
workdaysCounted += nWholeWeeks * 5;
// calculate the rest
while (workdaysCounted < nWorkDays)
{
tmpDate = tmpDate.AddDays(1);
if (!IsHoliday(tmpDate)) workdaysCounted++;
}
resultDate = AdjustResultWithHolidays(tmpDate, arguments);
return CreateResult(resultDate.ToOADate(), DataType.Date);
}
private System.DateTime AdjustResultWithHolidays(System.DateTime resultDate,
IEnumerable<FunctionArgument> arguments)
{
if (arguments.Count() == 2) return resultDate;
var holidays = arguments.ElementAt(2).Value as IEnumerable<FunctionArgument>;
if (holidays != null)
{
foreach (var arg in holidays)
{
if (ConvertUtil.IsNumeric(arg.Value))
{
var dateSerial = ConvertUtil.GetValueDouble(arg.Value);
var holidayDate = System.DateTime.FromOADate(dateSerial);
if (!IsHoliday(holidayDate))
{
resultDate = resultDate.AddDays(1);
}
}
}
}
else
{
var range = arguments.ElementAt(2).Value as ExcelDataProvider.IRangeInfo;
if (range != null)
{
foreach (var cell in range)
{
if (ConvertUtil.IsNumeric(cell.Value))
{
var dateSerial = ConvertUtil.GetValueDouble(cell.Value);
var holidayDate = System.DateTime.FromOADate(dateSerial);
if (!IsHoliday(holidayDate))
{
resultDate = resultDate.AddDays(1);
}
}
}
}
}
return resultDate;
}
private bool IsHoliday(System.DateTime date)
{
return date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
}
}
}