/// <summary> /// Gets the time. /// </summary> /// <param name="date">The date.</param> /// <param name="calendar">The calendar.</param> /// <returns>System.Nullable{DateTime}.</returns> private static DateTime? GetTime(DateTime date, ICalendar calendar) { if (calendar == null || calendar.WorkingIntervals == null || !calendar.WorkingIntervals.Any()) { return date; } var day = date.DayOfWeek; var skipInterval = false; foreach (var item in calendar.WorkingIntervals.OrderBy(x => x.StartDate).Where(x => x.Weekday == day.ToString())) { if (!item.StartDate.HasValue) continue; if (calendar.WorkingExceptions != null) { var startDate = new DateTime(date.Year, date.Month, date.Day, item.StartDate.Value.Hour, item.StartDate.Value.Minute, 0); var finishDateHour = 0; var finishDateMinute = 0; if (item.FinishDate != null) { finishDateHour = item.FinishDate.Value.Hour; finishDateMinute = item.FinishDate.Value.Minute; } var finishDate = new DateTime(date.Date.Year, date.Date.Month, date.Date.Day, finishDateHour, finishDateMinute, 0); var workingInterval = new DateTimeInterval(startDate, finishDate); var intersectedExceptions = new List<DateTimeInterval>(); foreach (var exception in calendar.WorkingExceptions) { if (exception.StartDate.HasValue && exception.FinishDate.HasValue) { var compareResult = workingInterval.Compare(exception.StartDate.Value, exception.FinishDate.Value); switch (compareResult) { case Interposition.Inside: skipInterval = true; break; case Interposition.IntersectRight: case Interposition.IntersectLeft: case Interposition.Contains: intersectedExceptions.Add(new DateTimeInterval(exception.StartDate.Value, exception.FinishDate.Value)); break; } } if (skipInterval) break; } if (intersectedExceptions.Count > 0) { for (var i = 0; i < intersectedExceptions.Count; i++) { //объеденить пересекающиеся между собой исключения for (var j = i + 1; j < intersectedExceptions.Count; j++) { var uniteResult = intersectedExceptions[i].Unite(intersectedExceptions[j]); if (uniteResult != null) { //remove united items intersectedExceptions.Remove(intersectedExceptions[j]); intersectedExceptions.Remove(intersectedExceptions[i]); //insert united result instead intersectedExceptions.Insert(i, uniteResult); } } } // единственное исключение с которым осталось сравнить рабочее время. var resultException = intersectedExceptions.OrderBy(exc => exc.StartDate).First(); switch (workingInterval.Compare(resultException)) { case Interposition.Inside: skipInterval = true; break; case Interposition.IntersectRight: return resultException.FinishDate; default: return workingInterval.StartDate; } } } if (skipInterval == false) return date.Date + item.StartDate.Value.TimeOfDay; skipInterval = false; } return null; }
private static ICalendarWorkingException GetWorkingException(DateTime date, ICalendar calendar, List<ICalendarWorkingInterval> workingIntervals, FrequencyPatternType pattern = FrequencyPatternType.Monthly) { if (calendar == null || !calendar.WorkingExceptions.Any() || workingIntervals == null || !workingIntervals.Any()) return null; foreach (var item in workingIntervals) { if (!item.StartDate.HasValue) continue; var startDate = new DateTime(date.Year, date.Month, date.Day, item.StartDate.Value.Hour, item.StartDate.Value.Minute, 0); var finishDateHour = 0; var finishDateMinute = 0; if (item.FinishDate.HasValue) { finishDateHour = item.FinishDate.Value.Hour; finishDateMinute = item.FinishDate.Value.Minute; } var finishDate = new DateTime(date.Date.Year, date.Date.Month, date.Date.Day, finishDateHour, finishDateMinute, 0); var workingInterval = new DateTimeInterval(startDate, finishDate); foreach (var exception in calendar.WorkingExceptions.Where(x => x.StartDate.HasValue && x.FinishDate.HasValue && (x.FinishDate.Value > x.StartDate.Value))) { var compareResult = workingInterval.Compare(exception.StartDate.Value, exception.FinishDate.Value); switch (compareResult) { case Interposition.Inside: case Interposition.IntersectRight: case Interposition.IntersectLeft: return pattern == FrequencyPatternType.Daily ? null : exception; case Interposition.Contains: return exception; } } } return null; }