private static DateTime GetPreviousTradingDay(List <CompiledScheduleTimeInterval> compiledSchedule, CompiledScheduleTimeInterval currentInterval, DateTime currentDateTime) { if (currentInterval.Enabled()) { return(currentDateTime.Date); } var timestampBeforeCurrentIntervalStart = currentInterval.Start.AddTicks(-1); // search for the interval just before the current interval started var previousInterval = compiledSchedule .Where(x => IsBetween(timestampBeforeCurrentIntervalStart, x.Start, x.End)) .OrderByDescending(x => x.Schedule.Rank) .FirstOrDefault(); // if trading was enabled, then at that moment was the last trading day if (previousInterval.Enabled()) { return(timestampBeforeCurrentIntervalStart.Date); } // if no, there was one more disabled interval and we should go next return(GetPreviousTradingDay(compiledSchedule, previousInterval, previousInterval.Start)); }
private static DateTime GetNextTradingDay(List <CompiledScheduleTimeInterval> compiledSchedule, CompiledScheduleTimeInterval currentInterval, DateTime currentDateTime, DateTime lastTradingDay) { // search for the interval right after the current interval finished var ordered = compiledSchedule .Where(x => x.End > (currentInterval?.End ?? currentDateTime) || currentInterval != null && x.Schedule.Rank > currentInterval.Schedule.Rank && x.End > currentInterval.End) .OrderBy(x => x.Start) .ThenByDescending(x => x.Schedule.Rank) .ToList(); var nextInterval = ordered.FirstOrDefault(); if (nextInterval == null) { if (!currentInterval.Enabled() && currentInterval.End.Date > lastTradingDay.Date) { return(currentInterval.End); } else // means no any intervals (current or any in the future) { return(currentDateTime.Date.AddDays(1)); } } var stateIsChangedToEnabled = nextInterval.Schedule.IsTradeEnabled != currentInterval.Enabled() && nextInterval.Enabled(); var intervalIsMissing = currentInterval != null && nextInterval.Start > currentInterval.End; if (stateIsChangedToEnabled || intervalIsMissing && currentInterval.End.Date > lastTradingDay.Date) { // ReSharper disable once PossibleNullReferenceException // if status was changed and next is enabled, that means current interval is disable == it not null return(currentInterval.End); } // if we have long enabled interval with overnight, next day will start at 00:00:00 if (currentInterval.Enabled() && currentDateTime.Date.AddDays(1) < nextInterval.Start) { return(currentDateTime.Date.AddDays(1)); } return(GetNextTradingDay(compiledSchedule, nextInterval, nextInterval.End.AddTicks(1), lastTradingDay)); }