-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathdate_range_comparison.go
258 lines (226 loc) · 8.86 KB
/
date_range_comparison.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
package gedcom
import "fmt"
// DateRangeComparison describe how two date ranges (each can be described with
// a DateNode) relate to each other.
//
// Since we are comparing ranges of time, rather than absolute points there are
// several variations of results to be considered. It's easiest to explain
// visually where Left and Right are the date range operands respectively:
//
// Method returns true:
// Left: |========|
// Right:
// Equal: |========| IsEqual()
// Inside: | <====> | IsPartiallyEqual()
// InsideStart: |======> | IsPartiallyEqual()
// InsideEnd: | <======| IsPartiallyEqual()
// Outside: <===+========+===> IsPartiallyEqual()
// OutsideStart: |========+===> IsPartiallyEqual()
// OutsideEnd: <===+========| IsPartiallyEqual()
// PartiallyBefore: <===+===> | IsPartiallyEqual()
// PartiallyAfter: | <==+===> IsPartiallyEqual()
// Before: <===| | IsNotEqual()
// After: | |===> IsNotEqual()
// EntirelyBefore: <=> | | IsNotEqual()
// EntirelyAfter: | | <=> IsNotEqual()
//
// The Simplified value is the DateRangeComparisonSimplified value which is
// derived from DateRangeComparison.Simplified().
type DateRangeComparison int
// Each of the constants below represent how the ranges cross over. See
// DateRangeComparison for a visual explanation.
const (
// DateRangeComparisonInvalid is only used in cases of an error.
DateRangeComparisonInvalid = DateRangeComparison(iota)
// Equal means that both date ranges are exactly the same in start and end
// date, or they have an equivalent other value:
//
// Yes:
// 3 Sep 1943 3 Sep 1943
// Sep 1943 - Mar 1944 Sep 1943 - Mar 1944
// (world war 2) (world war 2)
//
// No:
// 3 Sep 1943 Sep 1943
// Sep 1943 - Mar 1944 Sep 1943 - 3 Mar 1944
// (world war 2) (world war 1)
//
DateRangeComparisonEqual = iota
// Inside means that the right operand is both smaller and encapsulated by
// the greater range in both directions of the left operand. The Start and
// End derivatives represent if certain boundaries are also equal.
//
// Yes:
// 3 Sep 1943 - 20 Sep 1943 5 Sep 1943 - 17 Sep 1943
// Sep 1943 3 Sep 1943 - 20 Sep 1943
// No:
// 3 Sep 1943 - 20 Sep 1943 1 Sep 1943 - 5 Sep 1943
// Sep 1943 20 Sep 1943 - 10 Oct 1943
// (world war 2) (world war 2)
//
DateRangeComparisonInside = iota
DateRangeComparisonInsideStart = iota
DateRangeComparisonInsideEnd = iota
// Outside means that the right operand is larger in both directions. The
// opposite of Inside. The Start and End derivatives represent if certain
// boundaries are also equal.
//
// Yes:
// 3 Sep 1943 - 20 Sep 1943 1 Sep 1943 - 25 Sep 1943
// Sep 1943 14 Jul 1943 - 10 Oct 1943
// No:
// 3 Sep 1943 - 20 Sep 1943 1 Sep 1943 - 5 Sep 1943
// Sep 1943 20 Sep 1943 - 10 Oct 1943
// (world war 2) (world war 2)
//
DateRangeComparisonOutside = iota
DateRangeComparisonOutsideStart = iota
DateRangeComparisonOutsideEnd = iota
// PartiallyBefore means the right operand range surrounds the start of the
// left operand.
//
// Yes:
// 3 Sep 1943 - 20 Sep 1943 1 Sep 1943 - 5 Sep 1943
// Sep 1943 14 Jul 1943 - 10 Sep 1943
// No:
// 3 Sep 1943 - 20 Sep 1943 1 Sep 1943 - 25 Sep 1943
// Sep 1943 20 Sep 1943 - 10 Oct 1943
// (world war 2) (world war 2)
//
DateRangeComparisonPartiallyBefore = iota
// PartiallyAfter means the right operand range surrounds the end of the
// left operand.
//
// Yes:
// 3 Sep 1943 - 20 Sep 1943 17 Sep 1943 - 25 Sep 1943
// Sep 1943 10 Sep 1943 - 10 Oct 1943
// No:
// 3 Sep 1943 - 20 Sep 1943 10 Sep 1943 - 15 Sep 1943
// Sep 1943 20 Sep 1943 - 25 Sep 1943
// (world war 2) (world war 2)
//
DateRangeComparisonPartiallyAfter = iota
// Before means the right operand range starts before the left operand's
// before, but ends at the same value as the start of the left operand.
//
// Yes:
// 3 Sep 1943 - 20 Sep 1943 1 Sep 1943 - 3 Sep 1943
// Sep 1943 14 Jul 1943 - 1 Sep 1943
// No:
// 3 Sep 1943 - 20 Sep 1943 1 Sep 1943 - 4 Sep 1943
// Sep 1943 14 Jul 1943 - 10 Sep 1943
// (world war 2) (world war 2)
//
DateRangeComparisonBefore = iota
// After means the right operand starts at the end of the left operand and
// ends somewhere thereafter.
//
// Yes:
// 3 Sep 1943 - 20 Sep 1943 20 Sep 1943 - 25 Sep 1943
// Sep 1943 30 Sep 1943 - 10 Oct 1943
// No:
// 3 Sep 1943 - 20 Sep 1943 19 Sep 1943 - 25 Sep 1943
// Sep 1943 20 Sep 1943 - 25 Sep 1943
// (world war 2) (world war 2)
//
DateRangeComparisonAfter = iota
// EntirelyBefore means that the full range of the right operand is before
// any of the range of the left operand.
//
// Yes:
// 3 Sep 1943 - 20 Sep 1943 1 Sep 1943 - 2 Sep 1943
// Sep 1943 3 Jul 1943 - 10 Jul 1943
// No:
// 3 Sep 1943 - 20 Sep 1943 19 Sep 1943 - 25 Sep 1943
// Sep 1943 20 Sep 1943 - 25 Sep 1943
// (world war 2) (world war 2)
//
DateRangeComparisonEntirelyBefore = iota
// EntirelyAfter means that the full range of the right operand is after
// any of the range of the left operand.
//
// Yes:
// 3 Sep 1943 - 20 Sep 1943 25 Sep 1943 - 30 Sep 1943
// Sep 1943 3 Oct 1943 - 10 Oct 1943
// No:
// 3 Sep 1943 - 20 Sep 1943 19 Sep 1943 - 25 Sep 1943
// Sep 1943 20 Sep 1943 - 25 Sep 1943
// (world war 2) (world war 2)
//
DateRangeComparisonEntirelyAfter = iota
)
// IsEqual returns true only if both date ranges are exactly the same.
//
// It's important to note that a DateRangeComparison can be in one of three
// simplified states: Equal, PartiallyEqual or NotEqual. So !IsEqual() is not
// the same as IsNotEqual().
func (c DateRangeComparison) IsEqual() bool {
return c == DateRangeComparisonEqual
}
// IsPartiallyEqual returns true if any part of the date range touches or
// intersects another.
func (c DateRangeComparison) IsPartiallyEqual() bool {
switch c {
case DateRangeComparisonInside,
DateRangeComparisonInsideStart,
DateRangeComparisonInsideEnd,
DateRangeComparisonOutside,
DateRangeComparisonOutsideStart,
DateRangeComparisonOutsideEnd,
DateRangeComparisonPartiallyBefore,
DateRangeComparisonPartiallyAfter:
return true
}
return false
}
// IsNotEqual returns true if the two date ranges do not intersect at any point.
//
// It's important to note that a DateRangeComparison can be in one of three
// simplified states: Equal, PartiallyEqual or NotEqual. So !IsNotEqual() is not
// the same as IsEqual().
func (c DateRangeComparison) IsNotEqual() bool {
switch c {
case DateRangeComparisonBefore,
DateRangeComparisonAfter,
DateRangeComparisonEntirelyBefore,
DateRangeComparisonEntirelyAfter:
return true
}
return false
}
// String returns the name of the constant like
// "DateRangeComparisonInsideStart".
func (c DateRangeComparison) String() string {
switch c {
case DateRangeComparisonInvalid:
return "DateRangeComparisonInvalid"
case DateRangeComparisonEqual:
return "DateRangeComparisonEqual"
case DateRangeComparisonInside:
return "DateRangeComparisonInside"
case DateRangeComparisonInsideStart:
return "DateRangeComparisonInsideStart"
case DateRangeComparisonInsideEnd:
return "DateRangeComparisonInsideEnd"
case DateRangeComparisonOutside:
return "DateRangeComparisonOutside"
case DateRangeComparisonOutsideStart:
return "DateRangeComparisonOutsideStart"
case DateRangeComparisonOutsideEnd:
return "DateRangeComparisonOutsideEnd"
case DateRangeComparisonPartiallyBefore:
return "DateRangeComparisonPartiallyBefore"
case DateRangeComparisonPartiallyAfter:
return "DateRangeComparisonPartiallyAfter"
case DateRangeComparisonBefore:
return "DateRangeComparisonBefore"
case DateRangeComparisonAfter:
return "DateRangeComparisonAfter"
case DateRangeComparisonEntirelyBefore:
return "DateRangeComparisonEntirelyBefore"
case DateRangeComparisonEntirelyAfter:
return "DateRangeComparisonEntirelyAfter"
default:
panic(fmt.Sprintf("invalid constant: %d", c))
}
}