/// <summary>取得日期時間區段清單的交集</summary> public static IEnumerable <DateTimeSection> IntersectSection(this IEnumerable <DateTimeSection> source, IEnumerable <DateTimeSection> target) { source = source.Where(x => x != null && x.Start < x.End).OrderBy(x => x.End); target = target.Where(x => x != null && x.Start < x.End).OrderBy(x => x.End); using (IEnumerator <DateTimeSection> sIter = source.GetEnumerator(), tIter = target.GetEnumerator()) { bool hasS = sIter.MoveNext(); bool hasT = tIter.MoveNext(); while (hasS && hasT) { DateTimeSection overlap = Overlap(sIter.Current, tIter.Current); if (overlap.End == sIter.Current.End) { hasS = sIter.MoveNext(); } if (overlap.End == tIter.Current.End) { hasT = tIter.MoveNext(); } if (overlap.Start < overlap.End) { yield return(overlap); } } } }
/// <summary>取得日期時間區段清單的聯集</summary> public static IEnumerable <DateTimeSection> UnionSection(this IEnumerable <DateTimeSection> source, IEnumerable <DateTimeSection> target) { source = source.Concat(target).Where(x => x != null).OrderBy(x => x.Start); using (IEnumerator <DateTimeSection> iter = source.GetEnumerator()) { if (!iter.MoveNext()) { yield break; } var cursor = new DateTimeSection(iter.Current); while (iter.MoveNext()) { if (iter.Current.Start <= cursor.End) { cursor.End = OrionUtils.Max(iter.Current.End, cursor.End); continue; } yield return(cursor); cursor = new DateTimeSection(iter.Current); } yield return(cursor); } }
/// <summary> /// 修正时间至某一节,保留那一节 /// </summary> /// <param name="dt"></param> /// <param name="state"></param> /// <returns></returns> public static DateTime RequireDateTime(DateTime dt, DateTimeSection state) { switch (state) { case DateTimeSection.Year: return(new DateTime(dt.Year, 1, 1, 0, 0, 0, dt.Kind)); case DateTimeSection.Month: return(new DateTime(dt.Year, dt.Month, 1, 0, 0, 0, dt.Kind)); case DateTimeSection.Week: dt = dt.AddDays(-(int)dt.DayOfWeek); return(new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, dt.Kind)); case DateTimeSection.Day: return(new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, dt.Kind)); case DateTimeSection.Hour: return(new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0, dt.Kind)); case DateTimeSection.Minute: return(new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0, dt.Kind)); case DateTimeSection.Second: return(new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Kind)); default: return(dt); } }
/// <summary>取得重疊日期時間區段</summary> public static DateTimeSection Overlap(this DateTimeSection sectionA, DateTimeSection sectionB) { return(new DateTimeSection { Start = OrionUtils.Max(sectionA.Start, sectionB.Start), End = OrionUtils.Min(sectionA.End, sectionB.End), }); }
/// <summary> /// 修正时间为一个时间段 /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="state">0:年,1:月,2:日,3:时,4:分</param> public static void RequireDateTime(ref DateTime start, ref DateTime end, DateTimeSection state) { start = RequireDateTime(start, state); end = RequireDateTime(end, state); switch (state) { case DateTimeSection.Year: end = end.AddYears(1); break; case DateTimeSection.Month: end = end.AddMonths(1); break; case DateTimeSection.Week: end = end.AddDays(7); break; case DateTimeSection.Day: end = end.AddDays(1); break; case DateTimeSection.Hour: end = end.AddHours(1); break; case DateTimeSection.Minute: end = end.AddMinutes(1); break; case DateTimeSection.Second: end = end.AddSeconds(1); break; default: start = DateTime.Now.AddDays(-1); end = DateTime.Now; break; } end = end.AddSeconds(-1); }
/// <summary>將日期時間區段清單反轉成空缺區段</summary> public static IEnumerable <DateTimeSection> ComplementSection(this IEnumerable <DateTimeSection> source) { source = source.Where(x => x != null).OrderBy(x => x.Start); var cursor = new DateTimeSection { Start = DateTime.MinValue }; foreach (var item in source) { cursor.End = item.Start; yield return(cursor); cursor = new DateTimeSection { Start = item.End }; } cursor.End = DateTime.MaxValue; yield return(cursor); }
/// <summary>檢查日期時間區段是否重疊</summary> public static void CheckOverlap(this IEnumerable <DateTimeSection> source) { source = source.Where(x => x != null).OrderBy(x => x.Start); using (IEnumerator <DateTimeSection> iter = source.GetEnumerator()) { if (!iter.MoveNext()) { return; } DateTimeSection prev = iter.Current; while (iter.MoveNext()) { if (prev.End <= iter.Current.Start) { continue; } throw new DataException($"Section overlap {prev} and {iter.Current}"); } } }