public static DateTime?Project(this DateTime?dt, SubtotalLevel level) { if (!dt.HasValue) { return(null); } if (!level.HasFlag(SubtotalLevel.Day)) { return(null); } if (!level.HasFlag(SubtotalLevel.Week)) { return(dt); } if (level.HasFlag(SubtotalLevel.Year)) { return(new(dt !.Value.Year, 1, 1)); } if (level.HasFlag(SubtotalLevel.Month)) { return(new(dt !.Value.Year, dt !.Value.Month, 1)); } // if (level.HasFlag(SubtotalLevel.Week)) return(dt.Value.DayOfWeek switch { DayOfWeek.Monday => dt.Value.AddDays(-0), DayOfWeek.Tuesday => dt.Value.AddDays(-1), DayOfWeek.Wednesday => dt.Value.AddDays(-2), DayOfWeek.Thursday => dt.Value.AddDays(-3), DayOfWeek.Friday => dt.Value.AddDays(-4), DayOfWeek.Saturday => dt.Value.AddDays(-5), DayOfWeek.Sunday => dt.Value.AddDays(-6), _ => throw new ArgumentOutOfRangeException(), });
private ISubtotalResult BuildAggrPhase(SubtotalResult sub, IEnumerable <Balance> raw) { switch (m_Par.AggrType) { case AggregationType.None: sub.Fund = BuildEquiPhase(raw); if (m_Flags.HasFlag(SubtotalLevel.NonZero) && sub.Fund.IsZero() && !(sub is ISubtotalRoot)) { return(null); } return(sub); case AggregationType.ChangedDay: sub.TheItems = raw.GroupBy(b => b.Date).OrderBy(grp => grp.Key) .Select( grp => new SubtotalDate(grp.Key, m_Par.AggrInterval) { Fund = sub.Fund += BuildEquiPhase(grp), }).Cast <ISubtotalResult>().ToList(); return(sub); case AggregationType.EveryDay: sub.TheItems = new List <ISubtotalResult>(); var initial = Prev(m_Par.EveryDayRange.Range.StartDate); var ed = Next(Prev(m_Par.EveryDayRange.Range.EndDate)); var last = initial; void Append(DateTime?curr, double oldFund, double fund) { if (last.HasValue && curr.HasValue) { while (last < curr) { last = Next(last.Value); sub.TheItems.Add( new SubtotalDate(last, m_Par.AggrInterval) { Fund = last == curr ? fund : oldFund, }); } } else { sub.TheItems.Add( new SubtotalDate(curr, m_Par.AggrInterval) { Fund = fund }); } if (DateHelper.CompareDate(last, curr) < 0) { last = curr; } } var flag = true; var tmp0 = 0D; var forcedNull = (m_Par.EveryDayRange.Range.StartDate.HasValue || m_Par.EveryDayRange.Range.NullOnly) && m_Par.EveryDayRange.Range.Nullable; foreach (var grp in raw.GroupBy(b => b.Date).OrderBy(grp => grp.Key)) { if (flag && grp.Key != null && forcedNull) { sub.TheItems.Add( new SubtotalDate(null, m_Par.AggrInterval) { Fund = 0 }); } flag = false; var tmp = sub.Fund; sub.Fund += BuildEquiPhase(grp); if (DateHelper.CompareDate(grp.Key, ed) <= 0) { tmp0 = sub.Fund; } if (grp.Key.Within(m_Par.EveryDayRange.Range)) { Append(grp.Key, tmp, sub.Fund); } } if (flag && forcedNull) { sub.TheItems.Add( new SubtotalDate(null, m_Par.AggrInterval) { Fund = 0 }); } if (ed.HasValue && DateHelper.CompareDate(last, ed) < 0) { Append(ed, tmp0, tmp0); } else if (initial.HasValue && last == initial) { Append(Next(initial.Value), sub.Fund, sub.Fund); } return(sub); default: throw new ArgumentOutOfRangeException(); } }