DateTimeRange.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Masuit.Tools.DateTimeExt;
  5. namespace Masuit.Tools.Models;
  6. /// <summary>
  7. /// 时间段
  8. /// </summary>
  9. public class DateTimeRange : ITimePeriod
  10. {
  11. public DateTimeRange(DateTime? start, DateTime? end)
  12. {
  13. if (start > end)
  14. {
  15. throw new Exception("开始时间不能大于结束时间");
  16. }
  17. Start = start;
  18. End = end;
  19. }
  20. public DateTimeRange()
  21. {
  22. }
  23. /// <summary>
  24. /// 起始时间
  25. /// </summary>
  26. public DateTime? Start { get; set; }
  27. /// <summary>
  28. /// 结束时间
  29. /// </summary>
  30. public DateTime? End { get; set; }
  31. /// <summary>
  32. /// 是否相交
  33. /// </summary>
  34. /// <param name="start"></param>
  35. /// <param name="end"></param>
  36. /// <returns></returns>
  37. public bool HasIntersect(DateTime? start, DateTime? end)
  38. {
  39. return HasIntersect(new DateTimeRange(start, end));
  40. }
  41. /// <summary>
  42. /// 是否相交
  43. /// </summary>
  44. /// <param name="range"></param>
  45. /// <returns></returns>
  46. public bool HasIntersect(DateTimeRange range)
  47. {
  48. return IsDatetimeRangeOverlap(Start, End, range.Start, range.End);
  49. }
  50. /// <summary>
  51. /// 相交时间段
  52. /// </summary>
  53. /// <param name="range"></param>
  54. /// <returns></returns>
  55. public (bool intersected, DateTimeRange range) Intersect(DateTimeRange range)
  56. {
  57. if (!HasIntersect(range.Start, range.End))
  58. {
  59. return (false, null);
  60. }
  61. var list = new HashSet<DateTime?> { Start, range.Start, End, range.End }.ToList();
  62. list.Sort();
  63. return (true, new DateTimeRange(list[1], list[2]));
  64. }
  65. /// <summary>
  66. /// 相交时间段
  67. /// </summary>
  68. /// <param name="start"></param>
  69. /// <param name="end"></param>
  70. /// <returns></returns>
  71. public (bool intersected, DateTimeRange range) Intersect(DateTime start, DateTime end)
  72. {
  73. return Intersect(new DateTimeRange(start, end));
  74. }
  75. /// <summary>
  76. /// 是否包含时间段
  77. /// </summary>
  78. /// <param name="range"></param>
  79. /// <returns></returns>
  80. public bool Contains(DateTimeRange range)
  81. {
  82. return IsDatetimeRangeOverlap(Start, End, range.Start, range.End);
  83. }
  84. /// <summary>
  85. /// 是否包含时间段
  86. /// </summary>
  87. /// <param name="start"></param>
  88. /// <param name="end"></param>
  89. /// <returns></returns>
  90. public bool Contains(DateTime? start, DateTime? end)
  91. {
  92. return Contains(new DateTimeRange(start, end));
  93. }
  94. /// <summary>
  95. /// 是否在时间段内
  96. /// </summary>
  97. /// <param name="range"></param>
  98. /// <returns></returns>
  99. public bool In(DateTimeRange range)
  100. {
  101. return IsDatetimeRangeOverlap(Start, End, range.Start, range.End);
  102. }
  103. /// <summary>
  104. /// 是否在时间段内
  105. /// </summary>
  106. /// <param name="start"></param>
  107. /// <param name="end"></param>
  108. /// <returns></returns>
  109. public bool In(DateTime start, DateTime end)
  110. {
  111. return In(new DateTimeRange(start, end));
  112. }
  113. /// <summary>
  114. /// 合并时间段
  115. /// </summary>
  116. /// <param name="range"></param>
  117. /// <returns></returns>
  118. public DateTimeRange Union(DateTimeRange range)
  119. {
  120. if (!HasIntersect(range))
  121. throw new Exception("不相交的时间段不能合并");
  122. var list = new HashSet<DateTime?> { Start, range.Start, End, range.End }.ToList();
  123. list.Sort();
  124. return new DateTimeRange(list[0], list[3]);
  125. }
  126. /// <summary>
  127. /// 合并时间段
  128. /// </summary>
  129. /// <param name="start"></param>
  130. /// <param name="end"></param>
  131. /// <returns></returns>
  132. public DateTimeRange Union(DateTime start, DateTime end)
  133. {
  134. return Union(new DateTimeRange(start, end));
  135. }
  136. /// <summary>返回一个表示当前对象的 string。</summary>
  137. /// <returns>表示当前对象的字符串。</returns>
  138. public override string ToString()
  139. {
  140. return $"{Start:yyyy-MM-dd HH:mm:ss}~{End:yyyy-MM-dd HH:mm:ss}";
  141. }
  142. public override bool Equals(object obj)
  143. {
  144. if (obj is DateTimeRange range)
  145. {
  146. return Start?.Date == range.Start?.Date && End?.Date == range.End?.Date;
  147. }
  148. return false;
  149. }
  150. private static bool IsDatetimeRangeOverlap(DateTime? startDateA, DateTime? endDateA, DateTime? startDateB, DateTime? endDateB)
  151. {
  152. return !(endDateA < startDateB || endDateB < startDateA);
  153. }
  154. }