| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Text; | |
| using OfficeOpenXml.FormulaParsing.ExpressionGraph; | |
| namespace OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime | |
| { | |
| public class IsoWeekNum : ExcelFunction | |
| { | |
| public override CompileResult Execute(IEnumerable<FunctionArgument> arguments, ParsingContext context) | |
| { | |
| ValidateArguments(arguments, 1); | |
| var dateInt = ArgToInt(arguments, 0); | |
| var date = System.DateTime.FromOADate(dateInt); | |
| return CreateResult(WeekNumber(date), DataType.Integer); | |
| } | |
| /// <summary> | |
| /// This implementation was found on http://stackoverflow.com/questions/1285191/get-week-of-date-from-linq-query | |
| /// </summary> | |
| /// <param name="fromDate"></param> | |
| /// <returns></returns> | |
| private int WeekNumber(System.DateTime fromDate) | |
| { | |
| // Get jan 1st of the year | |
| var startOfYear = fromDate.AddDays(-fromDate.Day + 1).AddMonths(-fromDate.Month + 1); | |
| // Get dec 31st of the year | |
| var endOfYear = startOfYear.AddYears(1).AddDays(-1); | |
| // ISO 8601 weeks start with Monday | |
| // The first week of a year includes the first Thursday | |
| // DayOfWeek returns 0 for sunday up to 6 for saterday | |
| int[] iso8601Correction = { 6, 7, 8, 9, 10, 4, 5 }; | |
| int nds = fromDate.Subtract(startOfYear).Days + iso8601Correction[(int)startOfYear.DayOfWeek]; | |
| int wk = nds / 7; | |
| switch (wk) | |
| { | |
| case 0: | |
| // Return weeknumber of dec 31st of the previous year | |
| return WeekNumber(startOfYear.AddDays(-1)); | |
| case 53: | |
| // If dec 31st falls before thursday it is week 01 of next year | |
| if (endOfYear.DayOfWeek < DayOfWeek.Thursday) | |
| return 1; | |
| return wk; | |
| default: return wk; | |
| } | |
| } | |
| } | |
| } |