private DaylightInfo CalculateDaylightInfo(DateTime commuteStart, DateTime commuteEnd, SunCalculator sunCalculator, string timeZoneId) { var daylightInfo = new DaylightInfo(); var sunRise = sunCalculator.CalculateSunRise(commuteStart.Date, timeZoneId); var sunSet = sunCalculator.CalculateSunSet(commuteStart.Date, timeZoneId); var commuteIsAfterSunrise = commuteStart.TimeOfDay >= sunRise.TimeOfDay; var commuteIsBeforeSunSet = commuteEnd.TimeOfDay <= sunSet.TimeOfDay; if (commuteEnd.Date > commuteStart.Date) { // Special case; overlapping midnight. Just assume that it's always dark return daylightInfo; } daylightInfo.IsCurrentlyInDaylight = commuteIsAfterSunrise && commuteIsBeforeSunSet; for (var d = 0; d < DaysInYear; d++) { sunRise = sunCalculator.CalculateSunRise(commuteStart.Date.AddDays(d), timeZoneId); sunSet = sunCalculator.CalculateSunSet(commuteEnd.Date.AddDays(d), timeZoneId); if (commuteStart.TimeOfDay >= sunRise.TimeOfDay && commuteEnd.TimeOfDay <= sunSet.TimeOfDay) { daylightInfo.CommutesInDaylightPerYear++; } if (!daylightInfo.TransitionType.HasValue && DaylightTransitionHappened(sunRise, sunSet, commuteStart, commuteEnd, daylightInfo.IsCurrentlyInDaylight)) { // We need to work out on which edge the transition happened if (commuteIsAfterSunrise != (commuteStart.TimeOfDay >= sunRise.TimeOfDay)) { daylightInfo.NextDaylightTransition = sunRise.AddDays(-1); daylightInfo.TransitionType = DaylightTransition.SunRise; } else if (commuteIsBeforeSunSet != (commuteEnd.TimeOfDay <= sunSet.TimeOfDay)) { daylightInfo.NextDaylightTransition = sunSet.AddDays(-1); daylightInfo.TransitionType = DaylightTransition.SunSet; } else { throw new Exception("something went very wrong"); } } } return daylightInfo; }
public static DaylightInfoModel BuildDaylightInfoModel(DateTime today, DaylightInfo daylightInfo, Commute commuteType, WorkingDays workingDays) { var daysToTransition = 0; DateTime? nextWorkingDayDaylightTransition = null; if (daylightInfo.NextDaylightTransition.HasValue) { var day = today; if (day >= daylightInfo.NextDaylightTransition.Value) { throw new InvalidOperationException(string.Format("daylightInfo.NextDaylightTransition.Value equals {0}; but it should be in the future.", daylightInfo.NextDaylightTransition.Value)); } var days = new List<DateTime>(); while (day < daylightInfo.NextDaylightTransition.Value) { day = day.AddDays(1); days.Add(day); } // Nudge to the first working day, if necessary // TODO: Get rid of the flags variable here var workingDayFlags = new[] { workingDays.HasFlag(WorkingDays.Sunday), workingDays.HasFlag(WorkingDays.Monday), workingDays.HasFlag(WorkingDays.Tuesday), workingDays.HasFlag(WorkingDays.Wednesday), workingDays.HasFlag(WorkingDays.Thursday), workingDays.HasFlag(WorkingDays.Friday), workingDays.HasFlag(WorkingDays.Saturday) }; while (!workingDayFlags[(int)days.Last().DayOfWeek]) { days.Add(days.Last().AddDays(1)); } daysToTransition = days.Count(d => workingDayFlags[(int)d.DayOfWeek]); nextWorkingDayDaylightTransition = days.Last(); } return new DaylightInfoModel { IsCurrentlyInDaylight = daylightInfo.IsCurrentlyInDaylight, PercentOfTheYearInTheDark = GetPercentOfTheYearInTheDark(daylightInfo.CommutesInDaylightPerYear), NextWorkingDayDaylightTransition = nextWorkingDayDaylightTransition, CommuteType = commuteType, NumberOfDaysToTransition = daysToTransition, }; }
public void SetUp() { _daylights = new DaylightInfo { TransitionType = DaylightTransition.SunRise }; _workingDays = WorkingDays.Monday | WorkingDays.Tuesday | WorkingDays.Wednesday | WorkingDays.Thursday | WorkingDays.Friday; }