public DateTime ExpirationDate(int year, int month, string countryCode = "US") { var referenceDay = new DateTime(year, month, 1); var calendar = MyUtils.GetCalendarFromCountryCode(countryCode); int day; referenceDay = referenceDay.AddMonths((int)Rule.ReferenceRelativeMonth); if (Rule.ReferenceDayIsLastBusinessDayOfMonth) { var tmpDay = referenceDay.AddMonths(1).AddDays(-1); while (!calendar.isBusinessDay(tmpDay)) { tmpDay = tmpDay.AddDays(-1); } day = tmpDay.Day; } else if (Rule.ReferenceUsesDays) // we use a fixed number of days from the start of the month { day = Rule.ReferenceDays; } else // we use a number of weeks and then a weekday of that week { if (Rule.ReferenceWeekDayCount == WeekDayCount.Last) //the last week of the month { var tmpDay = referenceDay.AddMonths(1).AddDays(-1); while (tmpDay.DayOfWeek.ToInt() != (int)Rule.ReferenceWeekDay) { tmpDay = tmpDay.AddDays(-1); } day = tmpDay.Day; } else // 1st to 4th week of the month, just loop until we find the right day { var weekCount = 0; while (weekCount < (int)Rule.ReferenceWeekDayCount + 1) { if (referenceDay.DayOfWeek.ToInt() == (int)Rule.ReferenceWeekDay) { weekCount++; } referenceDay = referenceDay.AddDays(1); } day = referenceDay.Day - 1; } } referenceDay = new DateTime(year, month, day).AddMonths((int)Rule.ReferenceRelativeMonth); if (Rule.ReferenceDayMustBeBusinessDay) { while (!calendar.isBusinessDay(referenceDay)) { referenceDay = referenceDay.AddDays(-1); } } switch (Rule.DayType) { case DayType.Business: var daysLeft = Rule.DaysBefore; var daysBack = 0; while (daysLeft > 0) { daysBack++; if (calendar.isBusinessDay(referenceDay.AddDays(-daysBack))) { daysLeft--; } } return(referenceDay.AddDays(-daysBack)); case DayType.Calendar: return(referenceDay.AddDays(-Rule.DaysBefore)); default: return(referenceDay); } }