code_junkie

Determine Whether Two Date Ranges Overlap

Nov 12th, 2011
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.28 KB | None | 0 0
  1. (StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)
  2.  
  3. ----------------------|-------A-------|----------------------
  4. |----B1----|
  5. |----B2----|
  6. |----B3----|
  7. |----------B4----------|
  8. |----------------B5----------------|
  9. |----B6----|
  10. ----------------------|-------A-------|----------------------
  11. |------B7-------|
  12. |----------B8-----------|
  13. |----B9----|
  14. |----B10-----|
  15. |--------B11--------|
  16. |----B12----|
  17. |----B13----|
  18. ----------------------|-------A-------|----------------------
  19.  
  20. |----------------------| range 1
  21. |---> range 2 overlap
  22. |---> range 2 overlap
  23. |---> range 2 overlap
  24. |---> range 2 no overlap
  25.  
  26. def doesOverlap (r1,r2):
  27. if r1.s > r2.s:
  28. swap r1, r2
  29. if r2.s > r1.e:
  30. return false
  31. return true
  32.  
  33. |----------------------| range 1
  34. |---> range 2 overlap
  35. |---> range 2 overlap
  36. |---> range 2 no overlap
  37. |---> range 2 no overlap
  38.  
  39. StartDate1.IsBetween(StartDate2, EndDate2) || EndDate1.IsBetween(StartDate2, EndDate2)
  40.  
  41. public static bool IsBetween(this DateTime value, DateTime left, DateTime right) {
  42. return (value > left && value < right) || (value < left && value > right);
  43. }
  44.  
  45. // Takes a list and returns all records that have overlapping time ranges.
  46. public static IEnumerable<T> GetOverlappedTimes<T>(IEnumerable<T> list, Func<T, bool> filter, Func<T,DateTime> start, Func<T, DateTime> end)
  47. {
  48. // Selects all records that match filter() on left side and returns all records on right side that overlap.
  49. var overlap = from t1 in list
  50. where filter(t1)
  51. from t2 in list
  52. where !object.Equals(t1, t2) // Don't match the same record on right side.
  53. let in1 = start(t1)
  54. let out1 = end(t1)
  55. let in2 = start(t2)
  56. let out2 = end(t2)
  57. where in1 <= out2 && out1 >= in2
  58. let totover = GetMins(in1, out1, in2, out2)
  59. select t2;
  60.  
  61. return overlap;
  62. }
  63.  
  64. public static void TestOverlap()
  65. {
  66. var tl1 = new TempTimeEntry() { ID = 1, Name = "Bill", In = "1/1/08 1:00pm".ToDate(), Out = "1/1/08 4:00pm".ToDate() };
  67. var tl2 = new TempTimeEntry() { ID = 2, Name = "John", In = "1/1/08 5:00pm".ToDate(), Out = "1/1/08 6:00pm".ToDate() };
  68. var tl3 = new TempTimeEntry() { ID = 3, Name = "Lisa", In = "1/1/08 7:00pm".ToDate(), Out = "1/1/08 9:00pm".ToDate() };
  69. var tl4 = new TempTimeEntry() { ID = 4, Name = "Joe", In = "1/1/08 3:00pm".ToDate(), Out = "1/1/08 8:00pm".ToDate() };
  70. var tl5 = new TempTimeEntry() { ID = 1, Name = "Bill", In = "1/1/08 8:01pm".ToDate(), Out = "1/1/08 8:00pm".ToDate() };
  71. var list = new List<TempTimeEntry>() { tl1, tl2, tl3, tl4, tl5 };
  72. var overlap = GetOverlappedTimes(list, (TempTimeEntry t1)=>t1.ID==1, (TempTimeEntry tIn) => tIn.In, (TempTimeEntry tOut) => tOut.Out);
  73.  
  74. Console.WriteLine("nRecords overlap:");
  75. foreach (var tl in overlap)
  76. Console.WriteLine("Name:{0} T1In:{1} T1Out:{2}", tl.Name, tl.In, tl.Out);
  77. Console.WriteLine("Done");
  78.  
  79. /* Output:
  80. Records overlap:
  81. Name:Joe T1In:1/1/2008 3:00:00 PM T1Out:1/1/2008 8:00:00 PM
  82. Name:Lisa T1In:1/1/2008 7:00:00 PM T1Out:1/1/2008 9:00:00 PM
  83. Done
  84. */
  85. }
  86.  
  87. // ------------------------------------------------------------------------
  88. public enum PeriodRelation
  89. {
  90. After,
  91. StartTouching,
  92. StartInside,
  93. InsideStartTouching,
  94. EnclosingStartTouching,
  95. Enclosing,
  96. EnclosingEndTouching,
  97. ExactMatch,
  98. Inside,
  99. InsideEndTouching,
  100. EndInside,
  101. EndTouching,
  102. Before,
  103. } // enum PeriodRelation
  104.  
  105. declare
  106. @StartDate date,
  107. @EndDate date
  108.  
  109. select
  110. @StartDate = '1900-01-01',
  111. @EndDate = '2049-12-31'
  112.  
  113. create table Numbers
  114. (
  115. Id int identity (1, 1),
  116. Date date primary key
  117. )
  118.  
  119. ;
  120. with
  121. DateList as -- list of dates
  122. (
  123. select @StartDate as Date
  124. union all
  125. select dateadd(d, 1, Date) from DateList where datediff(d, Date, @EndDate) > 0
  126. )
  127. insert
  128. Numbers
  129. (
  130. Date
  131. )
  132. select
  133. Date
  134. from
  135. DateList
  136. option (maxrecursion 0)
  137.  
  138. alter function FnOverlaps
  139. (
  140. @StartDateA datetime,
  141. @EndDateA datetime,
  142. @StartDateB datetime,
  143. @EndDateB datetime
  144. )
  145. returns bit
  146. as
  147. begin
  148. declare
  149. @RetVal bit
  150.  
  151. ;
  152. with
  153. ins as
  154. (
  155. select Date from Numbers where Date between @StartDateA and @EndDateA
  156. intersect
  157. select Date from Numbers where Date between @StartDateB and @EndDateB
  158. )
  159. select @RetVal = case when count(*) = 0 then 0 else 1 end from ins
  160. return @RetVal
  161. end
  162. go
  163.  
  164. -- test here
  165. select dbo.FnOverlaps('2005-01-01', '2005-12-31', '2004-01-01', '2004-01-31')
Add Comment
Please, Sign In to add comment