private static DateTime CalculateEscalationDatePrivate(string zoneName, DateTime startDate, int seconds) { WorkflowManagementServer mngServer = null; try { mngServer = new WorkflowManagementServer("localhost", 5555); //fairly safe to do this as inline function runs on K2 Server. mngServer.Open(); //http://www.k2underground.com/forums/p/8275/31827.aspx mngServer.ZoneLoad(zoneName); return(mngServer.ZoneCalculateEvent(zoneName, startDate, new TimeSpan(0, 0, 0, seconds))); } catch (Exception ex) { //more detailed error in the k2server logs throw new Exception(string.Format("Error: {0}{1}", ex.Message, ex.StackTrace), ex); } finally { if (mngServer != null) { if (mngServer.Connection != null) { mngServer.Connection.Dispose(); } mngServer = null; } } }
private void UserCalculateEvent() { string FQN = base.GetStringProperty(Constants.SOProperties.WorkingHoursConfiguration.FQN, true); string Start = base.GetStringProperty(Constants.SOProperties.WorkingHoursConfiguration.StartDateTime, true); int DurationHours = base.GetIntProperty(Constants.SOProperties.WorkingHoursConfiguration.DurationHours); int DurationMinutes = base.GetIntProperty(Constants.SOProperties.WorkingHoursConfiguration.DurationMinutes); int DurationSeconds = base.GetIntProperty(Constants.SOProperties.WorkingHoursConfiguration.DurationSeconds); base.ServiceBroker.Service.ServiceObjects[0].Properties.InitResultTable(); DataTable results = base.ServiceBroker.ServicePackage.ResultTable; WorkflowManagementServer mngServer = this.ServiceBroker.K2Connection.GetConnection <WorkflowManagementServer>(); using (mngServer.Connection) { TimeSpan Duration = new TimeSpan(DurationHours, DurationMinutes, DurationSeconds); DateTime dt; if (!DateTime.TryParse(Start, out dt)) { throw new ApplicationException(Resources.DateNotValid); } AvailabilityZone zone = mngServer.ZoneLoad(mngServer.UserGetZone(FQN)); if (zone.AvailabilityHoursList == null || zone.AvailabilityHoursList.Count == 0) { throw new ApplicationException(Resources.WorkingHoursNotSet); } DataRow dRow = results.NewRow(); dRow[Constants.SOProperties.WorkingHoursConfiguration.FinishDateTime] = mngServer.UserCalculateEvent(FQN, dt, Duration); results.Rows.Add(dRow); } }
private void LoadZone() { string ZoneName = base.GetStringProperty(Constants.SOProperties.WorkingHoursConfiguration.ZoneName, true); base.ServiceBroker.Service.ServiceObjects[0].Properties.InitResultTable(); DataTable results = base.ServiceBroker.ServicePackage.ResultTable; WorkflowManagementServer mngServer = this.ServiceBroker.K2Connection.GetConnection <WorkflowManagementServer>(); using (mngServer.Connection) { if (!mngServer.ZoneExists(ZoneName)) { throw new ApplicationException(Resources.ZoneDoesNotExist + ZoneName + "."); } else { AvailabilityZone aZone = mngServer.ZoneLoad(ZoneName); DataRow dRow = results.NewRow(); dRow[Constants.SOProperties.WorkingHoursConfiguration.ZoneName] = aZone.ZoneName; dRow[Constants.SOProperties.WorkingHoursConfiguration.DefaultZone] = aZone.DefaultZone; dRow[Constants.SOProperties.WorkingHoursConfiguration.GMTOffset] = aZone.ZoneGMTOffset; dRow[Constants.SOProperties.WorkingHoursConfiguration.Description] = aZone.ZoneDescription; results.Rows.Add(dRow); } } }
private static DateTime CalculateEscalationDatePrivate(string zoneName, DateTime startDate, int seconds) { WorkflowManagementServer mngServer = null; try { mngServer = new WorkflowManagementServer("localhost", 5555); //fairly safe to do this as inline function runs on K2 Server. mngServer.Open(); //http://www.k2underground.com/forums/p/8275/31827.aspx mngServer.ZoneLoad(zoneName); return mngServer.ZoneCalculateEvent(zoneName, startDate, new TimeSpan(0, 0, 0, seconds)); } catch (Exception ex) { //more detailed error in the k2server logs throw new Exception(string.Format("Error: {0}{1}", ex.Message, ex.StackTrace), ex); } finally { if (mngServer != null) { if (mngServer.Connection != null) { mngServer.Connection.Dispose(); } mngServer = null; } } }
private void SaveZone() { string CurrentZoneName = base.GetStringProperty(Constants.SOProperties.WorkingHoursConfiguration.ZoneName, true); string NewZoneName = base.GetStringProperty(Constants.SOProperties.WorkingHoursConfiguration.NewZoneName); Property DescriptionProperty = ServiceBroker.Service.ServiceObjects[0].Properties[Constants.SOProperties.WorkingHoursConfiguration.Description]; Property GMTOffsetProperty = ServiceBroker.Service.ServiceObjects[0].Properties[Constants.SOProperties.WorkingHoursConfiguration.GMTOffset]; int GmtOffSet = base.GetIntProperty(Constants.SOProperties.WorkingHoursConfiguration.GMTOffset); bool DefaultZone = base.GetBoolProperty(Constants.SOProperties.WorkingHoursConfiguration.DefaultZone); WorkflowManagementServer mngServer = new WorkflowManagementServer(); using (mngServer.CreateConnection()) { mngServer.Open(BaseAPIConnectionString); if (!String.IsNullOrEmpty(NewZoneName) && !Helper.SpecialCharactersExist(NewZoneName)) { throw new ApplicationException(Constants.ErrorMessages.SpecialCharactersAreNotAllowed); } else if (!String.IsNullOrEmpty(NewZoneName) && mngServer.ZoneExists(NewZoneName)) { throw new ApplicationException(Constants.ErrorMessages.ZoneExists + NewZoneName + "."); } else if (!mngServer.ZoneExists(CurrentZoneName)) { throw new ApplicationException(Constants.ErrorMessages.ZoneDoesNotExist + CurrentZoneName + "."); } else if (GmtOffSet > 13 || GmtOffSet < -13) { throw new ApplicationException(Constants.ErrorMessages.GMTOffSetValidationFailed); } else { AvailabilityZone aZone = mngServer.ZoneLoad(CurrentZoneName); aZone.ZoneName = String.IsNullOrEmpty(NewZoneName) ? CurrentZoneName : NewZoneName; if ((DescriptionProperty.Value != null) || (DescriptionProperty.IsClear)) { aZone.ZoneDescription = DescriptionProperty.Value == null ? String.Empty : DescriptionProperty.Value as string; } if ((GmtOffSet != 0) || (GMTOffsetProperty.IsClear)) { aZone.ZoneGMTOffset = GmtOffSet; } aZone.DefaultZone = DefaultZone; //even if the value is false, you cannot make a zone nonDefault without setting other zone to default mngServer.ZoneSave(CurrentZoneName, aZone); } } }
private void ZoneCalculateEvent() { string ZoneName = base.GetStringProperty(Constants.SOProperties.WorkingHoursConfiguration.ZoneName, true); string Start = base.GetStringProperty(Constants.SOProperties.WorkingHoursConfiguration.StartDateTime, true); int DurationHours = base.GetIntProperty(Constants.SOProperties.WorkingHoursConfiguration.DurationHours); int DurationMinutes = base.GetIntProperty(Constants.SOProperties.WorkingHoursConfiguration.DurationMinutes); int DurationSeconds = base.GetIntProperty(Constants.SOProperties.WorkingHoursConfiguration.DurationSeconds); base.ServiceBroker.Service.ServiceObjects[0].Properties.InitResultTable(); DataTable results = base.ServiceBroker.ServicePackage.ResultTable; WorkflowManagementServer mngServer = new WorkflowManagementServer(); using (mngServer.CreateConnection()) { mngServer.Open(BaseAPIConnectionString); if (!mngServer.ZoneExists(ZoneName)) { throw new ApplicationException(Constants.ErrorMessages.ZoneDoesNotExist + ZoneName + "."); } else { TimeSpan Duration = new TimeSpan(DurationHours, DurationMinutes, DurationSeconds); DateTime dt; if (!DateTime.TryParse(Start, out dt)) { throw new ApplicationException(Constants.ErrorMessages.DateNotValid); } AvailabilityZone zone = mngServer.ZoneLoad(ZoneName); if (zone.AvailabilityHoursList == null || zone.AvailabilityHoursList.Count == 0) { throw new ApplicationException(Constants.ErrorMessages.WorkingHoursNotSet); } DataRow dRow = results.NewRow(); dRow[Constants.SOProperties.WorkingHoursConfiguration.FinishDateTime] = mngServer.ZoneCalculateEvent(ZoneName, dt, Duration); results.Rows.Add(dRow); } } }
private void LoadZone() { string ZoneName = base.GetStringProperty(Constants.SOProperties.WorkingHoursConfiguration.ZoneName, true); base.ServiceBroker.Service.ServiceObjects[0].Properties.InitResultTable(); DataTable results = base.ServiceBroker.ServicePackage.ResultTable; WorkflowManagementServer mngServer = new WorkflowManagementServer(); using (mngServer.CreateConnection()) { mngServer.Open(BaseAPIConnectionString); if (!mngServer.ZoneExists(ZoneName)) { throw new ApplicationException(Constants.ErrorMessages.ZoneDoesNotExist + ZoneName + "."); } else { AvailabilityZone aZone = mngServer.ZoneLoad(ZoneName); DataRow dRow = results.NewRow(); dRow[Constants.SOProperties.WorkingHoursConfiguration.ZoneName] = aZone.ZoneName; dRow[Constants.SOProperties.WorkingHoursConfiguration.DefaultZone] = aZone.DefaultZone; dRow[Constants.SOProperties.WorkingHoursConfiguration.GMTOffset] = aZone.ZoneGMTOffset; dRow[Constants.SOProperties.WorkingHoursConfiguration.Description] = aZone.ZoneDescription; results.Rows.Add(dRow); } } }
/// <summary> /// Check that the local K2 Server has a valid set of working hours for this test. /// </summary> private void ValidateWorkingHours() { WorkflowManagementServer mngServer = new WorkflowManagementServer("localhost", 5555); mngServer.Open(); AvailabilityZone zone = mngServer.ZoneLoad(workingHoursZoneName); List<AvailabilityDate> specialDates = zone.AvailabilityDateList.Where(x => x.IsNonWorkDate == false).ToList(); if (specialDates.Count > 2) Assert.Fail("Too many special dates"); List<AvailabilityDate> exceptionDates = zone.AvailabilityDateList.Where(x => x.IsNonWorkDate == true).ToList(); if (exceptionDates.Count > 2) Assert.Fail("Too many exception dates"); if (specialDates.Where(x => x.WorkDate == new DateTime(2011, 06, 30, 09, 00, 00) && x.Duration == new TimeSpan(3, 0, 0)).ToList().Count != 1) Assert.Fail("Problem finding special date June 30th 2011 09:00 - 12:00"); if (specialDates.Where(x => x.WorkDate == new DateTime(2011, 03, 11, 09, 00, 00) && x.Duration == new TimeSpan(3, 0, 0)).ToList().Count != 1) Assert.Fail("Problem finding special date March 11th 2011 09:00 - 12:00"); if (exceptionDates.Where(x => x.WorkDate == new DateTime(2011, 12, 26)).ToList().Count != 1) Assert.Fail("Problem finding exception date December 26th 2011"); if (exceptionDates.Where(x => x.WorkDate == new DateTime(2012, 1, 2)).ToList().Count != 1) Assert.Fail("Problem finding exception date Jan 2nd 2012"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Monday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Monday 9am - 12pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Tuesday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Tuesday 9am - 12pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Wednesday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Wednesday 9am - 12pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Thursday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Thursday 9am - 12pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Friday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Friday 9am - 12pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Monday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Monday 1pm - 5pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Tuesday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Tuesday 1pm - 5pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Wednesday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Wednesday 1pm - 5pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Thursday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Thursday 1pm - 5pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Friday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) Assert.Fail("Problem with Friday 1pm - 5pm working hours"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Saturday).ToList().Count > 0) Assert.Fail("Found working hours on Saturday where there should be none"); if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Sunday).ToList().Count > 0) Assert.Fail("Found working hours on Sunday wherer there should be none"); mngServer.Connection.Close(); mngServer.Connection.Dispose(); }
/// <summary> /// Check that the local K2 Server has a valid set of working hours for this test. /// </summary> private void ValidateWorkingHours() { WorkflowManagementServer mngServer = new WorkflowManagementServer("localhost", 5555); mngServer.Open(); AvailabilityZone zone = mngServer.ZoneLoad(workingHoursZoneName); List <AvailabilityDate> specialDates = zone.AvailabilityDateList.Where(x => x.IsNonWorkDate == false).ToList(); if (specialDates.Count > 2) { Assert.Fail("Too many special dates"); } List <AvailabilityDate> exceptionDates = zone.AvailabilityDateList.Where(x => x.IsNonWorkDate == true).ToList(); if (exceptionDates.Count > 2) { Assert.Fail("Too many exception dates"); } if (specialDates.Where(x => x.WorkDate == new DateTime(2011, 06, 30, 09, 00, 00) && x.Duration == new TimeSpan(3, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem finding special date June 30th 2011 09:00 - 12:00"); } if (specialDates.Where(x => x.WorkDate == new DateTime(2011, 03, 11, 09, 00, 00) && x.Duration == new TimeSpan(3, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem finding special date March 11th 2011 09:00 - 12:00"); } if (exceptionDates.Where(x => x.WorkDate == new DateTime(2011, 12, 26)).ToList().Count != 1) { Assert.Fail("Problem finding exception date December 26th 2011"); } if (exceptionDates.Where(x => x.WorkDate == new DateTime(2012, 1, 2)).ToList().Count != 1) { Assert.Fail("Problem finding exception date Jan 2nd 2012"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Monday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Monday 9am - 12pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Tuesday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Tuesday 9am - 12pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Wednesday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Wednesday 9am - 12pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Thursday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Thursday 9am - 12pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Friday && x.Duration == new TimeSpan(3, 0, 0) && x.TimeOfDay == new TimeSpan(9, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Friday 9am - 12pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Monday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Monday 1pm - 5pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Tuesday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Tuesday 1pm - 5pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Wednesday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Wednesday 1pm - 5pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Thursday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Thursday 1pm - 5pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Friday && x.Duration == new TimeSpan(4, 0, 0) && x.TimeOfDay == new TimeSpan(13, 0, 0)).ToList().Count != 1) { Assert.Fail("Problem with Friday 1pm - 5pm working hours"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Saturday).ToList().Count > 0) { Assert.Fail("Found working hours on Saturday where there should be none"); } if (zone.AvailabilityHoursList.Where(x => x.WorkDay == DayOfWeek.Sunday).ToList().Count > 0) { Assert.Fail("Found working hours on Sunday wherer there should be none"); } mngServer.Connection.Close(); mngServer.Connection.Dispose(); }
private static TimeSpan WorkingHoursDateDiff(string zoneName, DateTime startDate, DateTime endDate) { TimeSpan workedHours = new TimeSpan(0); WorkflowManagementServer mngServer = new WorkflowManagementServer("localhost", 5555); //safe to do this as inline function runs on K2 Server. mngServer.Open(); //let K2 catch errors here. AvailabilityZone zone = new AvailabilityZone(); if (string.IsNullOrEmpty(zoneName)) //use default working hours if not specified. { try { zoneName = mngServer.ZoneGetDefault(); } catch (Exception ex) { throw new Exception("Couldn't get default working hours because: " + ex.Message, ex); } } try { zone = mngServer.ZoneLoad(zoneName); } catch (Exception ex) { throw new Exception("Couldn't get working hours named: '" + zoneName + "' Because: " + ex.Message, ex); } DateTime currentZoneDate = startDate.Date; bool carryOn = true; while (carryOn) { List<AvailabilityHours> singleDayListOfHours = zone.AvailabilityHoursList.Where(x => x.WorkDay == currentZoneDate.DayOfWeek).ToList(); foreach (AvailabilityHours hours in singleDayListOfHours) { //quickly filter out exception dates :) if (zone.AvailabilityDateList.Count(x => x.IsNonWorkDate == true && x.WorkDate.Date == currentZoneDate.Date) > 0) continue; DateTime endOfSection = new DateTime(currentZoneDate.Year, currentZoneDate.Month, currentZoneDate.Day); DateTime startOfSection = new DateTime(currentZoneDate.Year, currentZoneDate.Month, currentZoneDate.Day); startOfSection = startOfSection.Add(hours.TimeOfDay); endOfSection = startOfSection.Add(hours.Duration); if ((startDate >= startOfSection && startDate <= endOfSection) && (endDate <= endOfSection && endDate >= startOfSection)) //starts inside, ends inside { workedHours += endDate - startDate; } if (startDate < startOfSection && endDate > endOfSection) // starts outside, ends outside { workedHours += endOfSection - startOfSection; } if (startDate < startOfSection && (endDate <= endOfSection && endDate >= startOfSection)) //starts outside, ends inside { workedHours += endDate - startOfSection; } if ((startDate >= startOfSection && startDate <= endOfSection) && endDate > endOfSection) //starts inside, ends outside { workedHours += endOfSection - startDate; } } //special dates require more work - basically duplicate the logic above but decrement worked hours for every special day foreach (AvailabilityDate specialDate in zone.AvailabilityDateList.Where(x => x.WorkDate.Date == currentZoneDate.Date && x.IsNonWorkDate == false)) { DateTime specialDateStart = specialDate.WorkDate; DateTime specialDateEnd = specialDate.WorkDate + specialDate.Duration; if ((startDate >= specialDateStart && startDate <= specialDateEnd) && (endDate <= specialDateEnd && endDate >= specialDateStart)) //starts inside, ends inside { workedHours -= endDate - startDate; } if (startDate < specialDateStart && endDate > specialDateEnd) // starts outside, ends outside { workedHours -= specialDateEnd - specialDateStart; } if (startDate < specialDateStart && (endDate <= specialDateEnd && endDate >= specialDateStart)) //starts outside, ends inside { workedHours -= endDate - specialDateStart; } if ((startDate >= specialDateStart && startDate <= specialDateEnd) && endDate > specialDateEnd) //starts inside, ends outside { workedHours -= specialDateEnd - startDate; } } if (currentZoneDate > endDate) carryOn = false; currentZoneDate = currentZoneDate.AddDays(1); } mngServer.Connection.Close(); mngServer.Connection.Dispose(); return workedHours; }
private static TimeSpan WorkingHoursDateDiff(string zoneName, DateTime startDate, DateTime endDate) { TimeSpan workedHours = new TimeSpan(0); WorkflowManagementServer mngServer = new WorkflowManagementServer("localhost", 5555); //safe to do this as inline function runs on K2 Server. mngServer.Open(); //let K2 catch errors here. AvailabilityZone zone = new AvailabilityZone(); if (string.IsNullOrEmpty(zoneName)) //use default working hours if not specified. { try { zoneName = mngServer.ZoneGetDefault(); } catch (Exception ex) { throw new Exception("Couldn't get default working hours because: " + ex.Message, ex); } } try { zone = mngServer.ZoneLoad(zoneName); } catch (Exception ex) { throw new Exception("Couldn't get working hours named: '" + zoneName + "' Because: " + ex.Message, ex); } DateTime currentZoneDate = startDate.Date; bool carryOn = true; while (carryOn) { List <AvailabilityHours> singleDayListOfHours = zone.AvailabilityHoursList.Where(x => x.WorkDay == currentZoneDate.DayOfWeek).ToList(); foreach (AvailabilityHours hours in singleDayListOfHours) { //quickly filter out exception dates :) if (zone.AvailabilityDateList.Count(x => x.IsNonWorkDate == true && x.WorkDate.Date == currentZoneDate.Date) > 0) { continue; } DateTime endOfSection = new DateTime(currentZoneDate.Year, currentZoneDate.Month, currentZoneDate.Day); DateTime startOfSection = new DateTime(currentZoneDate.Year, currentZoneDate.Month, currentZoneDate.Day); startOfSection = startOfSection.Add(hours.TimeOfDay); endOfSection = startOfSection.Add(hours.Duration); if ((startDate >= startOfSection && startDate <= endOfSection) && (endDate <= endOfSection && endDate >= startOfSection)) //starts inside, ends inside { workedHours += endDate - startDate; } if (startDate < startOfSection && endDate > endOfSection) // starts outside, ends outside { workedHours += endOfSection - startOfSection; } if (startDate < startOfSection && (endDate <= endOfSection && endDate >= startOfSection)) //starts outside, ends inside { workedHours += endDate - startOfSection; } if ((startDate >= startOfSection && startDate <= endOfSection) && endDate > endOfSection) //starts inside, ends outside { workedHours += endOfSection - startDate; } } //special dates require more work - basically duplicate the logic above but decrement worked hours for every special day foreach (AvailabilityDate specialDate in zone.AvailabilityDateList.Where(x => x.WorkDate.Date == currentZoneDate.Date && x.IsNonWorkDate == false)) { DateTime specialDateStart = specialDate.WorkDate; DateTime specialDateEnd = specialDate.WorkDate + specialDate.Duration; if ((startDate >= specialDateStart && startDate <= specialDateEnd) && (endDate <= specialDateEnd && endDate >= specialDateStart)) //starts inside, ends inside { workedHours -= endDate - startDate; } if (startDate < specialDateStart && endDate > specialDateEnd) // starts outside, ends outside { workedHours -= specialDateEnd - specialDateStart; } if (startDate < specialDateStart && (endDate <= specialDateEnd && endDate >= specialDateStart)) //starts outside, ends inside { workedHours -= endDate - specialDateStart; } if ((startDate >= specialDateStart && startDate <= specialDateEnd) && endDate > specialDateEnd) //starts inside, ends outside { workedHours -= specialDateEnd - startDate; } } if (currentZoneDate > endDate) { carryOn = false; } currentZoneDate = currentZoneDate.AddDays(1); } mngServer.Connection.Close(); mngServer.Connection.Dispose(); return(workedHours); }