1 // Written in the D programming language
2
3 /++
4 $(SCRIPT inhibitQuickIndex = 1;)
5 $(DIVC quickindex,
6 $(BOOKTABLE,
7 $(TR $(TH Category) $(TH Functions))
8 $(TR $(TD Main types) $(TD
9 $(LREF Interval)
10 $(LREF Direction)
11 ))
12 $(TR $(TD Special intervals) $(TD
13 $(LREF everyDayOfWeek)
14 $(LREF everyMonth)
15 $(LREF everyDuration)
16 ))
17 $(TR $(TD Special intervals) $(TD
18 $(LREF NegInfInterval)
19 $(LREF PosInfInterval)
20 ))
21 $(TR $(TD Underlying ranges) $(TD
22 $(LREF IntervalRange)
23 $(LREF NegInfIntervalRange)
24 $(LREF PosInfIntervalRange)
25 ))
26 $(TR $(TD Flags) $(TD
27 $(LREF PopFirst)
28 ))
29 ))
30
31 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
32 Authors: $(HTTP jmdavisprog.com, Jonathan M Davis)
33 Source: $(PHOBOSSRC std/datetime/interval.d)
34 +/
35 module std.datetime.interval;
36
37 import core.time : Duration, dur;
38 import std.datetime.date : AllowDayOverflow, DateTimeException, daysToDayOfWeek,
39 DayOfWeek, isTimePoint, Month;
40 import std.exception : enforce;
41 import std.range.primitives : isOutputRange;
42 import std.traits : isIntegral;
43 import std.typecons : Flag;
44
45 version (StdUnittest) import std.exception : assertThrown;
46
47
48 /++
49 Indicates a direction in time. One example of its use is $(LREF Interval)'s
50 $(LREF expand) function which uses it to indicate whether the interval
51 should be expanded backwards (into the past), forwards (into the future), or
52 both.
53 +/
54 enum Direction
55 {
56 /// Backward.
57 bwd,
58
59 /// Forward.
60 fwd,
61
62 /// Both backward and forward.
63 both
64 }
65
66
67 /++
68 Used to indicate whether `popFront` should be called immediately upon
69 creating a range. The idea is that for some functions used to generate a
70 range for an interval, `front` is not necessarily a time point which
71 would ever be generated by the range (e.g. if the range were every Sunday
72 within an interval, but the interval started on a Monday), so there needs
73 to be a way to deal with that. To get the first time point in the range to
74 match what the function generates, then use `PopFirst.yes` to indicate
75 that the range should have `popFront` called on it before the range is
76 returned so that `front` is a time point which the function would
77 generate. To let the first time point not match the generator function,
78 use `PopFront.no`.
79
80 For instance, if the function used to generate a range of time points
81 generated successive Easters (i.e. you're iterating over all of the Easters
82 within the interval), the initial date probably isn't an Easter. Using
83 `PopFirst.yes` would tell the function which returned the range that
84 `popFront` was to be called so that front would then be an Easter - the
85 next one generated by the function (which when iterating forward would be
86 the Easter following the original `front`, while when iterating backward,
87 it would be the Easter prior to the original `front`). If
88 `PopFirst.no` were used, then `front` would remain the original time
89 point and it would not necessarily be a time point which would be generated
90 by the range-generating function (which in many cases is exactly what is
91 desired - e.g. if iterating over every day starting at the beginning of the
92 interval).
93
94 If set to `PopFirst.no`, then popFront is not called before returning
95 the range.
96
97 Otherwise, if set to `PopFirst.yes`, then popFront is called before
98 returning the range.
99 +/
100 alias PopFirst = Flag!"popFirst";
101
102
103 /++
104 Represents an interval of time.
105
106 An `Interval` has a starting point and an end point. The interval of time
107 is therefore the time starting at the starting point up to, but not
108 including, the end point. e.g.
109
110 $(BOOKTABLE,
111 $(TR $(TD [January 5th, 2010 - March 10th, 2010$(RPAREN)))
112 $(TR $(TD [05:00:30 - 12:00:00$(RPAREN)))
113 $(TR $(TD [1982-01-04T08:59:00 - 2010-07-04T12:00:00$(RPAREN)))
114 )
115
116 A range can be obtained from an `Interval`, allowing iteration over
117 that interval, with the exact time points which are iterated over depending
118 on the function which generates the range.
119 +/
Interval(TP)120 struct Interval(TP)
121 {
122 public:
123
124 /++
125 Params:
126 begin = The time point which begins the interval.
127 end = The time point which ends (but is not included in) the
128 interval.
129
130 Throws:
131 $(REF DateTimeException,std,datetime,date) if $(D_PARAM end) is
132 before $(D_PARAM begin).
133
134 Example:
135 --------------------
136 Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
137 --------------------
138 +/
139 this(U)(scope const TP begin, scope const U end) pure
140 if (is(immutable TP == immutable U))
141 {
142 if (!_valid(begin, end))
143 throw new DateTimeException("Arguments would result in an invalid Interval.");
144 _begin = cast(TP) begin;
145 _end = cast(TP) end;
146 }
147
148
149 /++
150 Params:
151 begin = The time point which begins the interval.
152 duration = The duration from the starting point to the end point.
153
154 Throws:
155 $(REF DateTimeException,std,datetime,date) if the resulting
156 `end` is before `begin`.
157
158 Example:
159 --------------------
160 assert(Interval!Date(Date(1996, 1, 2), dur!"days"(3)) ==
161 Interval!Date(Date(1996, 1, 2), Date(1996, 1, 5)));
162 --------------------
163 +/
164 this(D)(scope const TP begin, scope const D duration) pure
165 if (__traits(compiles, begin + duration))
166 {
167 _begin = cast(TP) begin;
168 _end = begin + duration;
169 if (!_valid(_begin, _end))
170 throw new DateTimeException("Arguments would result in an invalid Interval.");
171 }
172
173
174 /++
175 Params:
176 rhs = The $(LREF Interval) to assign to this one.
177 +/
178 ref Interval opAssign(const ref Interval rhs) pure nothrow
179 {
180 _begin = cast(TP) rhs._begin;
181 _end = cast(TP) rhs._end;
182 return this;
183 }
184
185
186 /++
187 Params:
188 rhs = The $(LREF Interval) to assign to this one.
189 +/
190 ref Interval opAssign(Interval rhs) pure nothrow
191 {
192 _begin = cast(TP) rhs._begin;
193 _end = cast(TP) rhs._end;
194 return this;
195 }
196
197
198 /++
199 The starting point of the interval. It is included in the interval.
200
201 Example:
202 --------------------
203 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin ==
204 Date(1996, 1, 2));
205 --------------------
206 +/
207 @property TP begin() const pure nothrow
208 {
209 return cast(TP) _begin;
210 }
211
212
213 /++
214 The starting point of the interval. It is included in the interval.
215
216 Params:
217 timePoint = The time point to set `begin` to.
218
219 Throws:
220 $(REF DateTimeException,std,datetime,date) if the resulting
221 interval would be invalid.
222 +/
223 @property void begin(TP timePoint) pure
224 {
225 if (!_valid(timePoint, _end))
226 throw new DateTimeException("Arguments would result in an invalid Interval.");
227 _begin = timePoint;
228 }
229
230
231 /++
232 The end point of the interval. It is excluded from the interval.
233
234 Example:
235 --------------------
236 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end ==
237 Date(2012, 3, 1));
238 --------------------
239 +/
240 @property TP end() const pure nothrow
241 {
242 return cast(TP) _end;
243 }
244
245
246 /++
247 The end point of the interval. It is excluded from the interval.
248
249 Params:
250 timePoint = The time point to set end to.
251
252 Throws:
253 $(REF DateTimeException,std,datetime,date) if the resulting
254 interval would be invalid.
255 +/
256 @property void end(TP timePoint) pure
257 {
258 if (!_valid(_begin, timePoint))
259 throw new DateTimeException("Arguments would result in an invalid Interval.");
260 _end = timePoint;
261 }
262
263
264 /++
265 Returns the duration between `begin` and `end`.
266
267 Example:
268 --------------------
269 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length ==
270 dur!"days"(5903));
271 --------------------
272 +/
273 @property auto length() const pure nothrow
274 {
275 return _end - _begin;
276 }
277
278
279 /++
280 Whether the interval's length is 0, that is, whether $(D begin == end).
281
282 Example:
283 --------------------
284 assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
285 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
286 --------------------
287 +/
288 @property bool empty() const pure nothrow
289 {
290 return _begin == _end;
291 }
292
293
294 /++
295 Whether the given time point is within this interval.
296
297 Params:
298 timePoint = The time point to check for inclusion in this interval.
299
300 Throws:
301 $(REF DateTimeException,std,datetime,date) if this interval is
302 empty.
303
304 Example:
305 --------------------
306 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
307 Date(1994, 12, 24)));
308
309 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
310 Date(2000, 1, 5)));
311 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
312 Date(2012, 3, 1)));
313 --------------------
314 +/
315 bool contains(scope const TP timePoint) const pure
316 {
317 _enforceNotEmpty();
318 return timePoint >= _begin && timePoint < _end;
319 }
320
321
322 /++
323 Whether the given interval is completely within this interval.
324
325 Params:
326 interval = The interval to check for inclusion in this interval.
327
328 Throws:
329 $(REF DateTimeException,std,datetime,date) if either interval is
330 empty.
331
332 Example:
333 --------------------
334 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
335 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
336
337 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
338 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
339
340 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
341 Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
342 --------------------
343 +/
344 bool contains(scope const Interval interval) const pure
345 {
346 _enforceNotEmpty();
347 interval._enforceNotEmpty();
348 return interval._begin >= _begin &&
349 interval._begin < _end &&
350 interval._end <= _end;
351 }
352
353
354 /++
355 Whether the given interval is completely within this interval.
356
357 Always returns false (unless this interval is empty), because an
358 interval going to positive infinity can never be contained in a finite
359 interval.
360
361 Params:
362 interval = The interval to check for inclusion in this interval.
363
364 Throws:
365 $(REF DateTimeException,std,datetime,date) if this interval is
366 empty.
367
368 Example:
369 --------------------
370 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
371 PosInfInterval!Date(Date(1999, 5, 4))));
372 --------------------
373 +/
374 bool contains(scope const PosInfInterval!TP interval) const pure
375 {
376 _enforceNotEmpty();
377 return false;
378 }
379
380
381 /++
382 Whether the given interval is completely within this interval.
383
384 Always returns false (unless this interval is empty), because an
385 interval beginning at negative infinity can never be contained in a
386 finite interval.
387
388 Params:
389 interval = The interval to check for inclusion in this interval.
390
391 Throws:
392 $(REF DateTimeException,std,datetime,date) if this interval is
393 empty.
394
395 Example:
396 --------------------
397 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
398 NegInfInterval!Date(Date(1996, 5, 4))));
399 --------------------
400 +/
401 bool contains(scope const NegInfInterval!TP interval) const pure
402 {
403 _enforceNotEmpty();
404 return false;
405 }
406
407
408 /++
409 Whether this interval is before the given time point.
410
411 Params:
412 timePoint = The time point to check whether this interval is before
413 it.
414
415 Throws:
416 $(REF DateTimeException,std,datetime,date) if this interval is
417 empty.
418
419 Example:
420 --------------------
421 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
422 Date(1994, 12, 24)));
423
424 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
425 Date(2000, 1, 5)));
426
427 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
428 Date(2012, 3, 1)));
429 --------------------
430 +/
431 bool isBefore(scope const TP timePoint) const pure
432 {
433 _enforceNotEmpty();
434 return _end <= timePoint;
435 }
436
437
438 /++
439 Whether this interval is before the given interval and does not
440 intersect with it.
441
442 Params:
443 interval = The interval to check for against this interval.
444
445 Throws:
446 $(REF DateTimeException,std,datetime,date) if either interval is
447 empty.
448
449 Example:
450 --------------------
451 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
452 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
453
454 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
455 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
456
457 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
458 Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
459 --------------------
460 +/
461 bool isBefore(scope const Interval interval) const pure
462 {
463 _enforceNotEmpty();
464 interval._enforceNotEmpty();
465 return _end <= interval._begin;
466 }
467
468
469 /++
470 Whether this interval is before the given interval and does not
471 intersect with it.
472
473 Params:
474 interval = The interval to check for against this interval.
475
476 Throws:
477 $(REF DateTimeException,std,datetime,date) if this interval is
478 empty.
479
480 Example:
481 --------------------
482 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
483 PosInfInterval!Date(Date(1999, 5, 4))));
484
485 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
486 PosInfInterval!Date(Date(2013, 3, 7))));
487 --------------------
488 +/
489 bool isBefore(scope const PosInfInterval!TP interval) const pure
490 {
491 _enforceNotEmpty();
492 return _end <= interval._begin;
493 }
494
495
496 /++
497 Whether this interval is before the given interval and does not
498 intersect with it.
499
500 Always returns false (unless this interval is empty) because a finite
501 interval can never be before an interval beginning at negative infinity.
502
503 Params:
504 interval = The interval to check for against this interval.
505
506 Throws:
507 $(REF DateTimeException,std,datetime,date) if this interval is
508 empty.
509
510 Example:
511 --------------------
512 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
513 NegInfInterval!Date(Date(1996, 5, 4))));
514 --------------------
515 +/
516 bool isBefore(scope const NegInfInterval!TP interval) const pure
517 {
518 _enforceNotEmpty();
519 return false;
520 }
521
522
523 /++
524 Whether this interval is after the given time point.
525
526 Params:
527 timePoint = The time point to check whether this interval is after
528 it.
529
530 Throws:
531 $(REF DateTimeException,std,datetime,date) if this interval is
532 empty.
533
534 Example:
535 --------------------
536 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
537 Date(1994, 12, 24)));
538
539 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
540 Date(2000, 1, 5)));
541
542 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
543 Date(2012, 3, 1)));
544 --------------------
545 +/
546 bool isAfter(scope const TP timePoint) const pure
547 {
548 _enforceNotEmpty();
549 return timePoint < _begin;
550 }
551
552
553 /++
554 Whether this interval is after the given interval and does not intersect
555 it.
556
557 Params:
558 interval = The interval to check against this interval.
559
560 Throws:
561 $(REF DateTimeException,std,datetime,date) if either interval is
562 empty.
563
564 Example:
565 --------------------
566 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
567 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
568
569 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
570 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
571
572 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
573 Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
574 --------------------
575 +/
576 bool isAfter(scope const Interval interval) const pure
577 {
578 _enforceNotEmpty();
579 interval._enforceNotEmpty();
580 return _begin >= interval._end;
581 }
582
583
584 /++
585 Whether this interval is after the given interval and does not intersect
586 it.
587
588 Always returns false (unless this interval is empty) because a finite
589 interval can never be after an interval going to positive infinity.
590
591 Params:
592 interval = The interval to check against this interval.
593
594 Throws:
595 $(REF DateTimeException,std,datetime,date) if this interval is
596 empty.
597
598 Example:
599 --------------------
600 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
601 PosInfInterval!Date(Date(1999, 5, 4))));
602 --------------------
603 +/
604 bool isAfter(scope const PosInfInterval!TP interval) const pure
605 {
606 _enforceNotEmpty();
607 return false;
608 }
609
610
611 /++
612 Whether this interval is after the given interval and does not intersect
613 it.
614
615 Params:
616 interval = The interval to check against this interval.
617
618 Throws:
619 $(REF DateTimeException,std,datetime,date) if this interval is
620 empty.
621
622 Example:
623 --------------------
624 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
625 NegInfInterval!Date(Date(1996, 1, 2))));
626 --------------------
627 +/
628 bool isAfter(scope const NegInfInterval!TP interval) const pure
629 {
630 _enforceNotEmpty();
631 return _begin >= interval._end;
632 }
633
634
635 /++
636 Whether the given interval overlaps this interval.
637
638 Params:
639 interval = The interval to check for intersection with this interval.
640
641 Throws:
642 $(REF DateTimeException,std,datetime,date) if either interval is
643 empty.
644
645 Example:
646 --------------------
647 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
648 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
649
650 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
651 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
652
653 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
654 Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
655 --------------------
656 +/
657 bool intersects(scope const Interval interval) const pure
658 {
659 _enforceNotEmpty();
660 interval._enforceNotEmpty();
661 return interval._begin < _end && interval._end > _begin;
662 }
663
664
665 /++
666 Whether the given interval overlaps this interval.
667
668 Params:
669 interval = The interval to check for intersection with this interval.
670
671 Throws:
672 $(REF DateTimeException,std,datetime,date) if this interval is
673 empty.
674
675 Example:
676 --------------------
677 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
678 PosInfInterval!Date(Date(1999, 5, 4))));
679
680 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
681 PosInfInterval!Date(Date(2012, 3, 1))));
682 --------------------
683 +/
684 bool intersects(scope const PosInfInterval!TP interval) const pure
685 {
686 _enforceNotEmpty();
687 return _end > interval._begin;
688 }
689
690
691 /++
692 Whether the given interval overlaps this interval.
693
694 Params:
695 interval = The interval to check for intersection with this interval.
696
697 Throws:
698 $(REF DateTimeException,std,datetime,date) if this interval is
699 empty.
700
701 Example:
702 --------------------
703 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
704 NegInfInterval!Date(Date(1996, 1, 2))));
705
706 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
707 NegInfInterval!Date(Date(2000, 1, 2))));
708 --------------------
709 +/
710 bool intersects(scope const NegInfInterval!TP interval) const pure
711 {
712 _enforceNotEmpty();
713 return _begin < interval._end;
714 }
715
716
717 /++
718 Returns the intersection of two intervals
719
720 Params:
721 interval = The interval to intersect with this interval.
722
723 Throws:
724 $(REF DateTimeException,std,datetime,date) if the two intervals do
725 not intersect or if either interval is empty.
726
727 Example:
728 --------------------
729 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
730 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
731 Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
732
733 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
734 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
735 Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
736 --------------------
737 +/
738 Interval intersection(scope const Interval interval) const
739 {
740 import std.format : format;
741
742 enforce(this.intersects(interval),
743 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
744
745 auto begin = _begin > interval._begin ? _begin : interval._begin;
746 auto end = _end < interval._end ? _end : interval._end;
747
748 return Interval(begin, end);
749 }
750
751
752 /++
753 Returns the intersection of two intervals
754
755 Params:
756 interval = The interval to intersect with this interval.
757
758 Throws:
759 $(REF DateTimeException,std,datetime,date) if the two intervals do
760 not intersect or if this interval is empty.
761
762 Example:
763 --------------------
764 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
765 PosInfInterval!Date(Date(1990, 7, 6))) ==
766 Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
767
768 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
769 PosInfInterval!Date(Date(1999, 1, 12))) ==
770 Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
771 --------------------
772 +/
773 Interval intersection(scope const PosInfInterval!TP interval) const
774 {
775 import std.format : format;
776
777 enforce(this.intersects(interval),
778 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
779
780 return Interval(_begin > interval._begin ? _begin : interval._begin, _end);
781 }
782
783
784 /++
785 Returns the intersection of two intervals
786
787 Params:
788 interval = The interval to intersect with this interval.
789
790 Throws:
791 $(REF DateTimeException,std,datetime,date) if the two intervals do
792 not intersect or if this interval is empty.
793
794 Example:
795 --------------------
796 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
797 NegInfInterval!Date(Date(1999, 7, 6))) ==
798 Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
799
800 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
801 NegInfInterval!Date(Date(2013, 1, 12))) ==
802 Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
803 --------------------
804 +/
805 Interval intersection(scope const NegInfInterval!TP interval) const
806 {
807 import std.format : format;
808
809 enforce(this.intersects(interval),
810 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
811
812 return Interval(_begin, _end < interval._end ? _end : interval._end);
813 }
814
815
816 /++
817 Whether the given interval is adjacent to this interval.
818
819 Params:
820 interval = The interval to check whether its adjecent to this
821 interval.
822
823 Throws:
824 $(REF DateTimeException,std,datetime,date) if either interval is
825 empty.
826
827 Example:
828 --------------------
829 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
830 Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
831
832 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
833 Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
834
835 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
836 Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
837 --------------------
838 +/
839 bool isAdjacent(scope const Interval interval) const pure
840 {
841 _enforceNotEmpty();
842 interval._enforceNotEmpty();
843 return _begin == interval._end || _end == interval._begin;
844 }
845
846
847 /++
848 Whether the given interval is adjacent to this interval.
849
850 Params:
851 interval = The interval to check whether its adjecent to this
852 interval.
853
854 Throws:
855 $(REF DateTimeException,std,datetime,date) if this interval is
856 empty.
857
858 Example:
859 --------------------
860 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
861 PosInfInterval!Date(Date(1999, 5, 4))));
862
863 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
864 PosInfInterval!Date(Date(2012, 3, 1))));
865 --------------------
866 +/
867 bool isAdjacent(scope const PosInfInterval!TP interval) const pure
868 {
869 _enforceNotEmpty();
870 return _end == interval._begin;
871 }
872
873
874 /++
875 Whether the given interval is adjacent to this interval.
876
877 Params:
878 interval = The interval to check whether its adjecent to this
879 interval.
880
881 Throws:
882 $(REF DateTimeException,std,datetime,date) if this interval is
883 empty.
884
885 Example:
886 --------------------
887 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
888 NegInfInterval!Date(Date(1996, 1, 2))));
889
890 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
891 NegInfInterval!Date(Date(2000, 1, 2))));
892 --------------------
893 +/
894 bool isAdjacent(scope const NegInfInterval!TP interval) const pure
895 {
896 _enforceNotEmpty();
897 return _begin == interval._end;
898 }
899
900
901 /++
902 Returns the union of two intervals
903
904 Params:
905 interval = The interval to merge with this interval.
906
907 Throws:
908 $(REF DateTimeException,std,datetime,date) if the two intervals do
909 not intersect and are not adjacent or if either interval is empty.
910
911 Example:
912 --------------------
913 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
914 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
915 Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
916
917 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
918 Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
919 Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
920 --------------------
921 +/
922 Interval merge(scope const Interval interval) const
923 {
924 import std.format : format;
925
926 enforce(this.isAdjacent(interval) || this.intersects(interval),
927 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
928
929 auto begin = _begin < interval._begin ? _begin : interval._begin;
930 auto end = _end > interval._end ? _end : interval._end;
931
932 return Interval(begin, end);
933 }
934
935
936 /++
937 Returns the union of two intervals
938
939 Params:
940 interval = The interval to merge with this interval.
941
942 Throws:
943 $(REF DateTimeException,std,datetime,date) if the two intervals do
944 not intersect and are not adjacent or if this interval is empty.
945
946 Example:
947 --------------------
948 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
949 PosInfInterval!Date(Date(1990, 7, 6))) ==
950 PosInfInterval!Date(Date(1990, 7 , 6)));
951
952 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
953 PosInfInterval!Date(Date(2012, 3, 1))) ==
954 PosInfInterval!Date(Date(1996, 1 , 2)));
955 --------------------
956 +/
957 PosInfInterval!TP merge(scope const PosInfInterval!TP interval) const
958 {
959 import std.format : format;
960
961 enforce(this.isAdjacent(interval) || this.intersects(interval),
962 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
963
964 return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
965 }
966
967
968 /++
969 Returns the union of two intervals
970
971 Params:
972 interval = The interval to merge with this interval.
973
974 Throws:
975 $(REF DateTimeException,std,datetime,date) if the two intervals do
976 not intersect and are not adjacent or if this interval is empty.
977
978 Example:
979 --------------------
980 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
981 NegInfInterval!Date(Date(1996, 1, 2))) ==
982 NegInfInterval!Date(Date(2012, 3 , 1)));
983
984 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
985 NegInfInterval!Date(Date(2013, 1, 12))) ==
986 NegInfInterval!Date(Date(2013, 1 , 12)));
987 --------------------
988 +/
989 NegInfInterval!TP merge(scope const NegInfInterval!TP interval) const
990 {
991 import std.format : format;
992
993 enforce(this.isAdjacent(interval) || this.intersects(interval),
994 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
995
996 return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
997 }
998
999
1000 /++
1001 Returns an interval that covers from the earliest time point of two
1002 intervals up to (but not including) the latest time point of two
1003 intervals.
1004
1005 Params:
1006 interval = The interval to create a span together with this interval.
1007
1008 Throws:
1009 $(REF DateTimeException,std,datetime,date) if either interval is
1010 empty.
1011
1012 Example:
1013 --------------------
1014 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1015 Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) ==
1016 Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
1017
1018 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1019 Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
1020 Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
1021 --------------------
1022 +/
1023 Interval span(scope const Interval interval) const pure
1024 {
1025 _enforceNotEmpty();
1026 interval._enforceNotEmpty();
1027
1028 auto begin = _begin < interval._begin ? _begin : interval._begin;
1029 auto end = _end > interval._end ? _end : interval._end;
1030
1031 return Interval(begin, end);
1032 }
1033
1034
1035 /++
1036 Returns an interval that covers from the earliest time point of two
1037 intervals up to (but not including) the latest time point of two
1038 intervals.
1039
1040 Params:
1041 interval = The interval to create a span together with this interval.
1042
1043 Throws:
1044 $(REF DateTimeException,std,datetime,date) if this interval is
1045 empty.
1046
1047 Example:
1048 --------------------
1049 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1050 PosInfInterval!Date(Date(1990, 7, 6))) ==
1051 PosInfInterval!Date(Date(1990, 7 , 6)));
1052
1053 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1054 PosInfInterval!Date(Date(2050, 1, 1))) ==
1055 PosInfInterval!Date(Date(1996, 1 , 2)));
1056 --------------------
1057 +/
1058 PosInfInterval!TP span(scope const PosInfInterval!TP interval) const pure
1059 {
1060 _enforceNotEmpty();
1061 return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
1062 }
1063
1064
1065 /++
1066 Returns an interval that covers from the earliest time point of two
1067 intervals up to (but not including) the latest time point of two
1068 intervals.
1069
1070 Params:
1071 interval = The interval to create a span together with this interval.
1072
1073 Throws:
1074 $(REF DateTimeException,std,datetime,date) if this interval is
1075 empty.
1076
1077 Example:
1078 --------------------
1079 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1080 NegInfInterval!Date(Date(1602, 5, 21))) ==
1081 NegInfInterval!Date(Date(2012, 3 , 1)));
1082
1083 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1084 NegInfInterval!Date(Date(2013, 1, 12))) ==
1085 NegInfInterval!Date(Date(2013, 1 , 12)));
1086 --------------------
1087 +/
1088 NegInfInterval!TP span(scope const NegInfInterval!TP interval) const pure
1089 {
1090 _enforceNotEmpty();
1091 return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
1092 }
1093
1094
1095 /++
1096 Shifts the interval forward or backwards in time by the given duration
1097 (a positive duration shifts the interval forward; a negative duration
1098 shifts it backward). Effectively, it does $(D begin += duration) and
1099 $(D end += duration).
1100
1101 Params:
1102 duration = The duration to shift the interval by.
1103
1104 Throws:
1105 $(REF DateTimeException,std,datetime,date) this interval is empty
1106 or if the resulting interval would be invalid.
1107
1108 Example:
1109 --------------------
1110 auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
1111 auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
1112
1113 interval1.shift(dur!"days"(50));
1114 assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
1115
1116 interval2.shift(dur!"days"(-50));
1117 assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
1118 --------------------
1119 +/
1120 void shift(D)(D duration) pure
1121 if (__traits(compiles, begin + duration))
1122 {
1123 _enforceNotEmpty();
1124
1125 auto begin = _begin + duration;
1126 auto end = _end + duration;
1127
1128 if (!_valid(begin, end))
1129 throw new DateTimeException("Argument would result in an invalid Interval.");
1130
1131 _begin = begin;
1132 _end = end;
1133 }
1134
1135
1136 static if (__traits(compiles, begin.add!"months"(1)) &&
1137 __traits(compiles, begin.add!"years"(1)))
1138 {
1139 /++
1140 Shifts the interval forward or backwards in time by the given number
1141 of years and/or months (a positive number of years and months shifts
1142 the interval forward; a negative number shifts it backward).
1143 It adds the years the given years and months to both begin and end.
1144 It effectively calls `add!"years"()` and then `add!"months"()`
1145 on begin and end with the given number of years and months.
1146
1147 Params:
1148 years = The number of years to shift the interval by.
1149 months = The number of months to shift the interval by.
1150 allowOverflow = Whether the days should be allowed to overflow
1151 on `begin` and `end`, causing their month
1152 to increment.
1153
1154 Throws:
1155 $(REF DateTimeException,std,datetime,date) if this interval is
1156 empty or if the resulting interval would be invalid.
1157
1158 Example:
1159 --------------------
1160 auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1161 auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1162
1163 interval1.shift(2);
1164 assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
1165
1166 interval2.shift(-2);
1167 assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
1168 --------------------
1169 +/
1170 void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
1171 if (isIntegral!T)
1172 {
1173 _enforceNotEmpty();
1174
1175 auto begin = _begin;
1176 auto end = _end;
1177
1178 begin.add!"years"(years, allowOverflow);
1179 begin.add!"months"(months, allowOverflow);
1180 end.add!"years"(years, allowOverflow);
1181 end.add!"months"(months, allowOverflow);
1182
1183 enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
1184
1185 _begin = begin;
1186 _end = end;
1187 }
1188 }
1189
1190
1191 /++
1192 Expands the interval forwards and/or backwards in time. Effectively,
1193 it does $(D begin -= duration) and/or $(D end += duration). Whether
1194 it expands forwards and/or backwards in time is determined by
1195 $(D_PARAM dir).
1196
1197 Params:
1198 duration = The duration to expand the interval by.
1199 dir = The direction in time to expand the interval.
1200
1201 Throws:
1202 $(REF DateTimeException,std,datetime,date) this interval is empty
1203 or if the resulting interval would be invalid.
1204
1205 Example:
1206 --------------------
1207 auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1208 auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1209
1210 interval1.expand(2);
1211 assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
1212
1213 interval2.expand(-2);
1214 assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
1215 --------------------
1216 +/
1217 void expand(D)(D duration, Direction dir = Direction.both) pure
1218 if (__traits(compiles, begin + duration))
1219 {
1220 _enforceNotEmpty();
1221
1222 switch (dir)
1223 {
1224 case Direction.both:
1225 {
1226 auto begin = _begin - duration;
1227 auto end = _end + duration;
1228
1229 if (!_valid(begin, end))
1230 throw new DateTimeException("Argument would result in an invalid Interval.");
1231
1232 _begin = begin;
1233 _end = end;
1234
1235 return;
1236 }
1237 case Direction.fwd:
1238 {
1239 auto end = _end + duration;
1240
1241 if (!_valid(_begin, end))
1242 throw new DateTimeException("Argument would result in an invalid Interval.");
1243 _end = end;
1244
1245 return;
1246 }
1247 case Direction.bwd:
1248 {
1249 auto begin = _begin - duration;
1250
1251 if (!_valid(begin, _end))
1252 throw new DateTimeException("Argument would result in an invalid Interval.");
1253 _begin = begin;
1254
1255 return;
1256 }
1257 default:
1258 assert(0, "Invalid Direction.");
1259 }
1260 }
1261
1262 static if (__traits(compiles, begin.add!"months"(1)) &&
1263 __traits(compiles, begin.add!"years"(1)))
1264 {
1265 /++
1266 Expands the interval forwards and/or backwards in time. Effectively,
1267 it subtracts the given number of months/years from `begin` and
1268 adds them to `end`. Whether it expands forwards and/or backwards
1269 in time is determined by $(D_PARAM dir).
1270
1271 Params:
1272 years = The number of years to expand the interval by.
1273 months = The number of months to expand the interval by.
1274 allowOverflow = Whether the days should be allowed to overflow
1275 on `begin` and `end`, causing their month
1276 to increment.
1277 dir = The direction in time to expand the interval.
1278
1279 Throws:
1280 $(REF DateTimeException,std,datetime,date) if this interval is
1281 empty or if the resulting interval would be invalid.
1282
1283 Example:
1284 --------------------
1285 auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1286 auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1287
1288 interval1.expand(2);
1289 assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
1290
1291 interval2.expand(-2);
1292 assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
1293 --------------------
1294 +/
1295 void expand(T)(T years,
1296 T months = 0,
1297 AllowDayOverflow allowOverflow = AllowDayOverflow.yes,
1298 Direction dir = Direction.both)
1299 if (isIntegral!T)
1300 {
1301 _enforceNotEmpty();
1302
1303 switch (dir)
1304 {
1305 case Direction.both:
1306 {
1307 auto begin = _begin;
1308 auto end = _end;
1309
1310 begin.add!"years"(-years, allowOverflow);
1311 begin.add!"months"(-months, allowOverflow);
1312 end.add!"years"(years, allowOverflow);
1313 end.add!"months"(months, allowOverflow);
1314
1315 enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
1316 _begin = begin;
1317 _end = end;
1318
1319 return;
1320 }
1321 case Direction.fwd:
1322 {
1323 auto end = _end;
1324
1325 end.add!"years"(years, allowOverflow);
1326 end.add!"months"(months, allowOverflow);
1327
1328 enforce(_valid(_begin, end),
1329 new DateTimeException("Argument would result in an invalid Interval."));
1330 _end = end;
1331
1332 return;
1333 }
1334 case Direction.bwd:
1335 {
1336 auto begin = _begin;
1337
1338 begin.add!"years"(-years, allowOverflow);
1339 begin.add!"months"(-months, allowOverflow);
1340
1341 enforce(_valid(begin, _end),
1342 new DateTimeException("Argument would result in an invalid Interval."));
1343 _begin = begin;
1344
1345 return;
1346 }
1347 default:
1348 assert(0, "Invalid Direction.");
1349 }
1350 }
1351 }
1352
1353
1354 /++
1355 Returns a range which iterates forward over the interval, starting
1356 at `begin`, using $(D_PARAM func) to generate each successive time
1357 point.
1358
1359 The range's `front` is the interval's `begin`. $(D_PARAM func) is
1360 used to generate the next `front` when `popFront` is called. If
1361 $(D_PARAM popFirst) is `PopFirst.yes`, then `popFront` is called
1362 before the range is returned (so that `front` is a time point which
1363 $(D_PARAM func) would generate).
1364
1365 If $(D_PARAM func) ever generates a time point less than or equal to the
1366 current `front` of the range, then a
1367 $(REF DateTimeException,std,datetime,date) will be thrown. The range
1368 will be empty and iteration complete when $(D_PARAM func) generates a
1369 time point equal to or beyond the `end` of the interval.
1370
1371 There are helper functions in this module which generate common
1372 delegates to pass to `fwdRange`. Their documentation starts with
1373 "Range-generating function," making them easily searchable.
1374
1375 Params:
1376 func = The function used to generate the time points of the
1377 range over the interval.
1378 popFirst = Whether `popFront` should be called on the range
1379 before returning it.
1380
1381 Throws:
1382 $(REF DateTimeException,std,datetime,date) if this interval is
1383 empty.
1384
1385 Warning:
1386 $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
1387 would be a function pointer to a pure function, but forcing
1388 $(D_PARAM func) to be pure is far too restrictive to be useful, and
1389 in order to have the ease of use of having functions which generate
1390 functions to pass to `fwdRange`, $(D_PARAM func) must be a
1391 delegate.
1392
1393 If $(D_PARAM func) retains state which changes as it is called, then
1394 some algorithms will not work correctly, because the range's
1395 `save` will have failed to have really saved the range's state.
1396 To avoid such bugs, don't pass a delegate which is
1397 not logically pure to `fwdRange`. If $(D_PARAM func) is given the
1398 same time point with two different calls, it must return the same
1399 result both times.
1400
1401 Of course, none of the functions in this module have this problem,
1402 so it's only relevant if when creating a custom delegate.
1403
1404 Example:
1405 --------------------
1406 auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
1407 auto func = delegate (scope const Date date) // For iterating over even-numbered days.
1408 {
1409 if ((date.day & 1) == 0)
1410 return date + dur!"days"(2);
1411
1412 return date + dur!"days"(1);
1413 };
1414 auto range = interval.fwdRange(func);
1415
1416 // An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
1417 assert(range.front == Date(2010, 9, 1));
1418
1419 range.popFront();
1420 assert(range.front == Date(2010, 9, 2));
1421
1422 range.popFront();
1423 assert(range.front == Date(2010, 9, 4));
1424
1425 range.popFront();
1426 assert(range.front == Date(2010, 9, 6));
1427
1428 range.popFront();
1429 assert(range.front == Date(2010, 9, 8));
1430
1431 range.popFront();
1432 assert(range.empty);
1433 --------------------
1434 +/
1435 IntervalRange!(TP, Direction.fwd) fwdRange(TP delegate(scope const TP) func, PopFirst popFirst = PopFirst.no) const
1436 {
1437 _enforceNotEmpty();
1438
1439 auto range = IntervalRange!(TP, Direction.fwd)(this, func);
1440
1441 if (popFirst == PopFirst.yes)
1442 range.popFront();
1443
1444 return range;
1445 }
1446
1447
1448 /++
1449 Returns a range which iterates backwards over the interval, starting
1450 at `end`, using $(D_PARAM func) to generate each successive time
1451 point.
1452
1453 The range's `front` is the interval's `end`. $(D_PARAM func) is
1454 used to generate the next `front` when `popFront` is called. If
1455 $(D_PARAM popFirst) is `PopFirst.yes`, then `popFront` is called
1456 before the range is returned (so that `front` is a time point which
1457 $(D_PARAM func) would generate).
1458
1459 If $(D_PARAM func) ever generates a time point greater than or equal to
1460 the current `front` of the range, then a
1461 $(REF DateTimeException,std,datetime,date) will be thrown. The range
1462 will be empty and iteration complete when $(D_PARAM func) generates a
1463 time point equal to or less than the `begin` of the interval.
1464
1465 There are helper functions in this module which generate common
1466 delegates to pass to `bwdRange`. Their documentation starts with
1467 "Range-generating function," making them easily searchable.
1468
1469 Params:
1470 func = The function used to generate the time points of the
1471 range over the interval.
1472 popFirst = Whether `popFront` should be called on the range
1473 before returning it.
1474
1475 Throws:
1476 $(REF DateTimeException,std,datetime,date) if this interval is
1477 empty.
1478
1479 Warning:
1480 $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
1481 would be a function pointer to a pure function, but forcing
1482 $(D_PARAM func) to be pure is far too restrictive to be useful, and
1483 in order to have the ease of use of having functions which generate
1484 functions to pass to `fwdRange`, $(D_PARAM func) must be a
1485 delegate.
1486
1487 If $(D_PARAM func) retains state which changes as it is called, then
1488 some algorithms will not work correctly, because the range's
1489 `save` will have failed to have really saved the range's state.
1490 To avoid such bugs, don't pass a delegate which is
1491 not logically pure to `fwdRange`. If $(D_PARAM func) is given the
1492 same time point with two different calls, it must return the same
1493 result both times.
1494
1495 Of course, none of the functions in this module have this problem,
1496 so it's only relevant for custom delegates.
1497
1498 Example:
1499 --------------------
1500 auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
1501 auto func = delegate (scope const Date date) // For iterating over even-numbered days.
1502 {
1503 if ((date.day & 1) == 0)
1504 return date - dur!"days"(2);
1505
1506 return date - dur!"days"(1);
1507 };
1508 auto range = interval.bwdRange(func);
1509
1510 // An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
1511 assert(range.front == Date(2010, 9, 9));
1512
1513 range.popFront();
1514 assert(range.front == Date(2010, 9, 8));
1515
1516 range.popFront();
1517 assert(range.front == Date(2010, 9, 6));
1518
1519 range.popFront();
1520 assert(range.front == Date(2010, 9, 4));
1521
1522 range.popFront();
1523 assert(range.front == Date(2010, 9, 2));
1524
1525 range.popFront();
1526 assert(range.empty);
1527 --------------------
1528 +/
1529 IntervalRange!(TP, Direction.bwd) bwdRange(TP delegate(scope const TP) func, PopFirst popFirst = PopFirst.no) const
1530 {
1531 _enforceNotEmpty();
1532
1533 auto range = IntervalRange!(TP, Direction.bwd)(this, func);
1534
1535 if (popFirst == PopFirst.yes)
1536 range.popFront();
1537
1538 return range;
1539 }
1540
1541 /++
1542 Converts this interval to a string.
1543 Params:
1544 w = A `char` accepting
1545 $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
1546 Returns:
1547 A `string` when not using an output range; `void` otherwise.
1548 +/
1549 string toString() const @safe nothrow
1550 {
1551 import std.array : appender;
1552 auto app = appender!string();
1553 try
1554 toString(app);
1555 catch (Exception e)
1556 assert(0, "toString() threw.");
1557 return app.data;
1558 }
1559
1560 /// ditto
1561 void toString(Writer)(ref Writer w) const
1562 if (isOutputRange!(Writer, char))
1563 {
1564 import std.range.primitives : put;
1565 put(w, '[');
1566 _begin.toString(w);
1567 put(w, " - ");
1568 _end.toString(w);
1569 put(w, ')');
1570 }
1571
1572 private:
1573 /+
1574 Throws:
1575 $(REF DateTimeException,std,datetime,date) if this interval is
1576 empty.
1577 +/
1578 void _enforceNotEmpty(size_t line = __LINE__) const pure
1579 {
1580 if (empty)
1581 throw new DateTimeException("Invalid operation for an empty Interval.", __FILE__, line);
1582 }
1583
1584
1585 /+
1586 Whether the given values form a valid time interval.
1587
1588 Params:
1589 begin = The starting point of the interval.
1590 end = The end point of the interval.
1591 +/
1592 static bool _valid(scope const TP begin, scope const TP end) pure nothrow @trusted
1593 {
1594 return begin <= end;
1595 }
1596
1597
1598 pure invariant()
1599 {
1600 assert(_valid(_begin, _end), "Invariant Failure: begin is not before or equal to end.");
1601 }
1602
1603
1604 TP _begin;
1605 TP _end;
1606 }
1607
1608 // Test Interval's constructors.
1609 @safe unittest
1610 {
1611 import std.datetime.date;
1612 import std.datetime.systime;
1613
1614 assertThrown!DateTimeException(Interval!Date(Date(2010, 1, 1), Date(1, 1, 1)));
1615
1616 Interval!Date(Date.init, Date.init);
1617 Interval!TimeOfDay(TimeOfDay.init, TimeOfDay.init);
1618 Interval!DateTime(DateTime.init, DateTime.init);
1619 Interval!SysTime(SysTime(0), SysTime(0));
1620
1621 Interval!DateTime(DateTime.init, dur!"days"(7));
1622
1623 // Verify Examples.
1624 Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1625 assert(Interval!Date(Date(1996, 1, 2), dur!"weeks"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 23)));
1626 assert(Interval!Date(Date(1996, 1, 2), dur!"days"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 5)));
1627 assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"hours"(3)) ==
1628 Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 15, 0, 0)));
1629 assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"minutes"(3)) ==
1630 Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 3, 0)));
1631 assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"seconds"(3)) ==
1632 Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
1633 assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"msecs"(3000)) ==
1634 Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
1635 }
1636
1637 // Test Interval's begin.
1638 @safe unittest
1639 {
1640 import std.datetime.date;
1641
1642 assert(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).begin == Date(1, 1, 1));
1643 assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).begin == Date(2010, 1, 1));
1644 assert(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).begin == Date(1997, 12, 31));
1645
1646 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1647 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1648 assert(cInterval.begin == Date(2010, 7, 4));
1649 assert(iInterval.begin == Date(2010, 7, 4));
1650
1651 // Verify Examples.
1652 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin == Date(1996, 1, 2));
1653 }
1654
1655 // Test Interval's end.
1656 @safe unittest
1657 {
1658 import std.datetime.date;
1659
1660 assert(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).end == Date(2010, 1, 1));
1661 assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).end == Date(2010, 1, 1));
1662 assert(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).end == Date(1998, 1, 1));
1663
1664 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1665 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1666 assert(cInterval.end == Date(2012, 1, 7));
1667 assert(iInterval.end == Date(2012, 1, 7));
1668
1669 // Verify Examples.
1670 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end == Date(2012, 3, 1));
1671 }
1672
1673 // Test Interval's length.
1674 @safe unittest
1675 {
1676 import std.datetime.date;
1677 import std.datetime.systime;
1678
1679 assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).length == dur!"days"(0));
1680 assert(Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).length == dur!"days"(90));
1681 assert(Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).length == dur!"seconds"(42_727));
1682 assert(Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).length ==
1683 dur!"seconds"(129_127));
1684 assert(Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)),SysTime(DateTime(2010, 1, 2, 12, 22, 7))).length ==
1685 dur!"seconds"(129_127));
1686
1687 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1688 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1689 assert(cInterval.length != Duration.zero);
1690 assert(iInterval.length != Duration.zero);
1691
1692 // Verify Examples.
1693 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length == dur!"days"(5903));
1694 }
1695
1696 // Test Interval's empty.
1697 @safe unittest
1698 {
1699 import std.datetime.date;
1700 import std.datetime.systime;
1701
1702 assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).empty);
1703 assert(!Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).empty);
1704 assert(!Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).empty);
1705 assert(!Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).empty);
1706 assert(!Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)), SysTime(DateTime(2010, 1, 2, 12, 22, 7))).empty);
1707
1708 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1709 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1710 assert(!cInterval.empty);
1711 assert(!iInterval.empty);
1712
1713 // Verify Examples.
1714 assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
1715 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
1716 }
1717
1718 // Test Interval's contains(time point).
1719 @safe unittest
1720 {
1721 import std.datetime.date;
1722
1723 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1724
1725 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(Date(2010, 7, 4)));
1726
1727 assert(!interval.contains(Date(2009, 7, 4)));
1728 assert(!interval.contains(Date(2010, 7, 3)));
1729 assert(interval.contains(Date(2010, 7, 4)));
1730 assert(interval.contains(Date(2010, 7, 5)));
1731 assert(interval.contains(Date(2011, 7, 1)));
1732 assert(interval.contains(Date(2012, 1, 6)));
1733 assert(!interval.contains(Date(2012, 1, 7)));
1734 assert(!interval.contains(Date(2012, 1, 8)));
1735 assert(!interval.contains(Date(2013, 1, 7)));
1736
1737 const cdate = Date(2010, 7, 6);
1738 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1739 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1740 assert(interval.contains(cdate));
1741 assert(cInterval.contains(cdate));
1742 assert(iInterval.contains(cdate));
1743
1744 // Verify Examples.
1745 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
1746 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
1747 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
1748 }
1749
1750 // Test Interval's contains(Interval).
1751 @safe unittest
1752 {
1753 import std.datetime.date;
1754
1755 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1756
1757 assertThrown!DateTimeException(interval.contains(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
1758 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(interval));
1759 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4),dur!"days"(0)).contains(
1760 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
1761
1762 assert(interval.contains(interval));
1763 assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
1764 assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
1765 assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
1766 assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
1767 assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
1768 assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
1769 assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
1770 assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
1771 assert(interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
1772 assert(!interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
1773 assert(!interval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
1774 assert(!interval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
1775
1776 assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).contains(interval));
1777 assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).contains(interval));
1778 assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).contains(interval));
1779 assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).contains(interval));
1780 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).contains(interval));
1781 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).contains(interval));
1782 assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).contains(interval));
1783 assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).contains(interval));
1784 assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).contains(interval));
1785 assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).contains(interval));
1786 assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).contains(interval));
1787 assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).contains(interval));
1788
1789 assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
1790 assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
1791 assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
1792 assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
1793 assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
1794 assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
1795
1796 assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
1797 assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
1798 assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
1799 assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
1800 assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
1801 assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
1802
1803 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1804 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1805 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1806 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1807 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1808 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1809 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1810 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1811 assert(interval.contains(interval));
1812 assert(interval.contains(cInterval));
1813 assert(interval.contains(iInterval));
1814 assert(!interval.contains(posInfInterval));
1815 assert(!interval.contains(cPosInfInterval));
1816 assert(!interval.contains(iPosInfInterval));
1817 assert(!interval.contains(negInfInterval));
1818 assert(!interval.contains(cNegInfInterval));
1819 assert(!interval.contains(iNegInfInterval));
1820 assert(cInterval.contains(interval));
1821 assert(cInterval.contains(cInterval));
1822 assert(cInterval.contains(iInterval));
1823 assert(!cInterval.contains(posInfInterval));
1824 assert(!cInterval.contains(cPosInfInterval));
1825 assert(!cInterval.contains(iPosInfInterval));
1826 assert(!cInterval.contains(negInfInterval));
1827 assert(!cInterval.contains(cNegInfInterval));
1828 assert(!cInterval.contains(iNegInfInterval));
1829 assert(iInterval.contains(interval));
1830 assert(iInterval.contains(cInterval));
1831 assert(iInterval.contains(iInterval));
1832 assert(!iInterval.contains(posInfInterval));
1833 assert(!iInterval.contains(cPosInfInterval));
1834 assert(!iInterval.contains(iPosInfInterval));
1835 assert(!iInterval.contains(negInfInterval));
1836 assert(!iInterval.contains(cNegInfInterval));
1837 assert(!iInterval.contains(iNegInfInterval));
1838
1839 // Verify Examples.
1840 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
1841 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
1842 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
1843 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
1844 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
1845 Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
1846
1847 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
1848
1849 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
1850 }
1851
1852 // Test Interval's isBefore(time point).
1853 @safe unittest
1854 {
1855 import std.datetime.date;
1856
1857 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1858
1859 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(Date(2010, 7, 4)));
1860
1861 assert(!interval.isBefore(Date(2009, 7, 3)));
1862 assert(!interval.isBefore(Date(2010, 7, 3)));
1863 assert(!interval.isBefore(Date(2010, 7, 4)));
1864 assert(!interval.isBefore(Date(2010, 7, 5)));
1865 assert(!interval.isBefore(Date(2011, 7, 1)));
1866 assert(!interval.isBefore(Date(2012, 1, 6)));
1867 assert(interval.isBefore(Date(2012, 1, 7)));
1868 assert(interval.isBefore(Date(2012, 1, 8)));
1869 assert(interval.isBefore(Date(2013, 1, 7)));
1870
1871 const cdate = Date(2010, 7, 6);
1872 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1873 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1874 assert(!interval.isBefore(cdate));
1875 assert(!cInterval.isBefore(cdate));
1876 assert(!iInterval.isBefore(cdate));
1877
1878 // Verify Examples.
1879 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
1880 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
1881 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
1882 }
1883
1884 // Test Interval's isBefore(Interval).
1885 @safe unittest
1886 {
1887 import std.datetime.date;
1888
1889 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1890
1891 assertThrown!DateTimeException(interval.isBefore(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
1892 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(interval));
1893 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(
1894 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
1895
1896 assert(!interval.isBefore(interval));
1897 assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
1898 assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
1899 assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
1900 assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
1901 assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
1902 assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
1903 assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
1904 assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
1905 assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
1906 assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
1907 assert(interval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
1908 assert(interval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
1909
1910 assert(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isBefore(interval));
1911 assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isBefore(interval));
1912 assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isBefore(interval));
1913 assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isBefore(interval));
1914 assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isBefore(interval));
1915 assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isBefore(interval));
1916 assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isBefore(interval));
1917 assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isBefore(interval));
1918 assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isBefore(interval));
1919 assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isBefore(interval));
1920 assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isBefore(interval));
1921 assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isBefore(interval));
1922
1923 assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
1924 assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
1925 assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
1926 assert(!interval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
1927 assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
1928 assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
1929
1930 assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
1931 assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
1932 assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
1933 assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
1934 assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
1935 assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
1936
1937 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1938 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1939 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1940 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1941 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1942 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1943 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1944 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1945 assert(!interval.isBefore(interval));
1946 assert(!interval.isBefore(cInterval));
1947 assert(!interval.isBefore(iInterval));
1948 assert(!interval.isBefore(posInfInterval));
1949 assert(!interval.isBefore(cPosInfInterval));
1950 assert(!interval.isBefore(iPosInfInterval));
1951 assert(!interval.isBefore(negInfInterval));
1952 assert(!interval.isBefore(cNegInfInterval));
1953 assert(!interval.isBefore(iNegInfInterval));
1954 assert(!cInterval.isBefore(interval));
1955 assert(!cInterval.isBefore(cInterval));
1956 assert(!cInterval.isBefore(iInterval));
1957 assert(!cInterval.isBefore(posInfInterval));
1958 assert(!cInterval.isBefore(cPosInfInterval));
1959 assert(!cInterval.isBefore(iPosInfInterval));
1960 assert(!cInterval.isBefore(negInfInterval));
1961 assert(!cInterval.isBefore(cNegInfInterval));
1962 assert(!cInterval.isBefore(iNegInfInterval));
1963 assert(!iInterval.isBefore(interval));
1964 assert(!iInterval.isBefore(cInterval));
1965 assert(!iInterval.isBefore(iInterval));
1966 assert(!iInterval.isBefore(posInfInterval));
1967 assert(!iInterval.isBefore(cPosInfInterval));
1968 assert(!iInterval.isBefore(iPosInfInterval));
1969 assert(!iInterval.isBefore(negInfInterval));
1970 assert(!iInterval.isBefore(cNegInfInterval));
1971 assert(!iInterval.isBefore(iNegInfInterval));
1972
1973 // Verify Examples.
1974 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
1975 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
1976 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
1977 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
1978 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
1979 Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
1980
1981 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
1982 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
1983
1984 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
1985 }
1986
1987 // Test Interval's isAfter(time point).
1988 @safe unittest
1989 {
1990 import std.datetime.date;
1991
1992 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1993
1994 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(Date(2010, 7, 4)));
1995
1996 assert(interval.isAfter(Date(2009, 7, 4)));
1997 assert(interval.isAfter(Date(2010, 7, 3)));
1998 assert(!interval.isAfter(Date(2010, 7, 4)));
1999 assert(!interval.isAfter(Date(2010, 7, 5)));
2000 assert(!interval.isAfter(Date(2011, 7, 1)));
2001 assert(!interval.isAfter(Date(2012, 1, 6)));
2002 assert(!interval.isAfter(Date(2012, 1, 7)));
2003 assert(!interval.isAfter(Date(2012, 1, 8)));
2004 assert(!interval.isAfter(Date(2013, 1, 7)));
2005
2006 const cdate = Date(2010, 7, 6);
2007 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2008 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2009 assert(!interval.isAfter(cdate));
2010 assert(!cInterval.isAfter(cdate));
2011 assert(!iInterval.isAfter(cdate));
2012
2013 // Verify Examples.
2014 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
2015 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
2016 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
2017 }
2018
2019 // Test Interval's isAfter(Interval).
2020 @safe unittest
2021 {
2022 import std.datetime.date;
2023
2024 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2025
2026 assertThrown!DateTimeException(interval.isAfter(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2027 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(interval));
2028 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(
2029 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2030
2031 assert(!interval.isAfter(interval));
2032 assert(interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2033 assert(!interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
2034 assert(interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
2035 assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
2036 assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
2037 assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
2038 assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
2039 assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
2040 assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
2041 assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
2042 assert(!interval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
2043 assert(!interval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2044
2045 assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAfter(interval));
2046 assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAfter(interval));
2047 assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAfter(interval));
2048 assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAfter(interval));
2049 assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAfter(interval));
2050 assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAfter(interval));
2051 assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAfter(interval));
2052 assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAfter(interval));
2053 assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAfter(interval));
2054 assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAfter(interval));
2055 assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAfter(interval));
2056 assert(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAfter(interval));
2057
2058 assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
2059 assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
2060 assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
2061 assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
2062 assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
2063 assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
2064
2065 assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
2066 assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
2067 assert(!interval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
2068 assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
2069 assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
2070 assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
2071
2072 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2073 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2074 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2075 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2076 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2077 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2078 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2079 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2080 assert(!interval.isAfter(interval));
2081 assert(!interval.isAfter(cInterval));
2082 assert(!interval.isAfter(iInterval));
2083 assert(!interval.isAfter(posInfInterval));
2084 assert(!interval.isAfter(cPosInfInterval));
2085 assert(!interval.isAfter(iPosInfInterval));
2086 assert(!interval.isAfter(negInfInterval));
2087 assert(!interval.isAfter(cNegInfInterval));
2088 assert(!interval.isAfter(iNegInfInterval));
2089 assert(!cInterval.isAfter(interval));
2090 assert(!cInterval.isAfter(cInterval));
2091 assert(!cInterval.isAfter(iInterval));
2092 assert(!cInterval.isAfter(posInfInterval));
2093 assert(!cInterval.isAfter(cPosInfInterval));
2094 assert(!cInterval.isAfter(iPosInfInterval));
2095 assert(!cInterval.isAfter(negInfInterval));
2096 assert(!cInterval.isAfter(cNegInfInterval));
2097 assert(!cInterval.isAfter(iNegInfInterval));
2098 assert(!iInterval.isAfter(interval));
2099 assert(!iInterval.isAfter(cInterval));
2100 assert(!iInterval.isAfter(iInterval));
2101 assert(!iInterval.isAfter(posInfInterval));
2102 assert(!iInterval.isAfter(cPosInfInterval));
2103 assert(!iInterval.isAfter(iPosInfInterval));
2104 assert(!iInterval.isAfter(negInfInterval));
2105 assert(!iInterval.isAfter(cNegInfInterval));
2106 assert(!iInterval.isAfter(iNegInfInterval));
2107
2108 // Verify Examples.
2109 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
2110 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
2111 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
2112 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
2113 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
2114 Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
2115
2116 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
2117
2118 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
2119 }
2120
2121 // Test Interval's intersects().
2122 @safe unittest
2123 {
2124 import std.datetime.date;
2125
2126 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2127
2128 assertThrown!DateTimeException(interval.intersects(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2129 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(interval));
2130 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(
2131 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2132
2133 assert(interval.intersects(interval));
2134 assert(!interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2135 assert(interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
2136 assert(!interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
2137 assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
2138 assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
2139 assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
2140 assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
2141 assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
2142 assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
2143 assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
2144 assert(!interval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
2145 assert(!interval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2146
2147 assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersects(interval));
2148 assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersects(interval));
2149 assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersects(interval));
2150 assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersects(interval));
2151 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersects(interval));
2152 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersects(interval));
2153 assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersects(interval));
2154 assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersects(interval));
2155 assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersects(interval));
2156 assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersects(interval));
2157 assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersects(interval));
2158 assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersects(interval));
2159
2160 assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
2161 assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
2162 assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
2163 assert(interval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
2164 assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
2165 assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
2166
2167 assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
2168 assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
2169 assert(interval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
2170 assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
2171 assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
2172 assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
2173
2174 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2175 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2176 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2177 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2178 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2179 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2180 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2181 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2182 assert(interval.intersects(interval));
2183 assert(interval.intersects(cInterval));
2184 assert(interval.intersects(iInterval));
2185 assert(interval.intersects(posInfInterval));
2186 assert(interval.intersects(cPosInfInterval));
2187 assert(interval.intersects(iPosInfInterval));
2188 assert(interval.intersects(negInfInterval));
2189 assert(interval.intersects(cNegInfInterval));
2190 assert(interval.intersects(iNegInfInterval));
2191 assert(cInterval.intersects(interval));
2192 assert(cInterval.intersects(cInterval));
2193 assert(cInterval.intersects(iInterval));
2194 assert(cInterval.intersects(posInfInterval));
2195 assert(cInterval.intersects(cPosInfInterval));
2196 assert(cInterval.intersects(iPosInfInterval));
2197 assert(cInterval.intersects(negInfInterval));
2198 assert(cInterval.intersects(cNegInfInterval));
2199 assert(cInterval.intersects(iNegInfInterval));
2200 assert(iInterval.intersects(interval));
2201 assert(iInterval.intersects(cInterval));
2202 assert(iInterval.intersects(iInterval));
2203 assert(iInterval.intersects(posInfInterval));
2204 assert(iInterval.intersects(cPosInfInterval));
2205 assert(iInterval.intersects(iPosInfInterval));
2206 assert(iInterval.intersects(negInfInterval));
2207 assert(iInterval.intersects(cNegInfInterval));
2208 assert(iInterval.intersects(iNegInfInterval));
2209
2210 // Verify Examples.
2211 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
2212 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
2213 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
2214 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
2215 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
2216 Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
2217
2218 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
2219 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
2220
2221 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
2222 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2000, 1, 2))));
2223 }
2224
2225 // Test Interval's intersection().
2226 @safe unittest
2227 {
2228 import std.datetime.date;
2229
2230 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2231
2232 assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2233 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(interval));
2234 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(
2235 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2236
2237 assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2238 assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
2239 assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
2240 assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2241
2242 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersection(interval));
2243 assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersection(interval));
2244 assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersection(interval));
2245 assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersection(interval));
2246
2247 assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 7))));
2248 assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 8))));
2249
2250 assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 3))));
2251 assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 4))));
2252
2253 assert(interval.intersection(interval) == interval);
2254 assert(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
2255 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2256 assert(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
2257 Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
2258 assert(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
2259 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2260 assert(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
2261 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2262 assert(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
2263 Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
2264 assert(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
2265 Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
2266 assert(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
2267 Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2268 assert(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
2269 Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2270
2271 assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersection(interval) ==
2272 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2273 assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersection(interval) ==
2274 Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
2275 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersection(interval) ==
2276 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2277 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersection(interval) ==
2278 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2279 assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersection(interval) ==
2280 Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
2281 assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersection(interval) ==
2282 Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
2283 assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersection(interval) ==
2284 Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2285 assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersection(interval) ==
2286 Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2287
2288 assert(interval.intersection(PosInfInterval!Date(Date(2010, 7, 3))) ==
2289 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2290 assert(interval.intersection(PosInfInterval!Date(Date(2010, 7, 4))) ==
2291 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2292 assert(interval.intersection(PosInfInterval!Date(Date(2010, 7, 5))) ==
2293 Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
2294 assert(interval.intersection(PosInfInterval!Date(Date(2012, 1, 6))) ==
2295 Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2296
2297 assert(interval.intersection(NegInfInterval!Date(Date(2010, 7, 5))) ==
2298 Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
2299 assert(interval.intersection(NegInfInterval!Date(Date(2012, 1, 6))) ==
2300 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 6)));
2301 assert(interval.intersection(NegInfInterval!Date(Date(2012, 1, 7))) ==
2302 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2303 assert(interval.intersection(NegInfInterval!Date(Date(2012, 1, 8))) ==
2304 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2305
2306 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2307 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2308 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2309 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2310 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2311 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2312 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2313 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2314 assert(!interval.intersection(interval).empty);
2315 assert(!interval.intersection(cInterval).empty);
2316 assert(!interval.intersection(iInterval).empty);
2317 assert(!interval.intersection(posInfInterval).empty);
2318 assert(!interval.intersection(cPosInfInterval).empty);
2319 assert(!interval.intersection(iPosInfInterval).empty);
2320 assert(!interval.intersection(negInfInterval).empty);
2321 assert(!interval.intersection(cNegInfInterval).empty);
2322 assert(!interval.intersection(iNegInfInterval).empty);
2323 assert(!cInterval.intersection(interval).empty);
2324 assert(!cInterval.intersection(cInterval).empty);
2325 assert(!cInterval.intersection(iInterval).empty);
2326 assert(!cInterval.intersection(posInfInterval).empty);
2327 assert(!cInterval.intersection(cPosInfInterval).empty);
2328 assert(!cInterval.intersection(iPosInfInterval).empty);
2329 assert(!cInterval.intersection(negInfInterval).empty);
2330 assert(!cInterval.intersection(cNegInfInterval).empty);
2331 assert(!cInterval.intersection(iNegInfInterval).empty);
2332 assert(!iInterval.intersection(interval).empty);
2333 assert(!iInterval.intersection(cInterval).empty);
2334 assert(!iInterval.intersection(iInterval).empty);
2335 assert(!iInterval.intersection(posInfInterval).empty);
2336 assert(!iInterval.intersection(cPosInfInterval).empty);
2337 assert(!iInterval.intersection(iPosInfInterval).empty);
2338 assert(!iInterval.intersection(negInfInterval).empty);
2339 assert(!iInterval.intersection(cNegInfInterval).empty);
2340 assert(!iInterval.intersection(iNegInfInterval).empty);
2341
2342 // Verify Examples.
2343 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2344 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
2345 Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
2346 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2347 Interval!Date(Date(1999, 1, 12),Date(2011, 9, 17))) ==
2348 Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
2349
2350 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2351 PosInfInterval!Date(Date(1990, 7, 6))) ==
2352 Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
2353 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2354 PosInfInterval!Date(Date(1999, 1, 12))) ==
2355 Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
2356
2357 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2358 NegInfInterval!Date(Date(1999, 7, 6))) ==
2359 Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
2360 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2361 NegInfInterval!Date(Date(2013, 1, 12))) ==
2362 Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
2363 }
2364
2365 // Test Interval's isAdjacent().
2366 @safe unittest
2367 {
2368 import std.datetime.date;
2369
2370 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2371
2372 static void testInterval(scope const Interval!Date interval1, scope const Interval!Date interval2)
2373 {
2374 interval1.isAdjacent(interval2);
2375 }
2376
2377 assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2378 assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
2379 assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),
2380 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2381
2382 assert(!interval.isAdjacent(interval));
2383 assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2384 assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
2385 assert(interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
2386 assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
2387 assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
2388 assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
2389 assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
2390 assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
2391 assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
2392 assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
2393 assert(interval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
2394 assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2395
2396 assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAdjacent(interval));
2397 assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAdjacent(interval));
2398 assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAdjacent(interval));
2399 assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAdjacent(interval));
2400 assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAdjacent(interval));
2401 assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAdjacent(interval));
2402 assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAdjacent(interval));
2403 assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAdjacent(interval));
2404 assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAdjacent(interval));
2405 assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAdjacent(interval));
2406 assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAdjacent(interval));
2407 assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAdjacent(interval));
2408
2409 assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
2410 assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
2411 assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
2412 assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
2413 assert(interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
2414 assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
2415
2416 assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
2417 assert(interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
2418 assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
2419 assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
2420 assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
2421 assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
2422
2423 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2424 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2425 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2426 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2427 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2428 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2429 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2430 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2431 assert(!interval.isAdjacent(interval));
2432 assert(!interval.isAdjacent(cInterval));
2433 assert(!interval.isAdjacent(iInterval));
2434 assert(!interval.isAdjacent(posInfInterval));
2435 assert(!interval.isAdjacent(cPosInfInterval));
2436 assert(!interval.isAdjacent(iPosInfInterval));
2437 assert(!interval.isAdjacent(negInfInterval));
2438 assert(!interval.isAdjacent(cNegInfInterval));
2439 assert(!interval.isAdjacent(iNegInfInterval));
2440 assert(!cInterval.isAdjacent(interval));
2441 assert(!cInterval.isAdjacent(cInterval));
2442 assert(!cInterval.isAdjacent(iInterval));
2443 assert(!cInterval.isAdjacent(posInfInterval));
2444 assert(!cInterval.isAdjacent(cPosInfInterval));
2445 assert(!cInterval.isAdjacent(iPosInfInterval));
2446 assert(!cInterval.isAdjacent(negInfInterval));
2447 assert(!cInterval.isAdjacent(cNegInfInterval));
2448 assert(!cInterval.isAdjacent(iNegInfInterval));
2449 assert(!iInterval.isAdjacent(interval));
2450 assert(!iInterval.isAdjacent(cInterval));
2451 assert(!iInterval.isAdjacent(iInterval));
2452 assert(!iInterval.isAdjacent(posInfInterval));
2453 assert(!iInterval.isAdjacent(cPosInfInterval));
2454 assert(!iInterval.isAdjacent(iPosInfInterval));
2455 assert(!iInterval.isAdjacent(negInfInterval));
2456 assert(!iInterval.isAdjacent(cNegInfInterval));
2457 assert(!iInterval.isAdjacent(iNegInfInterval));
2458
2459 // Verify Examples.
2460 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
2461 Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
2462 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
2463 Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
2464 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
2465 Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
2466
2467 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
2468 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
2469
2470 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
2471 assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)) .isAdjacent(NegInfInterval!Date(Date(2000, 1, 2))));
2472 }
2473
2474 // Test Interval's merge().
2475 @safe unittest
2476 {
2477 import std.datetime.date;
2478
2479 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2480
testInterval(I)2481 static void testInterval(I)(scope const Interval!Date interval1, scope const I interval2)
2482 {
2483 interval1.merge(interval2);
2484 }
2485
2486 assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2487 assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
2488 assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),
2489 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2490
2491 assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2492 assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2493
2494 assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)), interval));
2495 assertThrown!DateTimeException(testInterval(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)), interval));
2496
2497 assertThrown!DateTimeException(testInterval(interval, PosInfInterval!Date(Date(2012, 1, 8))));
2498
2499 assertThrown!DateTimeException(testInterval(interval, NegInfInterval!Date(Date(2010, 7, 3))));
2500
2501 assert(interval.merge(interval) == interval);
2502 assert(interval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
2503 Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
2504 assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
2505 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2506 assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
2507 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2508 assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
2509 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2510 assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
2511 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
2512 assert(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
2513 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2514 assert(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
2515 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2516 assert(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
2517 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2518 assert(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
2519 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2520 assert(interval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
2521 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2522
2523 assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).merge(interval) ==
2524 Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
2525 assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).merge(interval) ==
2526 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2527 assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).merge(interval) ==
2528 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2529 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).merge(interval) ==
2530 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2531 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).merge(interval) ==
2532 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
2533 assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).merge(interval) ==
2534 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2535 assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).merge(interval) ==
2536 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2537 assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).merge(interval) ==
2538 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2539 assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).merge(interval) ==
2540 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2541 assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).merge(interval) ==
2542 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2543
2544 assert(interval.merge(PosInfInterval!Date(Date(2010, 7, 3))) ==
2545 PosInfInterval!Date(Date(2010, 7, 3)));
2546 assert(interval.merge(PosInfInterval!Date(Date(2010, 7, 4))) ==
2547 PosInfInterval!Date(Date(2010, 7, 4)));
2548 assert(interval.merge(PosInfInterval!Date(Date(2010, 7, 5))) ==
2549 PosInfInterval!Date(Date(2010, 7, 4)));
2550 assert(interval.merge(PosInfInterval!Date(Date(2012, 1, 6))) ==
2551 PosInfInterval!Date(Date(2010, 7, 4)));
2552 assert(interval.merge(PosInfInterval!Date(Date(2012, 1, 7))) ==
2553 PosInfInterval!Date(Date(2010, 7, 4)));
2554
2555 assert(interval.merge(NegInfInterval!Date(Date(2010, 7, 4))) ==
2556 NegInfInterval!Date(Date(2012, 1, 7)));
2557 assert(interval.merge(NegInfInterval!Date(Date(2010, 7, 5))) ==
2558 NegInfInterval!Date(Date(2012, 1, 7)));
2559 assert(interval.merge(NegInfInterval!Date(Date(2012, 1, 6))) ==
2560 NegInfInterval!Date(Date(2012, 1, 7)));
2561 assert(interval.merge(NegInfInterval!Date(Date(2012, 1, 7))) ==
2562 NegInfInterval!Date(Date(2012, 1, 7)));
2563 assert(interval.merge(NegInfInterval!Date(Date(2012, 1, 8))) ==
2564 NegInfInterval!Date(Date(2012, 1, 8)));
2565
2566 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2567 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2568 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2569 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2570 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2571 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2572 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2573 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2574 assert(!interval.merge(interval).empty);
2575 assert(!interval.merge(cInterval).empty);
2576 assert(!interval.merge(iInterval).empty);
2577 assert(!interval.merge(posInfInterval).empty);
2578 assert(!interval.merge(cPosInfInterval).empty);
2579 assert(!interval.merge(iPosInfInterval).empty);
2580 assert(!interval.merge(negInfInterval).empty);
2581 assert(!interval.merge(cNegInfInterval).empty);
2582 assert(!interval.merge(iNegInfInterval).empty);
2583 assert(!cInterval.merge(interval).empty);
2584 assert(!cInterval.merge(cInterval).empty);
2585 assert(!cInterval.merge(iInterval).empty);
2586 assert(!cInterval.merge(posInfInterval).empty);
2587 assert(!cInterval.merge(cPosInfInterval).empty);
2588 assert(!cInterval.merge(iPosInfInterval).empty);
2589 assert(!cInterval.merge(negInfInterval).empty);
2590 assert(!cInterval.merge(cNegInfInterval).empty);
2591 assert(!cInterval.merge(iNegInfInterval).empty);
2592 assert(!iInterval.merge(interval).empty);
2593 assert(!iInterval.merge(cInterval).empty);
2594 assert(!iInterval.merge(iInterval).empty);
2595 assert(!iInterval.merge(posInfInterval).empty);
2596 assert(!iInterval.merge(cPosInfInterval).empty);
2597 assert(!iInterval.merge(iPosInfInterval).empty);
2598 assert(!iInterval.merge(negInfInterval).empty);
2599 assert(!iInterval.merge(cNegInfInterval).empty);
2600 assert(!iInterval.merge(iNegInfInterval).empty);
2601
2602 // Verify Examples.
2603 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
2604 Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
2605 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
2606 Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
2607
2608 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(1990, 7, 6))) ==
2609 PosInfInterval!Date(Date(1990, 7 , 6)));
2610 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(2012, 3, 1))) ==
2611 PosInfInterval!Date(Date(1996, 1 , 2)));
2612
2613 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1996, 1, 2))) ==
2614 NegInfInterval!Date(Date(2012, 3 , 1)));
2615 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) ==
2616 NegInfInterval!Date(Date(2013, 1 , 12)));
2617 }
2618
2619 // Test Interval's span().
2620 @safe unittest
2621 {
2622 import std.datetime.date;
2623
2624 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2625
2626 static void testInterval(scope const Interval!Date interval1, scope const Interval!Date interval2)
2627 {
2628 interval1.span(interval2);
2629 }
2630
2631 assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2632 assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),interval));
2633 assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),
2634 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2635
2636 assert(interval.span(interval) == interval);
2637 assert(interval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
2638 Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
2639 assert(interval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
2640 Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
2641 assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
2642 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2643 assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
2644 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2645 assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
2646 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2647 assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
2648 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
2649 assert(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
2650 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2651 assert(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
2652 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2653 assert(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
2654 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2655 assert(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
2656 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2657 assert(interval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
2658 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2659 assert(interval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
2660 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
2661
2662 assert(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).span(interval) ==
2663 Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
2664 assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).span(interval) ==
2665 Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
2666 assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).span(interval) ==
2667 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2668 assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).span(interval) ==
2669 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2670 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).span(interval) ==
2671 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2672 assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).span(interval) ==
2673 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
2674 assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).span(interval) ==
2675 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2676 assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).span(interval) ==
2677 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2678 assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).span(interval) ==
2679 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2680 assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).span(interval) ==
2681 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2682 assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).span(interval) ==
2683 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2684 assert(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).span(interval) ==
2685 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
2686
2687 assert(interval.span(PosInfInterval!Date(Date(2010, 7, 3))) == PosInfInterval!Date(Date(2010, 7, 3)));
2688 assert(interval.span(PosInfInterval!Date(Date(2010, 7, 4))) == PosInfInterval!Date(Date(2010, 7, 4)));
2689 assert(interval.span(PosInfInterval!Date(Date(2010, 7, 5))) == PosInfInterval!Date(Date(2010, 7, 4)));
2690 assert(interval.span(PosInfInterval!Date(Date(2012, 1, 6))) == PosInfInterval!Date(Date(2010, 7, 4)));
2691 assert(interval.span(PosInfInterval!Date(Date(2012, 1, 7))) == PosInfInterval!Date(Date(2010, 7, 4)));
2692 assert(interval.span(PosInfInterval!Date(Date(2012, 1, 8))) == PosInfInterval!Date(Date(2010, 7, 4)));
2693
2694 assert(interval.span(NegInfInterval!Date(Date(2010, 7, 3))) == NegInfInterval!Date(Date(2012, 1, 7)));
2695 assert(interval.span(NegInfInterval!Date(Date(2010, 7, 4))) == NegInfInterval!Date(Date(2012, 1, 7)));
2696 assert(interval.span(NegInfInterval!Date(Date(2010, 7, 5))) == NegInfInterval!Date(Date(2012, 1, 7)));
2697 assert(interval.span(NegInfInterval!Date(Date(2012, 1, 6))) == NegInfInterval!Date(Date(2012, 1, 7)));
2698 assert(interval.span(NegInfInterval!Date(Date(2012, 1, 7))) == NegInfInterval!Date(Date(2012, 1, 7)));
2699 assert(interval.span(NegInfInterval!Date(Date(2012, 1, 8))) == NegInfInterval!Date(Date(2012, 1, 8)));
2700
2701 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2702 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2703 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2704 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2705 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2706 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2707 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2708 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2709 assert(!interval.span(interval).empty);
2710 assert(!interval.span(cInterval).empty);
2711 assert(!interval.span(iInterval).empty);
2712 assert(!interval.span(posInfInterval).empty);
2713 assert(!interval.span(cPosInfInterval).empty);
2714 assert(!interval.span(iPosInfInterval).empty);
2715 assert(!interval.span(negInfInterval).empty);
2716 assert(!interval.span(cNegInfInterval).empty);
2717 assert(!interval.span(iNegInfInterval).empty);
2718 assert(!cInterval.span(interval).empty);
2719 assert(!cInterval.span(cInterval).empty);
2720 assert(!cInterval.span(iInterval).empty);
2721 assert(!cInterval.span(posInfInterval).empty);
2722 assert(!cInterval.span(cPosInfInterval).empty);
2723 assert(!cInterval.span(iPosInfInterval).empty);
2724 assert(!cInterval.span(negInfInterval).empty);
2725 assert(!cInterval.span(cNegInfInterval).empty);
2726 assert(!cInterval.span(iNegInfInterval).empty);
2727 assert(!iInterval.span(interval).empty);
2728 assert(!iInterval.span(cInterval).empty);
2729 assert(!iInterval.span(iInterval).empty);
2730 assert(!iInterval.span(posInfInterval).empty);
2731 assert(!iInterval.span(cPosInfInterval).empty);
2732 assert(!iInterval.span(iPosInfInterval).empty);
2733 assert(!iInterval.span(negInfInterval).empty);
2734 assert(!iInterval.span(cNegInfInterval).empty);
2735 assert(!iInterval.span(iNegInfInterval).empty);
2736
2737 // Verify Examples.
2738 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) ==
2739 Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
2740 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
2741 Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
2742
2743 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(1990, 7, 6))) ==
2744 PosInfInterval!Date(Date(1990, 7 , 6)));
2745 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(2050, 1, 1))) ==
2746 PosInfInterval!Date(Date(1996, 1 , 2)));
2747
2748 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1602, 5, 21))) ==
2749 NegInfInterval!Date(Date(2012, 3 , 1)));
2750 assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) ==
2751 NegInfInterval!Date(Date(2013, 1 , 12)));
2752 }
2753
2754 // Test Interval's shift(duration).
2755 @safe unittest
2756 {
2757 import std.datetime.date;
2758
2759 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2760
2761 static void testIntervalFail(Interval!Date interval, scope const Duration duration)
2762 {
2763 interval.shift(duration);
2764 }
2765
2766 assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
2767
testInterval(I)2768 static void testInterval(I)(I interval, scope const Duration duration,
2769 scope const I expected, size_t line = __LINE__)
2770 {
2771 interval.shift(duration);
2772 assert(interval == expected);
2773 }
2774
2775 testInterval(interval, dur!"days"(22), Interval!Date(Date(2010, 7, 26), Date(2012, 1, 29)));
2776 testInterval(interval, dur!"days"(-22), Interval!Date(Date(2010, 6, 12), Date(2011, 12, 16)));
2777
2778 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2779 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2780 static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
2781 static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
2782
2783 // Verify Examples.
2784 auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
2785 auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
2786
2787 interval1.shift(dur!"days"(50));
2788 assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
2789
2790 interval2.shift(dur!"days"(-50));
2791 assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
2792 }
2793
2794 // Test Interval's shift(int, int, AllowDayOverflow).
2795 @safe unittest
2796 {
2797 import std.datetime.date;
2798
2799 {
2800 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2801
2802 static void testIntervalFail(Interval!Date interval, int years, int months)
2803 {
2804 interval.shift(years, months);
2805 }
2806
2807 assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
2808
testInterval(I)2809 static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
2810 in I expected, size_t line = __LINE__)
2811 {
2812 interval.shift(years, months, allow);
2813 assert(interval == expected);
2814 }
2815
2816 testInterval(interval, 5, 0, AllowDayOverflow.yes, Interval!Date(Date(2015, 7, 4), Date(2017, 1, 7)));
2817 testInterval(interval, -5, 0, AllowDayOverflow.yes, Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
2818
2819 auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
2820
2821 testInterval(interval2, 1, 1, AllowDayOverflow.yes, Interval!Date(Date(2001, 3, 1), Date(2011, 7, 1)));
2822 testInterval(interval2, 1, -1, AllowDayOverflow.yes, Interval!Date(Date(2000, 12, 29), Date(2011, 5, 1)));
2823 testInterval(interval2, -1, -1, AllowDayOverflow.yes, Interval!Date(Date(1998, 12, 29), Date(2009, 5, 1)));
2824 testInterval(interval2, -1, 1, AllowDayOverflow.yes, Interval!Date(Date(1999, 3, 1), Date(2009, 7, 1)));
2825
2826 testInterval(interval2, 1, 1, AllowDayOverflow.no, Interval!Date(Date(2001, 2, 28), Date(2011, 6, 30)));
2827 testInterval(interval2, 1, -1, AllowDayOverflow.no, Interval!Date(Date(2000, 12, 29), Date(2011, 4, 30)));
2828 testInterval(interval2, -1, -1, AllowDayOverflow.no, Interval!Date(Date(1998, 12, 29), Date(2009, 4, 30)));
2829 testInterval(interval2, -1, 1, AllowDayOverflow.no, Interval!Date(Date(1999, 2, 28), Date(2009, 6, 30)));
2830 }
2831
2832 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2833 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2834 static assert(!__traits(compiles, cInterval.shift(5)));
2835 static assert(!__traits(compiles, iInterval.shift(5)));
2836
2837 // Verify Examples.
2838 auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2839 auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2840
2841 interval1.shift(2);
2842 assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
2843
2844 interval2.shift(-2);
2845 assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
2846 }
2847
2848 // Test Interval's expand(Duration).
2849 @safe unittest
2850 {
2851 import std.datetime.date;
2852
2853 auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
2854
testIntervalFail(I)2855 static void testIntervalFail(I)(I interval, scope const Duration duration)
2856 {
2857 interval.expand(duration);
2858 }
2859
2860 assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
2861 assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)), dur!"days"(-5)));
2862
testInterval(I)2863 static void testInterval(I)(I interval, scope const Duration duration,
2864 scope const I expected, size_t line = __LINE__)
2865 {
2866 interval.expand(duration);
2867 assert(interval == expected);
2868 }
2869
2870 testInterval(interval, dur!"days"(22), Interval!Date(Date(2000, 6, 12), Date(2012, 1, 29)));
2871 testInterval(interval, dur!"days"(-22), Interval!Date(Date(2000, 7, 26), Date(2011, 12, 16)));
2872
2873 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2874 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2875 static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
2876 static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
2877
2878 // Verify Examples.
2879 auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2880 auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2881
2882 interval1.expand(dur!"days"(2));
2883 assert(interval1 == Interval!Date(Date(1995, 12, 31), Date(2012, 3, 3)));
2884
2885 interval2.expand(dur!"days"(-2));
2886 assert(interval2 == Interval!Date(Date(1996, 1, 4), Date(2012, 2, 28)));
2887 }
2888
2889 // Test Interval's expand(int, int, AllowDayOverflow, Direction)
2890 @safe unittest
2891 {
2892 import std.datetime.date;
2893
2894 {
2895 auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
2896
2897 static void testIntervalFail(Interval!Date interval, int years, int months)
2898 {
2899 interval.expand(years, months);
2900 }
2901
2902 assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
2903 assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)), -5, 0));
2904
testInterval(I)2905 static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, Direction dir,
2906 in I expected, size_t line = __LINE__)
2907 {
2908 interval.expand(years, months, allow, dir);
2909 assert(interval == expected);
2910 }
2911
2912 testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.both,
2913 Interval!Date(Date(1995, 7, 4), Date(2017, 1, 7)));
2914 testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.both,
2915 Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
2916
2917 testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.fwd,
2918 Interval!Date(Date(2000, 7, 4), Date(2017, 1, 7)));
2919 testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.fwd,
2920 Interval!Date(Date(2000, 7, 4), Date(2007, 1, 7)));
2921
2922 testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.bwd,
2923 Interval!Date(Date(1995, 7, 4), Date(2012, 1, 7)));
2924 testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.bwd,
2925 Interval!Date(Date(2005, 7, 4), Date(2012, 1, 7)));
2926
2927 auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
2928
2929 testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.both,
2930 Interval!Date(Date(1998, 12, 29), Date(2011, 7, 1)));
2931 testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.both,
2932 Interval!Date(Date(1999, 3, 1), Date(2011, 5, 1)));
2933 testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.both,
2934 Interval!Date(Date(2001, 3, 1), Date(2009, 5, 1)));
2935 testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.both,
2936 Interval!Date(Date(2000, 12, 29), Date(2009, 7, 1)));
2937
2938 testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.both,
2939 Interval!Date(Date(1998, 12, 29), Date(2011, 6, 30)));
2940 testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.both,
2941 Interval!Date(Date(1999, 2, 28), Date(2011, 4, 30)));
2942 testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.both,
2943 Interval!Date(Date(2001, 2, 28), Date(2009, 4, 30)));
2944 testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.both,
2945 Interval!Date(Date(2000, 12, 29), Date(2009, 6, 30)));
2946
2947 testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.fwd,
2948 Interval!Date(Date(2000, 1, 29), Date(2011, 7, 1)));
2949 testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.fwd,
2950 Interval!Date(Date(2000, 1, 29), Date(2011, 5, 1)));
2951 testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.fwd,
2952 Interval!Date(Date(2000, 1, 29), Date(2009, 5, 1)));
2953 testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.fwd,
2954 Interval!Date(Date(2000, 1, 29), Date(2009, 7, 1)));
2955
2956 testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.fwd,
2957 Interval!Date(Date(2000, 1, 29), Date(2011, 6, 30)));
2958 testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.fwd,
2959 Interval!Date(Date(2000, 1, 29), Date(2011, 4, 30)));
2960 testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.fwd,
2961 Interval!Date(Date(2000, 1, 29), Date(2009, 4, 30)));
2962 testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.fwd,
2963 Interval!Date(Date(2000, 1, 29), Date(2009, 6, 30)));
2964
2965 testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.bwd,
2966 Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
2967 testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.bwd,
2968 Interval!Date(Date(1999, 3, 1), Date(2010, 5, 31)));
2969 testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.bwd,
2970 Interval!Date(Date(2001, 3, 1), Date(2010, 5, 31)));
2971 testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.bwd,
2972 Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
2973
2974 testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.bwd,
2975 Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
2976 testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.bwd,
2977 Interval!Date(Date(1999, 2, 28), Date(2010, 5, 31)));
2978 testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.bwd,
2979 Interval!Date(Date(2001, 2, 28), Date(2010, 5, 31)));
2980 testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.bwd,
2981 Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
2982 }
2983
2984 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2985 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2986 static assert(!__traits(compiles, cInterval.expand(5)));
2987 static assert(!__traits(compiles, iInterval.expand(5)));
2988
2989 // Verify Examples.
2990 auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2991 auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2992
2993 interval1.expand(2);
2994 assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
2995
2996 interval2.expand(-2);
2997 assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
2998 }
2999
3000 // Test Interval's fwdRange.
3001 @system unittest
3002 {
3003 import std.datetime.date;
3004
3005 {
3006 auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
3007
3008 static void testInterval1(Interval!Date interval)
3009 {
3010 interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
3011 }
3012
3013 assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
3014
3015 static void testInterval2(Interval!Date interval)
3016 {
3017 interval.fwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).popFront();
3018 }
3019
3020 assertThrown!DateTimeException(testInterval2(interval));
3021
3022 assert(!interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3023 assert(interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).empty);
3024
3025 assert(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).front ==
3026 Date(2010, 9, 12));
3027
3028 assert(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(
3029 everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).front == Date(2010, 9, 17));
3030 }
3031
3032 // Verify Examples.
3033 {
3034 auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
delegate(scope const Date date)3035 auto func = delegate (scope const Date date)
3036 {
3037 if ((date.day & 1) == 0)
3038 return date + dur!"days"(2);
3039 return date + dur!"days"(1);
3040 };
3041 auto range = interval.fwdRange(func);
3042
3043 // An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
3044 assert(range.front == Date(2010, 9, 1));
3045
3046 range.popFront();
3047 assert(range.front == Date(2010, 9, 2));
3048
3049 range.popFront();
3050 assert(range.front == Date(2010, 9, 4));
3051
3052 range.popFront();
3053 assert(range.front == Date(2010, 9, 6));
3054
3055 range.popFront();
3056 assert(range.front == Date(2010, 9, 8));
3057
3058 range.popFront();
3059 assert(range.empty);
3060 }
3061
3062 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3063 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3064 assert(!cInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3065 assert(!iInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3066 }
3067
3068 // Test Interval's bwdRange.
3069 @system unittest
3070 {
3071 import std.datetime.date;
3072
3073 {
3074 auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
3075
3076 static void testInterval1(Interval!Date interval)
3077 {
3078 interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
3079 }
3080
3081 assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
3082
3083 static void testInterval2(Interval!Date interval)
3084 {
3085 interval.bwdRange(everyDayOfWeek!(Date, Direction.fwd)(DayOfWeek.fri)).popFront();
3086 }
3087
3088 assertThrown!DateTimeException(testInterval2(interval));
3089
3090 assert(!interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).empty);
3091 assert(interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).empty);
3092
3093 assert(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(
3094 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).front == Date(2010, 10, 1));
3095
3096 assert(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(
3097 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).front == Date(2010, 9, 24));
3098 }
3099
3100 // Verify Examples.
3101 {
3102 auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
delegate(scope const Date date)3103 auto func = delegate (scope const Date date)
3104 {
3105 if ((date.day & 1) == 0)
3106 return date - dur!"days"(2);
3107 return date - dur!"days"(1);
3108 };
3109 auto range = interval.bwdRange(func);
3110
3111 // An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
3112 assert(range.front == Date(2010, 9, 9));
3113
3114 range.popFront();
3115 assert(range.front == Date(2010, 9, 8));
3116
3117 range.popFront();
3118 assert(range.front == Date(2010, 9, 6));
3119
3120 range.popFront();
3121 assert(range.front == Date(2010, 9, 4));
3122
3123 range.popFront();
3124 assert(range.front == Date(2010, 9, 2));
3125
3126 range.popFront();
3127 assert(range.empty);
3128 }
3129
3130 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3131 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3132 assert(!cInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3133 assert(!iInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3134 }
3135
3136 // Test Interval's toString().
3137 @safe unittest
3138 {
3139 import std.datetime.date;
3140
3141 assert(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).toString() == "[2010-Jul-04 - 2012-Jan-07)");
3142
3143 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3144 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3145 assert(cInterval.toString());
3146 assert(iInterval.toString());
3147 }
3148
3149
3150 /++
3151 Represents an interval of time which has positive infinity as its end point.
3152
3153 Any ranges which iterate over a `PosInfInterval` are infinite. So, the
3154 main purpose of using `PosInfInterval` is to create an infinite range
3155 which starts at a fixed point in time and goes to positive infinity.
3156 +/
PosInfInterval(TP)3157 struct PosInfInterval(TP)
3158 {
3159 public:
3160
3161 /++
3162 Params:
3163 begin = The time point which begins the interval.
3164
3165 Example:
3166 --------------------
3167 auto interval = PosInfInterval!Date(Date(1996, 1, 2));
3168 --------------------
3169 +/
3170 this(scope const TP begin) pure nothrow
3171 {
3172 _begin = cast(TP) begin;
3173 }
3174
3175
3176 /++
3177 Params:
3178 rhs = The `PosInfInterval` to assign to this one.
3179 +/
3180 ref PosInfInterval opAssign(const ref PosInfInterval rhs) pure nothrow
3181 {
3182 _begin = cast(TP) rhs._begin;
3183 return this;
3184 }
3185
3186
3187 /++
3188 Params:
3189 rhs = The `PosInfInterval` to assign to this one.
3190 +/
3191 ref PosInfInterval opAssign(PosInfInterval rhs) pure nothrow
3192 {
3193 _begin = cast(TP) rhs._begin;
3194 return this;
3195 }
3196
3197
3198 /++
3199 The starting point of the interval. It is included in the interval.
3200
3201 Example:
3202 --------------------
3203 assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
3204 --------------------
3205 +/
3206 @property TP begin() const pure nothrow
3207 {
3208 return cast(TP)_begin;
3209 }
3210
3211
3212 /++
3213 The starting point of the interval. It is included in the interval.
3214
3215 Params:
3216 timePoint = The time point to set `begin` to.
3217 +/
3218 @property void begin(TP timePoint) pure nothrow
3219 {
3220 _begin = timePoint;
3221 }
3222
3223
3224 /++
3225 Whether the interval's length is 0. Always returns false.
3226
3227 Example:
3228 --------------------
3229 assert(!PosInfInterval!Date(Date(1996, 1, 2)).empty);
3230 --------------------
3231 +/
3232 enum bool empty = false;
3233
3234
3235 /++
3236 Whether the given time point is within this interval.
3237
3238 Params:
3239 timePoint = The time point to check for inclusion in this interval.
3240
3241 Example:
3242 --------------------
3243 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(1994, 12, 24)));
3244 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(2000, 1, 5)));
3245 --------------------
3246 +/
3247 bool contains(TP timePoint) const pure nothrow
3248 {
3249 return timePoint >= _begin;
3250 }
3251
3252
3253 /++
3254 Whether the given interval is completely within this interval.
3255
3256 Params:
3257 interval = The interval to check for inclusion in this interval.
3258
3259 Throws:
3260 $(REF DateTimeException,std,datetime,date) if the given interval
3261 is empty.
3262
3263 Example:
3264 --------------------
3265 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
3266 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
3267
3268 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
3269 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3270
3271 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
3272 Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
3273 --------------------
3274 +/
3275 bool contains(scope const Interval!TP interval) const pure
3276 {
3277 interval._enforceNotEmpty();
3278 return interval._begin >= _begin;
3279 }
3280
3281
3282 /++
3283 Whether the given interval is completely within this interval.
3284
3285 Params:
3286 interval = The interval to check for inclusion in this interval.
3287
3288 Example:
3289 --------------------
3290 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
3291 PosInfInterval!Date(Date(1999, 5, 4))));
3292
3293 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
3294 PosInfInterval!Date(Date(1995, 7, 2))));
3295 --------------------
3296 +/
3297 bool contains(scope const PosInfInterval interval) const pure nothrow
3298 {
3299 return interval._begin >= _begin;
3300 }
3301
3302
3303 /++
3304 Whether the given interval is completely within this interval.
3305
3306 Always returns false because an interval going to positive infinity
3307 can never contain an interval beginning at negative infinity.
3308
3309 Params:
3310 interval = The interval to check for inclusion in this interval.
3311
3312 Example:
3313 --------------------
3314 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
3315 NegInfInterval!Date(Date(1996, 5, 4))));
3316 --------------------
3317 +/
3318 bool contains(scope const NegInfInterval!TP interval) const pure nothrow
3319 {
3320 return false;
3321 }
3322
3323
3324 /++
3325 Whether this interval is before the given time point.
3326
3327 Always returns false because an interval going to positive infinity
3328 can never be before any time point.
3329
3330 Params:
3331 timePoint = The time point to check whether this interval is before
3332 it.
3333
3334 Example:
3335 --------------------
3336 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(1994, 12, 24)));
3337 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(2000, 1, 5)));
3338 --------------------
3339 +/
3340 bool isBefore(scope const TP timePoint) const pure nothrow
3341 {
3342 return false;
3343 }
3344
3345
3346 /++
3347 Whether this interval is before the given interval and does not
3348 intersect it.
3349
3350 Always returns false (unless the given interval is empty) because an
3351 interval going to positive infinity can never be before any other
3352 interval.
3353
3354 Params:
3355 interval = The interval to check for against this interval.
3356
3357 Throws:
3358 $(REF DateTimeException,std,datetime,date) if the given interval
3359 is empty.
3360
3361 Example:
3362 --------------------
3363 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3364 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
3365
3366 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3367 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3368 --------------------
3369 +/
3370 bool isBefore(scope const Interval!TP interval) const pure
3371 {
3372 interval._enforceNotEmpty();
3373 return false;
3374 }
3375
3376
3377 /++
3378 Whether this interval is before the given interval and does not
3379 intersect it.
3380
3381 Always returns false because an interval going to positive infinity can
3382 never be before any other interval.
3383
3384 Params:
3385 interval = The interval to check for against this interval.
3386
3387 Example:
3388 --------------------
3389 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3390 PosInfInterval!Date(Date(1992, 5, 4))));
3391
3392 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3393 PosInfInterval!Date(Date(2013, 3, 7))));
3394 --------------------
3395 +/
3396 bool isBefore(scope const PosInfInterval interval) const pure nothrow
3397 {
3398 return false;
3399 }
3400
3401
3402 /++
3403 Whether this interval is before the given interval and does not
3404 intersect it.
3405
3406 Always returns false because an interval going to positive infinity can
3407 never be before any other interval.
3408
3409 Params:
3410 interval = The interval to check for against this interval.
3411
3412 Example:
3413 --------------------
3414 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3415 NegInfInterval!Date(Date(1996, 5, 4))));
3416 --------------------
3417 +/
3418 bool isBefore(scope const NegInfInterval!TP interval) const pure nothrow
3419 {
3420 return false;
3421 }
3422
3423
3424 /++
3425 Whether this interval is after the given time point.
3426
3427 Params:
3428 timePoint = The time point to check whether this interval is after
3429 it.
3430
3431 Example:
3432 --------------------
3433 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(1994, 12, 24)));
3434 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(2000, 1, 5)));
3435 --------------------
3436 +/
3437 bool isAfter(scope const TP timePoint) const pure nothrow
3438 {
3439 return timePoint < _begin;
3440 }
3441
3442
3443 /++
3444 Whether this interval is after the given interval and does not intersect
3445 it.
3446
3447 Params:
3448 interval = The interval to check against this interval.
3449
3450 Throws:
3451 $(REF DateTimeException,std,datetime,date) if the given interval
3452 is empty.
3453
3454 Example:
3455 --------------------
3456 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3457 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
3458
3459 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3460 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3461
3462 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3463 Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
3464 --------------------
3465 +/
3466 bool isAfter(scope const Interval!TP interval) const pure
3467 {
3468 interval._enforceNotEmpty();
3469 return _begin >= interval._end;
3470 }
3471
3472
3473 /++
3474 Whether this interval is after the given interval and does not intersect
3475 it.
3476
3477 Always returns false because an interval going to positive infinity can
3478 never be after another interval going to positive infinity.
3479
3480 Params:
3481 interval = The interval to check against this interval.
3482
3483 Example:
3484 --------------------
3485 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3486 PosInfInterval!Date(Date(1990, 1, 7))));
3487
3488 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3489 PosInfInterval!Date(Date(1999, 5, 4))));
3490 --------------------
3491 +/
3492 bool isAfter(scope const PosInfInterval interval) const pure nothrow
3493 {
3494 return false;
3495 }
3496
3497
3498 /++
3499 Whether this interval is after the given interval and does not intersect
3500 it.
3501
3502 Params:
3503 interval = The interval to check against this interval.
3504
3505 Example:
3506 --------------------
3507 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3508 NegInfInterval!Date(Date(1996, 1, 2))));
3509
3510 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3511 NegInfInterval!Date(Date(2000, 7, 1))));
3512 --------------------
3513 +/
3514 bool isAfter(scope const NegInfInterval!TP interval) const pure nothrow
3515 {
3516 return _begin >= interval._end;
3517 }
3518
3519
3520 /++
3521 Whether the given interval overlaps this interval.
3522
3523 Params:
3524 interval = The interval to check for intersection with this interval.
3525
3526 Throws:
3527 $(REF DateTimeException,std,datetime,date) if the given interval
3528 is empty.
3529
3530 Example:
3531 --------------------
3532 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3533 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
3534
3535 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3536 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3537
3538 assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3539 Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
3540 --------------------
3541 +/
3542 bool intersects(scope const Interval!TP interval) const pure
3543 {
3544 interval._enforceNotEmpty();
3545 return interval._end > _begin;
3546 }
3547
3548
3549 /++
3550 Whether the given interval overlaps this interval.
3551
3552 Always returns true because two intervals going to positive infinity
3553 always overlap.
3554
3555 Params:
3556 interval = The interval to check for intersection with this
3557 interval.
3558
3559 Example:
3560 --------------------
3561 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3562 PosInfInterval!Date(Date(1990, 1, 7))));
3563
3564 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3565 PosInfInterval!Date(Date(1999, 5, 4))));
3566 --------------------
3567 +/
3568 bool intersects(scope const PosInfInterval interval) const pure nothrow
3569 {
3570 return true;
3571 }
3572
3573
3574 /++
3575 Whether the given interval overlaps this interval.
3576
3577 Params:
3578 interval = The interval to check for intersection with this
3579 interval.
3580
3581 Example:
3582 --------------------
3583 assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3584 NegInfInterval!Date(Date(1996, 1, 2))));
3585
3586 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3587 NegInfInterval!Date(Date(2000, 7, 1))));
3588 --------------------
3589 +/
3590 bool intersects(scope const NegInfInterval!TP interval) const pure nothrow
3591 {
3592 return _begin < interval._end;
3593 }
3594
3595
3596 /++
3597 Returns the intersection of two intervals
3598
3599 Params:
3600 interval = The interval to intersect with this interval.
3601
3602 Throws:
3603 $(REF DateTimeException,std,datetime,date) if the two intervals do
3604 not intersect or if the given interval is empty.
3605
3606 Example:
3607 --------------------
3608 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3609 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
3610 Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
3611
3612 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3613 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
3614 Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
3615 --------------------
3616 +/
3617 Interval!TP intersection(scope const Interval!TP interval) const
3618 {
3619 import std.format : format;
3620
3621 enforce(this.intersects(interval),
3622 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
3623
3624 auto begin = _begin > interval._begin ? _begin : interval._begin;
3625
3626 return Interval!TP(begin, interval._end);
3627 }
3628
3629
3630 /++
3631 Returns the intersection of two intervals
3632
3633 Params:
3634 interval = The interval to intersect with this interval.
3635
3636 Example:
3637 --------------------
3638 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3639 PosInfInterval!Date(Date(1990, 7, 6))) ==
3640 PosInfInterval!Date(Date(1996, 1 , 2)));
3641
3642 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3643 PosInfInterval!Date(Date(1999, 1, 12))) ==
3644 PosInfInterval!Date(Date(1999, 1 , 12)));
3645 --------------------
3646 +/
3647 PosInfInterval intersection(scope const PosInfInterval interval) const pure nothrow
3648 {
3649 return PosInfInterval(_begin < interval._begin ? interval._begin : _begin);
3650 }
3651
3652
3653 /++
3654 Returns the intersection of two intervals
3655
3656 Params:
3657 interval = The interval to intersect with this interval.
3658
3659 Throws:
3660 $(REF DateTimeException,std,datetime,date) if the two intervals do
3661 not intersect.
3662
3663 Example:
3664 --------------------
3665 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3666 NegInfInterval!Date(Date(1999, 7, 6))) ==
3667 Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
3668
3669 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3670 NegInfInterval!Date(Date(2013, 1, 12))) ==
3671 Interval!Date(Date(1996, 1 , 2), Date(2013, 1, 12)));
3672 --------------------
3673 +/
3674 Interval!TP intersection(scope const NegInfInterval!TP interval) const
3675 {
3676 import std.format : format;
3677
3678 enforce(this.intersects(interval),
3679 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
3680
3681 return Interval!TP(_begin, interval._end);
3682 }
3683
3684
3685 /++
3686 Whether the given interval is adjacent to this interval.
3687
3688 Params:
3689 interval = The interval to check whether its adjecent to this
3690 interval.
3691
3692 Throws:
3693 $(REF DateTimeException,std,datetime,date) if the given interval
3694 is empty.
3695
3696 Example:
3697 --------------------
3698 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3699 Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
3700
3701 assert(!PosInfInterval!Date(Date(1999, 1, 12)).isAdjacent(
3702 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3703 --------------------
3704 +/
3705 bool isAdjacent(scope const Interval!TP interval) const pure
3706 {
3707 interval._enforceNotEmpty();
3708 return _begin == interval._end;
3709 }
3710
3711
3712 /++
3713 Whether the given interval is adjacent to this interval.
3714
3715 Always returns false because two intervals going to positive infinity
3716 can never be adjacent to one another.
3717
3718 Params:
3719 interval = The interval to check whether its adjecent to this
3720 interval.
3721
3722 Example:
3723 --------------------
3724 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3725 PosInfInterval!Date(Date(1990, 1, 7))));
3726
3727 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3728 PosInfInterval!Date(Date(1996, 1, 2))));
3729 --------------------
3730 +/
3731 bool isAdjacent(scope const PosInfInterval interval) const pure nothrow
3732 {
3733 return false;
3734 }
3735
3736
3737 /++
3738 Whether the given interval is adjacent to this interval.
3739
3740 Params:
3741 interval = The interval to check whether its adjecent to this
3742 interval.
3743
3744 Example:
3745 --------------------
3746 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3747 NegInfInterval!Date(Date(1996, 1, 2))));
3748
3749 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3750 NegInfInterval!Date(Date(2000, 7, 1))));
3751 --------------------
3752 +/
3753 bool isAdjacent(scope const NegInfInterval!TP interval) const pure nothrow
3754 {
3755 return _begin == interval._end;
3756 }
3757
3758
3759 /++
3760 Returns the union of two intervals
3761
3762 Params:
3763 interval = The interval to merge with this interval.
3764
3765 Throws:
3766 $(REF DateTimeException,std,datetime,date) if the two intervals do
3767 not intersect and are not adjacent or if the given interval is
3768 empty.
3769
3770 Note:
3771 There is no overload for `merge` which takes a
3772 `NegInfInterval`, because an interval
3773 going from negative infinity to positive infinity
3774 is not possible.
3775
3776 Example:
3777 --------------------
3778 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
3779 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
3780 PosInfInterval!Date(Date(1990, 7 , 6)));
3781
3782 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
3783 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
3784 PosInfInterval!Date(Date(1996, 1 , 2)));
3785 --------------------
3786 +/
3787 PosInfInterval merge(scope const Interval!TP interval) const
3788 {
3789 import std.format : format;
3790
3791 enforce(this.isAdjacent(interval) || this.intersects(interval),
3792 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
3793
3794 return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
3795 }
3796
3797
3798 /++
3799 Returns the union of two intervals
3800
3801 Params:
3802 interval = The interval to merge with this interval.
3803
3804 Note:
3805 There is no overload for `merge` which takes a
3806 `NegInfInterval`, because an interval
3807 going from negative infinity to positive infinity
3808 is not possible.
3809
3810 Example:
3811 --------------------
3812 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
3813 PosInfInterval!Date(Date(1990, 7, 6))) ==
3814 PosInfInterval!Date(Date(1990, 7 , 6)));
3815
3816 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
3817 PosInfInterval!Date(Date(1999, 1, 12))) ==
3818 PosInfInterval!Date(Date(1996, 1 , 2)));
3819 --------------------
3820 +/
3821 PosInfInterval merge(scope const PosInfInterval interval) const pure nothrow
3822 {
3823 return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
3824 }
3825
3826
3827 /++
3828 Returns an interval that covers from the earliest time point of two
3829 intervals up to (but not including) the latest time point of two
3830 intervals.
3831
3832 Params:
3833 interval = The interval to create a span together with this
3834 interval.
3835
3836 Throws:
3837 $(REF DateTimeException,std,datetime,date) if the given interval
3838 is empty.
3839
3840 Note:
3841 There is no overload for `span` which takes a
3842 `NegInfInterval`, because an interval
3843 going from negative infinity to positive infinity
3844 is not possible.
3845
3846 Example:
3847 --------------------
3848 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3849 Interval!Date(Date(500, 8, 9), Date(1602, 1, 31))) ==
3850 PosInfInterval!Date(Date(500, 8, 9)));
3851
3852 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3853 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
3854 PosInfInterval!Date(Date(1990, 7 , 6)));
3855
3856 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3857 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
3858 PosInfInterval!Date(Date(1996, 1 , 2)));
3859 --------------------
3860 +/
3861 PosInfInterval span(scope const Interval!TP interval) const pure
3862 {
3863 interval._enforceNotEmpty();
3864 return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
3865 }
3866
3867
3868 /++
3869 Returns an interval that covers from the earliest time point of two
3870 intervals up to (but not including) the latest time point of two
3871 intervals.
3872
3873 Params:
3874 interval = The interval to create a span together with this
3875 interval.
3876
3877 Note:
3878 There is no overload for `span` which takes a
3879 `NegInfInterval`, because an interval
3880 going from negative infinity to positive infinity
3881 is not possible.
3882
3883 Example:
3884 --------------------
3885 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3886 PosInfInterval!Date(Date(1990, 7, 6))) ==
3887 PosInfInterval!Date(Date(1990, 7 , 6)));
3888
3889 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3890 PosInfInterval!Date(Date(1999, 1, 12))) ==
3891 PosInfInterval!Date(Date(1996, 1 , 2)));
3892 --------------------
3893 +/
3894 PosInfInterval span(scope const PosInfInterval interval) const pure nothrow
3895 {
3896 return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
3897 }
3898
3899
3900 /++
3901 Shifts the `begin` of this interval forward or backwards in time by
3902 the given duration (a positive duration shifts the interval forward; a
3903 negative duration shifts it backward). Effectively, it does
3904 $(D begin += duration).
3905
3906 Params:
3907 duration = The duration to shift the interval by.
3908
3909 Example:
3910 --------------------
3911 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
3912 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
3913
3914 interval1.shift(dur!"days"(50));
3915 assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
3916
3917 interval2.shift(dur!"days"(-50));
3918 assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
3919 --------------------
3920 +/
3921 void shift(D)(D duration) pure nothrow
3922 if (__traits(compiles, begin + duration))
3923 {
3924 _begin += duration;
3925 }
3926
3927
3928 static if (__traits(compiles, begin.add!"months"(1)) &&
3929 __traits(compiles, begin.add!"years"(1)))
3930 {
3931 /++
3932 Shifts the `begin` of this interval forward or backwards in time
3933 by the given number of years and/or months (a positive number of
3934 years and months shifts the interval forward; a negative number
3935 shifts it backward). It adds the years the given years and months to
3936 `begin`. It effectively calls `add!"years"()` and then
3937 `add!"months"()` on `begin` with the given number of years and
3938 months.
3939
3940 Params:
3941 years = The number of years to shift the interval by.
3942 months = The number of months to shift the interval by.
3943 allowOverflow = Whether the days should be allowed to overflow
3944 on `begin`, causing its month to increment.
3945
3946 Throws:
3947 $(REF DateTimeException,std,datetime,date) if this interval is
3948 empty or if the resulting interval would be invalid.
3949
3950 Example:
3951 --------------------
3952 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
3953 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
3954
3955 interval1.shift(dur!"days"(50));
3956 assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
3957
3958 interval2.shift(dur!"days"(-50));
3959 assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
3960 --------------------
3961 +/
3962 void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
3963 if (isIntegral!T)
3964 {
3965 auto begin = _begin;
3966
3967 begin.add!"years"(years, allowOverflow);
3968 begin.add!"months"(months, allowOverflow);
3969
3970 _begin = begin;
3971 }
3972 }
3973
3974
3975 /++
3976 Expands the interval backwards in time. Effectively, it does
3977 $(D begin -= duration).
3978
3979 Params:
3980 duration = The duration to expand the interval by.
3981
3982 Example:
3983 --------------------
3984 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
3985 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
3986
3987 interval1.expand(dur!"days"(2));
3988 assert(interval1 == PosInfInterval!Date(Date(1995, 12, 31)));
3989
3990 interval2.expand(dur!"days"(-2));
3991 assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
3992 --------------------
3993 +/
3994 void expand(D)(D duration) pure nothrow
3995 if (__traits(compiles, begin + duration))
3996 {
3997 _begin -= duration;
3998 }
3999
4000
4001 static if (__traits(compiles, begin.add!"months"(1)) &&
4002 __traits(compiles, begin.add!"years"(1)))
4003 {
4004 /++
4005 Expands the interval forwards and/or backwards in time. Effectively,
4006 it subtracts the given number of months/years from `begin`.
4007
4008 Params:
4009 years = The number of years to expand the interval by.
4010 months = The number of months to expand the interval by.
4011 allowOverflow = Whether the days should be allowed to overflow
4012 on `begin`, causing its month to increment.
4013
4014 Throws:
4015 $(REF DateTimeException,std,datetime,date) if this interval is
4016 empty or if the resulting interval would be invalid.
4017
4018 Example:
4019 --------------------
4020 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
4021 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
4022
4023 interval1.expand(2);
4024 assert(interval1 == PosInfInterval!Date(Date(1994, 1, 2)));
4025
4026 interval2.expand(-2);
4027 assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
4028 --------------------
4029 +/
4030 void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
4031 if (isIntegral!T)
4032 {
4033 auto begin = _begin;
4034
4035 begin.add!"years"(-years, allowOverflow);
4036 begin.add!"months"(-months, allowOverflow);
4037
4038 _begin = begin;
4039 }
4040 }
4041
4042
4043 /++
4044 Returns a range which iterates forward over the interval, starting
4045 at `begin`, using $(D_PARAM func) to generate each successive time
4046 point.
4047
4048 The range's `front` is the interval's `begin`. $(D_PARAM func) is
4049 used to generate the next `front` when `popFront` is called. If
4050 $(D_PARAM popFirst) is `PopFirst.yes`, then `popFront` is called
4051 before the range is returned (so that `front` is a time point which
4052 $(D_PARAM func) would generate).
4053
4054 If $(D_PARAM func) ever generates a time point less than or equal to the
4055 current `front` of the range, then a
4056 $(REF DateTimeException,std,datetime,date) will be thrown.
4057
4058 There are helper functions in this module which generate common
4059 delegates to pass to `fwdRange`. Their documentation starts with
4060 "Range-generating function," to make them easily searchable.
4061
4062 Params:
4063 func = The function used to generate the time points of the
4064 range over the interval.
4065 popFirst = Whether `popFront` should be called on the range
4066 before returning it.
4067
4068 Throws:
4069 $(REF DateTimeException,std,datetime,date) if this interval is
4070 empty.
4071
4072 Warning:
4073 $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
4074 would be a function pointer to a pure function, but forcing
4075 $(D_PARAM func) to be pure is far too restrictive to be useful, and
4076 in order to have the ease of use of having functions which generate
4077 functions to pass to `fwdRange`, $(D_PARAM func) must be a
4078 delegate.
4079
4080 If $(D_PARAM func) retains state which changes as it is called, then
4081 some algorithms will not work correctly, because the range's
4082 `save` will have failed to have really saved the range's state.
4083 To avoid such bugs, don't pass a delegate which is
4084 not logically pure to `fwdRange`. If $(D_PARAM func) is given the
4085 same time point with two different calls, it must return the same
4086 result both times.
4087
4088 Of course, none of the functions in this module have this problem,
4089 so it's only relevant for custom delegates.
4090
4091 Example:
4092 --------------------
4093 auto interval = PosInfInterval!Date(Date(2010, 9, 1));
4094 auto func = delegate (scope const Date date) //For iterating over even-numbered days.
4095 {
4096 if ((date.day & 1) == 0)
4097 return date + dur!"days"(2);
4098
4099 return date + dur!"days"(1);
4100 };
4101 auto range = interval.fwdRange(func);
4102
4103 //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
4104 assert(range.front == Date(2010, 9, 1));
4105
4106 range.popFront();
4107 assert(range.front == Date(2010, 9, 2));
4108
4109 range.popFront();
4110 assert(range.front == Date(2010, 9, 4));
4111
4112 range.popFront();
4113 assert(range.front == Date(2010, 9, 6));
4114
4115 range.popFront();
4116 assert(range.front == Date(2010, 9, 8));
4117
4118 range.popFront();
4119 assert(!range.empty);
4120 --------------------
4121 +/
4122 PosInfIntervalRange!(TP) fwdRange(TP delegate(scope const TP) func, PopFirst popFirst = PopFirst.no) const
4123 {
4124 auto range = PosInfIntervalRange!(TP)(this, func);
4125
4126 if (popFirst == PopFirst.yes)
4127 range.popFront();
4128
4129 return range;
4130 }
4131
4132
4133 /+
4134 Converts this interval to a string.
4135 +/
4136 // Due to bug https://issues.dlang.org/show_bug.cgi?id=3715 , we can't
4137 // have versions of toString() with extra modifiers,
4138 // so we define one version with modifiers and one without.
4139 string toString()
4140 {
4141 return _toStringImpl();
4142 }
4143
4144
4145 /++
4146 Converts this interval to a string.
4147 +/
4148 // Due to bug https://issues.dlang.org/show_bug.cgi?id=3715 , we can't
4149 // have versions of toString() with extra modifiers,
4150 // so we define one version with modifiers and one without.
4151 string toString() const nothrow
4152 {
4153 return _toStringImpl();
4154 }
4155
4156 private:
4157
4158 /+
4159 Since we have two versions of toString(), we have _toStringImpl()
4160 so that they can share implementations.
4161 +/
4162 string _toStringImpl() const nothrow
4163 {
4164 import std.format : format;
4165 try
4166 return format("[%s - ∞)", _begin);
4167 catch (Exception e)
4168 assert(0, "format() threw.");
4169 }
4170
4171
4172 TP _begin;
4173 }
4174
4175 //Test PosInfInterval's constructor.
4176 @safe unittest
4177 {
4178 import std.datetime.date;
4179 import std.datetime.systime;
4180
4181 PosInfInterval!Date(Date.init);
4182 PosInfInterval!TimeOfDay(TimeOfDay.init);
4183 PosInfInterval!DateTime(DateTime.init);
4184 PosInfInterval!SysTime(SysTime(0));
4185
4186 //Verify Examples.
4187 auto interval = PosInfInterval!Date(Date(1996, 1, 2));
4188 }
4189
4190 //Test PosInfInterval's begin.
4191 @safe unittest
4192 {
4193 import std.datetime.date;
4194
4195 assert(PosInfInterval!Date(Date(1, 1, 1)).begin == Date(1, 1, 1));
4196 assert(PosInfInterval!Date(Date(2010, 1, 1)).begin == Date(2010, 1, 1));
4197 assert(PosInfInterval!Date(Date(1997, 12, 31)).begin == Date(1997, 12, 31));
4198
4199 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4200 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4201 assert(cPosInfInterval.begin != Date.init);
4202 assert(iPosInfInterval.begin != Date.init);
4203
4204 //Verify Examples.
4205 assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
4206 }
4207
4208 //Test PosInfInterval's empty.
4209 @safe unittest
4210 {
4211 import std.datetime.date;
4212 import std.datetime.systime;
4213
4214 assert(!PosInfInterval!Date(Date(2010, 1, 1)).empty);
4215 assert(!PosInfInterval!TimeOfDay(TimeOfDay(0, 30, 0)).empty);
4216 assert(!PosInfInterval!DateTime(DateTime(2010, 1, 1, 0, 30, 0)).empty);
4217 assert(!PosInfInterval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0))).empty);
4218
4219 const cPosInfInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4220 immutable iPosInfInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4221 assert(!cPosInfInterval.empty);
4222 assert(!iPosInfInterval.empty);
4223
4224 //Verify Examples.
4225 assert(!PosInfInterval!Date(Date(1996, 1, 2)).empty);
4226 }
4227
4228 //Test PosInfInterval's contains(time point).
4229 @safe unittest
4230 {
4231 import std.datetime.date;
4232
4233 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4234
4235 assert(!posInfInterval.contains(Date(2009, 7, 4)));
4236 assert(!posInfInterval.contains(Date(2010, 7, 3)));
4237 assert(posInfInterval.contains(Date(2010, 7, 4)));
4238 assert(posInfInterval.contains(Date(2010, 7, 5)));
4239 assert(posInfInterval.contains(Date(2011, 7, 1)));
4240 assert(posInfInterval.contains(Date(2012, 1, 6)));
4241 assert(posInfInterval.contains(Date(2012, 1, 7)));
4242 assert(posInfInterval.contains(Date(2012, 1, 8)));
4243 assert(posInfInterval.contains(Date(2013, 1, 7)));
4244
4245 const cdate = Date(2010, 7, 6);
4246 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4247 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4248 assert(posInfInterval.contains(cdate));
4249 assert(cPosInfInterval.contains(cdate));
4250 assert(iPosInfInterval.contains(cdate));
4251
4252 //Verify Examples.
4253 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(1994, 12, 24)));
4254 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(2000, 1, 5)));
4255 }
4256
4257 //Test PosInfInterval's contains(Interval).
4258 @safe unittest
4259 {
4260 import std.datetime.date;
4261
4262 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4263
4264 static void testInterval(scope const PosInfInterval!Date posInfInterval, scope const Interval!Date interval)
4265 {
4266 posInfInterval.contains(interval);
4267 }
4268
4269 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4270
4271 assert(posInfInterval.contains(posInfInterval));
4272 assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4273 assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4274 assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4275 assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4276 assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4277 assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4278 assert(posInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4279 assert(posInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4280 assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4281 assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4282 assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4283 assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4284
4285 assert(!posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
4286 assert(posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
4287 assert(posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
4288 assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
4289 assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
4290 assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
4291
4292 assert(PosInfInterval!Date(Date(2010, 7, 3)).contains(posInfInterval));
4293 assert(PosInfInterval!Date(Date(2010, 7, 4)).contains(posInfInterval));
4294 assert(!PosInfInterval!Date(Date(2010, 7, 5)).contains(posInfInterval));
4295 assert(!PosInfInterval!Date(Date(2012, 1, 6)).contains(posInfInterval));
4296 assert(!PosInfInterval!Date(Date(2012, 1, 7)).contains(posInfInterval));
4297 assert(!PosInfInterval!Date(Date(2012, 1, 8)).contains(posInfInterval));
4298
4299 assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
4300 assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
4301 assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
4302 assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
4303 assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
4304 assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
4305
4306 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4307 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4308 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4309 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4310 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4311 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4312 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4313 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4314 assert(posInfInterval.contains(interval));
4315 assert(posInfInterval.contains(cInterval));
4316 assert(posInfInterval.contains(iInterval));
4317 assert(posInfInterval.contains(posInfInterval));
4318 assert(posInfInterval.contains(cPosInfInterval));
4319 assert(posInfInterval.contains(iPosInfInterval));
4320 assert(!posInfInterval.contains(negInfInterval));
4321 assert(!posInfInterval.contains(cNegInfInterval));
4322 assert(!posInfInterval.contains(iNegInfInterval));
4323 assert(cPosInfInterval.contains(interval));
4324 assert(cPosInfInterval.contains(cInterval));
4325 assert(cPosInfInterval.contains(iInterval));
4326 assert(cPosInfInterval.contains(posInfInterval));
4327 assert(cPosInfInterval.contains(cPosInfInterval));
4328 assert(cPosInfInterval.contains(iPosInfInterval));
4329 assert(!cPosInfInterval.contains(negInfInterval));
4330 assert(!cPosInfInterval.contains(cNegInfInterval));
4331 assert(!cPosInfInterval.contains(iNegInfInterval));
4332 assert(iPosInfInterval.contains(interval));
4333 assert(iPosInfInterval.contains(cInterval));
4334 assert(iPosInfInterval.contains(iInterval));
4335 assert(iPosInfInterval.contains(posInfInterval));
4336 assert(iPosInfInterval.contains(cPosInfInterval));
4337 assert(iPosInfInterval.contains(iPosInfInterval));
4338 assert(!iPosInfInterval.contains(negInfInterval));
4339 assert(!iPosInfInterval.contains(cNegInfInterval));
4340 assert(!iPosInfInterval.contains(iNegInfInterval));
4341
4342 //Verify Examples.
4343 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
4344 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4345 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
4346
4347 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
4348 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1995, 7, 2))));
4349
4350 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
4351 }
4352
4353 //Test PosInfInterval's isBefore(time point).
4354 @safe unittest
4355 {
4356 import std.datetime.date;
4357
4358 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4359
4360 assert(!posInfInterval.isBefore(Date(2009, 7, 3)));
4361 assert(!posInfInterval.isBefore(Date(2010, 7, 3)));
4362 assert(!posInfInterval.isBefore(Date(2010, 7, 4)));
4363 assert(!posInfInterval.isBefore(Date(2010, 7, 5)));
4364 assert(!posInfInterval.isBefore(Date(2011, 7, 1)));
4365 assert(!posInfInterval.isBefore(Date(2012, 1, 6)));
4366 assert(!posInfInterval.isBefore(Date(2012, 1, 7)));
4367 assert(!posInfInterval.isBefore(Date(2012, 1, 8)));
4368 assert(!posInfInterval.isBefore(Date(2013, 1, 7)));
4369
4370 const cdate = Date(2010, 7, 6);
4371 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4372 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4373 assert(!posInfInterval.isBefore(cdate));
4374 assert(!cPosInfInterval.isBefore(cdate));
4375 assert(!iPosInfInterval.isBefore(cdate));
4376
4377 //Verify Examples.
4378 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(1994, 12, 24)));
4379 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(2000, 1, 5)));
4380 }
4381
4382 //Test PosInfInterval's isBefore(Interval).
4383 @safe unittest
4384 {
4385 import std.datetime.date;
4386
4387 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4388
4389 static void testInterval(scope const PosInfInterval!Date posInfInterval, scope const Interval!Date interval)
4390 {
4391 posInfInterval.isBefore(interval);
4392 }
4393
4394 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4395
4396 assert(!posInfInterval.isBefore(posInfInterval));
4397 assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4398 assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4399 assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4400 assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4401 assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4402 assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4403 assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4404 assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4405 assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4406 assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4407 assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4408 assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4409
4410 assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
4411 assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
4412 assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
4413 assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
4414 assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
4415 assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
4416
4417 assert(!PosInfInterval!Date(Date(2010, 7, 3)).isBefore(posInfInterval));
4418 assert(!PosInfInterval!Date(Date(2010, 7, 4)).isBefore(posInfInterval));
4419 assert(!PosInfInterval!Date(Date(2010, 7, 5)).isBefore(posInfInterval));
4420 assert(!PosInfInterval!Date(Date(2012, 1, 6)).isBefore(posInfInterval));
4421 assert(!PosInfInterval!Date(Date(2012, 1, 7)).isBefore(posInfInterval));
4422 assert(!PosInfInterval!Date(Date(2012, 1, 8)).isBefore(posInfInterval));
4423
4424 assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
4425 assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
4426 assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
4427 assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
4428 assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
4429 assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
4430
4431 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4432 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4433 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4434 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4435 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4436 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4437 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4438 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4439 assert(!posInfInterval.isBefore(interval));
4440 assert(!posInfInterval.isBefore(cInterval));
4441 assert(!posInfInterval.isBefore(iInterval));
4442 assert(!posInfInterval.isBefore(posInfInterval));
4443 assert(!posInfInterval.isBefore(cPosInfInterval));
4444 assert(!posInfInterval.isBefore(iPosInfInterval));
4445 assert(!posInfInterval.isBefore(negInfInterval));
4446 assert(!posInfInterval.isBefore(cNegInfInterval));
4447 assert(!posInfInterval.isBefore(iNegInfInterval));
4448 assert(!cPosInfInterval.isBefore(interval));
4449 assert(!cPosInfInterval.isBefore(cInterval));
4450 assert(!cPosInfInterval.isBefore(iInterval));
4451 assert(!cPosInfInterval.isBefore(posInfInterval));
4452 assert(!cPosInfInterval.isBefore(cPosInfInterval));
4453 assert(!cPosInfInterval.isBefore(iPosInfInterval));
4454 assert(!cPosInfInterval.isBefore(negInfInterval));
4455 assert(!cPosInfInterval.isBefore(cNegInfInterval));
4456 assert(!cPosInfInterval.isBefore(iNegInfInterval));
4457 assert(!iPosInfInterval.isBefore(interval));
4458 assert(!iPosInfInterval.isBefore(cInterval));
4459 assert(!iPosInfInterval.isBefore(iInterval));
4460 assert(!iPosInfInterval.isBefore(posInfInterval));
4461 assert(!iPosInfInterval.isBefore(cPosInfInterval));
4462 assert(!iPosInfInterval.isBefore(iPosInfInterval));
4463 assert(!iPosInfInterval.isBefore(negInfInterval));
4464 assert(!iPosInfInterval.isBefore(cNegInfInterval));
4465 assert(!iPosInfInterval.isBefore(iNegInfInterval));
4466
4467 //Verify Examples.
4468 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
4469 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4470
4471 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(1992, 5, 4))));
4472 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
4473
4474 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
4475 }
4476
4477 //Test PosInfInterval's isAfter(time point).
4478 @safe unittest
4479 {
4480 import std.datetime.date;
4481
4482 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4483
4484 assert(posInfInterval.isAfter(Date(2009, 7, 3)));
4485 assert(posInfInterval.isAfter(Date(2010, 7, 3)));
4486 assert(!posInfInterval.isAfter(Date(2010, 7, 4)));
4487 assert(!posInfInterval.isAfter(Date(2010, 7, 5)));
4488 assert(!posInfInterval.isAfter(Date(2011, 7, 1)));
4489 assert(!posInfInterval.isAfter(Date(2012, 1, 6)));
4490 assert(!posInfInterval.isAfter(Date(2012, 1, 7)));
4491 assert(!posInfInterval.isAfter(Date(2012, 1, 8)));
4492 assert(!posInfInterval.isAfter(Date(2013, 1, 7)));
4493
4494 const cdate = Date(2010, 7, 6);
4495 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4496 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4497 assert(!posInfInterval.isAfter(cdate));
4498 assert(!cPosInfInterval.isAfter(cdate));
4499 assert(!iPosInfInterval.isAfter(cdate));
4500
4501 //Verify Examples.
4502 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(1994, 12, 24)));
4503 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(2000, 1, 5)));
4504 }
4505
4506 //Test PosInfInterval's isAfter(Interval).
4507 @safe unittest
4508 {
4509 import std.datetime.date;
4510
4511 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4512
4513 static void testInterval(scope const PosInfInterval!Date posInfInterval, scope const Interval!Date interval)
4514 {
4515 posInfInterval.isAfter(interval);
4516 }
4517
4518 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4519
4520 assert(!posInfInterval.isAfter(posInfInterval));
4521 assert(posInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4522 assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4523 assert(posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4524 assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4525 assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4526 assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4527 assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4528 assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4529 assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4530 assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4531 assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4532 assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4533
4534 assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
4535 assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
4536 assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
4537 assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
4538 assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
4539 assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
4540
4541 assert(!PosInfInterval!Date(Date(2010, 7, 3)).isAfter(posInfInterval));
4542 assert(!PosInfInterval!Date(Date(2010, 7, 4)).isAfter(posInfInterval));
4543 assert(!PosInfInterval!Date(Date(2010, 7, 5)).isAfter(posInfInterval));
4544 assert(!PosInfInterval!Date(Date(2012, 1, 6)).isAfter(posInfInterval));
4545 assert(!PosInfInterval!Date(Date(2012, 1, 7)).isAfter(posInfInterval));
4546 assert(!PosInfInterval!Date(Date(2012, 1, 8)).isAfter(posInfInterval));
4547
4548 assert(posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
4549 assert(posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
4550 assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
4551 assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
4552 assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
4553 assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
4554
4555 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4556 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4557 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4558 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4559 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4560 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4561 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4562 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4563 assert(!posInfInterval.isAfter(interval));
4564 assert(!posInfInterval.isAfter(cInterval));
4565 assert(!posInfInterval.isAfter(iInterval));
4566 assert(!posInfInterval.isAfter(posInfInterval));
4567 assert(!posInfInterval.isAfter(cPosInfInterval));
4568 assert(!posInfInterval.isAfter(iPosInfInterval));
4569 assert(!posInfInterval.isAfter(negInfInterval));
4570 assert(!posInfInterval.isAfter(cNegInfInterval));
4571 assert(!posInfInterval.isAfter(iNegInfInterval));
4572 assert(!cPosInfInterval.isAfter(interval));
4573 assert(!cPosInfInterval.isAfter(cInterval));
4574 assert(!cPosInfInterval.isAfter(iInterval));
4575 assert(!cPosInfInterval.isAfter(posInfInterval));
4576 assert(!cPosInfInterval.isAfter(cPosInfInterval));
4577 assert(!cPosInfInterval.isAfter(iPosInfInterval));
4578 assert(!cPosInfInterval.isAfter(negInfInterval));
4579 assert(!cPosInfInterval.isAfter(cNegInfInterval));
4580 assert(!cPosInfInterval.isAfter(iNegInfInterval));
4581 assert(!iPosInfInterval.isAfter(interval));
4582 assert(!iPosInfInterval.isAfter(cInterval));
4583 assert(!iPosInfInterval.isAfter(iInterval));
4584 assert(!iPosInfInterval.isAfter(posInfInterval));
4585 assert(!iPosInfInterval.isAfter(cPosInfInterval));
4586 assert(!iPosInfInterval.isAfter(iPosInfInterval));
4587 assert(!iPosInfInterval.isAfter(negInfInterval));
4588 assert(!iPosInfInterval.isAfter(cNegInfInterval));
4589 assert(!iPosInfInterval.isAfter(iNegInfInterval));
4590
4591 //Verify Examples.
4592 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
4593 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4594 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
4595
4596 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1990, 1, 7))));
4597 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
4598
4599 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
4600 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(2000, 7, 1))));
4601 }
4602
4603 //Test PosInfInterval's intersects().
4604 @safe unittest
4605 {
4606 import std.datetime.date;
4607
4608 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4609
4610 static void testInterval(scope const PosInfInterval!Date posInfInterval, scope const Interval!Date interval)
4611 {
4612 posInfInterval.intersects(interval);
4613 }
4614
4615 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4616
4617 assert(posInfInterval.intersects(posInfInterval));
4618 assert(!posInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4619 assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4620 assert(!posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4621 assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4622 assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4623 assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4624 assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4625 assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4626 assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4627 assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4628 assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4629 assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4630
4631 assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
4632 assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
4633 assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
4634 assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
4635 assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
4636 assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
4637
4638 assert(PosInfInterval!Date(Date(2010, 7, 3)).intersects(posInfInterval));
4639 assert(PosInfInterval!Date(Date(2010, 7, 4)).intersects(posInfInterval));
4640 assert(PosInfInterval!Date(Date(2010, 7, 5)).intersects(posInfInterval));
4641 assert(PosInfInterval!Date(Date(2012, 1, 6)).intersects(posInfInterval));
4642 assert(PosInfInterval!Date(Date(2012, 1, 7)).intersects(posInfInterval));
4643 assert(PosInfInterval!Date(Date(2012, 1, 8)).intersects(posInfInterval));
4644
4645 assert(!posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
4646 assert(!posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
4647 assert(posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
4648 assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
4649 assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
4650 assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
4651
4652 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4653 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4654 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4655 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4656 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4657 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4658 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4659 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4660 assert(posInfInterval.intersects(interval));
4661 assert(posInfInterval.intersects(cInterval));
4662 assert(posInfInterval.intersects(iInterval));
4663 assert(posInfInterval.intersects(posInfInterval));
4664 assert(posInfInterval.intersects(cPosInfInterval));
4665 assert(posInfInterval.intersects(iPosInfInterval));
4666 assert(posInfInterval.intersects(negInfInterval));
4667 assert(posInfInterval.intersects(cNegInfInterval));
4668 assert(posInfInterval.intersects(iNegInfInterval));
4669 assert(cPosInfInterval.intersects(interval));
4670 assert(cPosInfInterval.intersects(cInterval));
4671 assert(cPosInfInterval.intersects(iInterval));
4672 assert(cPosInfInterval.intersects(posInfInterval));
4673 assert(cPosInfInterval.intersects(cPosInfInterval));
4674 assert(cPosInfInterval.intersects(iPosInfInterval));
4675 assert(cPosInfInterval.intersects(negInfInterval));
4676 assert(cPosInfInterval.intersects(cNegInfInterval));
4677 assert(cPosInfInterval.intersects(iNegInfInterval));
4678 assert(iPosInfInterval.intersects(interval));
4679 assert(iPosInfInterval.intersects(cInterval));
4680 assert(iPosInfInterval.intersects(iInterval));
4681 assert(iPosInfInterval.intersects(posInfInterval));
4682 assert(iPosInfInterval.intersects(cPosInfInterval));
4683 assert(iPosInfInterval.intersects(iPosInfInterval));
4684 assert(iPosInfInterval.intersects(negInfInterval));
4685 assert(iPosInfInterval.intersects(cNegInfInterval));
4686 assert(iPosInfInterval.intersects(iNegInfInterval));
4687
4688 //Verify Examples.
4689 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
4690 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4691 assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
4692
4693 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1990, 1, 7))));
4694 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
4695
4696 assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
4697 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(2000, 7, 1))));
4698 }
4699
4700 //Test PosInfInterval's intersection().
4701 @safe unittest
4702 {
4703 import std.datetime.date;
4704
4705 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4706
testInterval(I,J)4707 static void testInterval(I, J)(scope const I interval1, scope const J interval2)
4708 {
4709 interval1.intersection(interval2);
4710 }
4711
4712 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4713
4714 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4715 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4716
4717 assertThrown!DateTimeException(testInterval(posInfInterval, NegInfInterval!Date(Date(2010, 7, 3))));
4718 assertThrown!DateTimeException(testInterval(posInfInterval, NegInfInterval!Date(Date(2010, 7, 4))));
4719
4720 assert(posInfInterval.intersection(posInfInterval) == posInfInterval);
4721 assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
4722 Interval!Date(Date(2010, 7, 4), Date(2013, 7, 3)));
4723 assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
4724 Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
4725 assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
4726 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
4727 assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
4728 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
4729 assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
4730 Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
4731 assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
4732 Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
4733 assert(posInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
4734 Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
4735 assert(posInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
4736 Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)));
4737 assert(posInfInterval.intersection(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
4738 Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)));
4739 assert(posInfInterval.intersection(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
4740 Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)));
4741
4742 assert(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 3))) == PosInfInterval!Date(Date(2010, 7, 4)));
4743 assert(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 4))) == PosInfInterval!Date(Date(2010, 7, 4)));
4744 assert(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 5))) == PosInfInterval!Date(Date(2010, 7, 5)));
4745 assert(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 6))) == PosInfInterval!Date(Date(2012, 1, 6)));
4746 assert(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 7))) == PosInfInterval!Date(Date(2012, 1, 7)));
4747 assert(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 8))) == PosInfInterval!Date(Date(2012, 1, 8)));
4748
4749 assert(PosInfInterval!Date(Date(2010, 7, 3)).intersection(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4750 assert(PosInfInterval!Date(Date(2010, 7, 4)).intersection(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4751 assert(PosInfInterval!Date(Date(2010, 7, 5)).intersection(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 5)));
4752 assert(PosInfInterval!Date(Date(2012, 1, 6)).intersection(posInfInterval) == PosInfInterval!Date(Date(2012, 1, 6)));
4753 assert(PosInfInterval!Date(Date(2012, 1, 7)).intersection(posInfInterval) == PosInfInterval!Date(Date(2012, 1, 7)));
4754 assert(PosInfInterval!Date(Date(2012, 1, 8)).intersection(posInfInterval) == PosInfInterval!Date(Date(2012, 1, 8)));
4755
4756 assert(posInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 5))) ==
4757 Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
4758 assert(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 6))) ==
4759 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 6)));
4760 assert(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 7))) ==
4761 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
4762 assert(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 8))) ==
4763 Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
4764
4765 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4766 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4767 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4768 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4769 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4770 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4771 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4772 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4773 assert(!posInfInterval.intersection(interval).empty);
4774 assert(!posInfInterval.intersection(cInterval).empty);
4775 assert(!posInfInterval.intersection(iInterval).empty);
4776 assert(!posInfInterval.intersection(posInfInterval).empty);
4777 assert(!posInfInterval.intersection(cPosInfInterval).empty);
4778 assert(!posInfInterval.intersection(iPosInfInterval).empty);
4779 assert(!posInfInterval.intersection(negInfInterval).empty);
4780 assert(!posInfInterval.intersection(cNegInfInterval).empty);
4781 assert(!posInfInterval.intersection(iNegInfInterval).empty);
4782 assert(!cPosInfInterval.intersection(interval).empty);
4783 assert(!cPosInfInterval.intersection(cInterval).empty);
4784 assert(!cPosInfInterval.intersection(iInterval).empty);
4785 assert(!cPosInfInterval.intersection(posInfInterval).empty);
4786 assert(!cPosInfInterval.intersection(cPosInfInterval).empty);
4787 assert(!cPosInfInterval.intersection(iPosInfInterval).empty);
4788 assert(!cPosInfInterval.intersection(negInfInterval).empty);
4789 assert(!cPosInfInterval.intersection(cNegInfInterval).empty);
4790 assert(!cPosInfInterval.intersection(iNegInfInterval).empty);
4791 assert(!iPosInfInterval.intersection(interval).empty);
4792 assert(!iPosInfInterval.intersection(cInterval).empty);
4793 assert(!iPosInfInterval.intersection(iInterval).empty);
4794 assert(!iPosInfInterval.intersection(posInfInterval).empty);
4795 assert(!iPosInfInterval.intersection(cPosInfInterval).empty);
4796 assert(!iPosInfInterval.intersection(iPosInfInterval).empty);
4797 assert(!iPosInfInterval.intersection(negInfInterval).empty);
4798 assert(!iPosInfInterval.intersection(cNegInfInterval).empty);
4799 assert(!iPosInfInterval.intersection(iNegInfInterval).empty);
4800
4801 //Verify Examples.
4802 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
4803 Interval!Date(Date(1996, 1, 2), Date(2000, 8, 2)));
4804 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
4805 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17)));
4806
4807 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) ==
4808 PosInfInterval!Date(Date(1996, 1, 2)));
4809 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) ==
4810 PosInfInterval!Date(Date(1999, 1, 12)));
4811
4812 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) ==
4813 Interval!Date(Date(1996, 1, 2), Date(1999, 7, 6)));
4814 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) ==
4815 Interval!Date(Date(1996, 1, 2), Date(2013, 1, 12)));
4816 }
4817
4818 //Test PosInfInterval's isAdjacent().
4819 @safe unittest
4820 {
4821 import std.datetime.date;
4822
4823 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4824
4825 static void testInterval(scope const PosInfInterval!Date posInfInterval, scope const Interval!Date interval)
4826 {
4827 posInfInterval.isAdjacent(interval);
4828 }
4829
4830 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4831
4832 assert(!posInfInterval.isAdjacent(posInfInterval));
4833 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4834 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4835 assert(posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4836 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4837 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4838 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4839 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4840 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4841 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4842 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4843 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4844 assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4845
4846 assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
4847 assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
4848 assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
4849 assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
4850 assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
4851 assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
4852
4853 assert(!PosInfInterval!Date(Date(2010, 7, 3)).isAdjacent(posInfInterval));
4854 assert(!PosInfInterval!Date(Date(2010, 7, 4)).isAdjacent(posInfInterval));
4855 assert(!PosInfInterval!Date(Date(2010, 7, 5)).isAdjacent(posInfInterval));
4856 assert(!PosInfInterval!Date(Date(2012, 1, 6)).isAdjacent(posInfInterval));
4857 assert(!PosInfInterval!Date(Date(2012, 1, 7)).isAdjacent(posInfInterval));
4858 assert(!PosInfInterval!Date(Date(2012, 1, 8)).isAdjacent(posInfInterval));
4859
4860 assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
4861 assert(posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
4862 assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
4863 assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
4864 assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
4865 assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
4866
4867 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4868 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4869 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4870 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4871 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4872 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4873 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4874 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4875 assert(!posInfInterval.isAdjacent(interval));
4876 assert(!posInfInterval.isAdjacent(cInterval));
4877 assert(!posInfInterval.isAdjacent(iInterval));
4878 assert(!posInfInterval.isAdjacent(posInfInterval));
4879 assert(!posInfInterval.isAdjacent(cPosInfInterval));
4880 assert(!posInfInterval.isAdjacent(iPosInfInterval));
4881 assert(!posInfInterval.isAdjacent(negInfInterval));
4882 assert(!posInfInterval.isAdjacent(cNegInfInterval));
4883 assert(!posInfInterval.isAdjacent(iNegInfInterval));
4884 assert(!cPosInfInterval.isAdjacent(interval));
4885 assert(!cPosInfInterval.isAdjacent(cInterval));
4886 assert(!cPosInfInterval.isAdjacent(iInterval));
4887 assert(!cPosInfInterval.isAdjacent(posInfInterval));
4888 assert(!cPosInfInterval.isAdjacent(cPosInfInterval));
4889 assert(!cPosInfInterval.isAdjacent(iPosInfInterval));
4890 assert(!cPosInfInterval.isAdjacent(negInfInterval));
4891 assert(!cPosInfInterval.isAdjacent(cNegInfInterval));
4892 assert(!cPosInfInterval.isAdjacent(iNegInfInterval));
4893 assert(!iPosInfInterval.isAdjacent(interval));
4894 assert(!iPosInfInterval.isAdjacent(cInterval));
4895 assert(!iPosInfInterval.isAdjacent(iInterval));
4896 assert(!iPosInfInterval.isAdjacent(posInfInterval));
4897 assert(!iPosInfInterval.isAdjacent(cPosInfInterval));
4898 assert(!iPosInfInterval.isAdjacent(iPosInfInterval));
4899 assert(!iPosInfInterval.isAdjacent(negInfInterval));
4900 assert(!iPosInfInterval.isAdjacent(cNegInfInterval));
4901 assert(!iPosInfInterval.isAdjacent(iNegInfInterval));
4902
4903 //Verify Examples.
4904 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
4905 assert(!PosInfInterval!Date(Date(1999, 1, 12)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4906
4907 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1990, 1, 7))));
4908 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1996, 1, 2))));
4909
4910 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
4911 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(2000, 7, 1))));
4912 }
4913
4914 //Test PosInfInterval's merge().
4915 @safe unittest
4916 {
4917 import std.datetime.date;
4918
4919 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4920
4921 static void testInterval(scope const PosInfInterval!Date posInfInterval, scope const Interval!Date interval)
4922 {
4923 posInfInterval.merge(interval);
4924 }
4925
4926 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4927
4928 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4929
4930 assert(posInfInterval.merge(posInfInterval) == posInfInterval);
4931 assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
4932 PosInfInterval!Date(Date(2010, 7, 1)));
4933 assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
4934 PosInfInterval!Date(Date(2010, 7, 3)));
4935 assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
4936 PosInfInterval!Date(Date(2010, 7, 3)));
4937 assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
4938 PosInfInterval!Date(Date(2010, 7, 3)));
4939 assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
4940 PosInfInterval!Date(Date(2010, 7, 3)));
4941 assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
4942 PosInfInterval!Date(Date(2010, 7, 4)));
4943 assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
4944 PosInfInterval!Date(Date(2010, 7, 4)));
4945 assert(posInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
4946 PosInfInterval!Date(Date(2010, 7, 4)));
4947 assert(posInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
4948 PosInfInterval!Date(Date(2010, 7, 4)));
4949 assert(posInfInterval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
4950 PosInfInterval!Date(Date(2010, 7, 4)));
4951 assert(posInfInterval.merge(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
4952 PosInfInterval!Date(Date(2010, 7, 4)));
4953
4954 assert(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 3))) == PosInfInterval!Date(Date(2010, 7, 3)));
4955 assert(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 4))) == PosInfInterval!Date(Date(2010, 7, 4)));
4956 assert(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 5))) == PosInfInterval!Date(Date(2010, 7, 4)));
4957 assert(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 6))) == PosInfInterval!Date(Date(2010, 7, 4)));
4958 assert(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 7))) == PosInfInterval!Date(Date(2010, 7, 4)));
4959 assert(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 8))) == PosInfInterval!Date(Date(2010, 7, 4)));
4960
4961 assert(PosInfInterval!Date(Date(2010, 7, 3)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 3)));
4962 assert(PosInfInterval!Date(Date(2010, 7, 4)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4963 assert(PosInfInterval!Date(Date(2010, 7, 5)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4964 assert(PosInfInterval!Date(Date(2012, 1, 6)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4965 assert(PosInfInterval!Date(Date(2012, 1, 7)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4966 assert(PosInfInterval!Date(Date(2012, 1, 8)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4967
4968 static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 3)))));
4969 static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 4)))));
4970 static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 5)))));
4971 static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 6)))));
4972 static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 7)))));
4973 static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 8)))));
4974
4975 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4976 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4977 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4978 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4979 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4980 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4981 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4982 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4983 assert(!posInfInterval.merge(interval).empty);
4984 assert(!posInfInterval.merge(cInterval).empty);
4985 assert(!posInfInterval.merge(iInterval).empty);
4986 assert(!posInfInterval.merge(posInfInterval).empty);
4987 assert(!posInfInterval.merge(cPosInfInterval).empty);
4988 assert(!posInfInterval.merge(iPosInfInterval).empty);
4989 static assert(!__traits(compiles, posInfInterval.merge(negInfInterval)));
4990 static assert(!__traits(compiles, posInfInterval.merge(cNegInfInterval)));
4991 static assert(!__traits(compiles, posInfInterval.merge(iNegInfInterval)));
4992 assert(!cPosInfInterval.merge(interval).empty);
4993 assert(!cPosInfInterval.merge(cInterval).empty);
4994 assert(!cPosInfInterval.merge(iInterval).empty);
4995 assert(!cPosInfInterval.merge(posInfInterval).empty);
4996 assert(!cPosInfInterval.merge(cPosInfInterval).empty);
4997 assert(!cPosInfInterval.merge(iPosInfInterval).empty);
4998 static assert(!__traits(compiles, cPosInfInterval.merge(negInfInterval)));
4999 static assert(!__traits(compiles, cPosInfInterval.merge(cNegInfInterval)));
5000 static assert(!__traits(compiles, cPosInfInterval.merge(iNegInfInterval)));
5001 assert(!iPosInfInterval.merge(interval).empty);
5002 assert(!iPosInfInterval.merge(cInterval).empty);
5003 assert(!iPosInfInterval.merge(iInterval).empty);
5004 assert(!iPosInfInterval.merge(posInfInterval).empty);
5005 assert(!iPosInfInterval.merge(cPosInfInterval).empty);
5006 assert(!iPosInfInterval.merge(iPosInfInterval).empty);
5007 static assert(!__traits(compiles, iPosInfInterval.merge(negInfInterval)));
5008 static assert(!__traits(compiles, iPosInfInterval.merge(cNegInfInterval)));
5009 static assert(!__traits(compiles, iPosInfInterval.merge(iNegInfInterval)));
5010
5011 //Verify Examples.
5012 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
5013 PosInfInterval!Date(Date(1990, 7, 6)));
5014 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
5015 PosInfInterval!Date(Date(1996, 1, 2)));
5016
5017 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1990, 7, 6))) ==
5018 PosInfInterval!Date(Date(1990, 7, 6)));
5019 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1999, 1, 12))) ==
5020 PosInfInterval!Date(Date(1996, 1, 2)));
5021 }
5022
5023 //Test PosInfInterval's span().
5024 @safe unittest
5025 {
5026 import std.datetime.date;
5027
5028 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5029
5030 static void testInterval(scope const PosInfInterval!Date posInfInterval, scope const Interval!Date interval)
5031 {
5032 posInfInterval.span(interval);
5033 }
5034
5035 assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
5036
5037 assert(posInfInterval.span(posInfInterval) == posInfInterval);
5038 assert(posInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
5039 PosInfInterval!Date(Date(2010, 7, 1)));
5040 assert(posInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
5041 PosInfInterval!Date(Date(2010, 7, 1)));
5042 assert(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
5043 PosInfInterval!Date(Date(2010, 7, 3)));
5044 assert(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
5045 PosInfInterval!Date(Date(2010, 7, 3)));
5046 assert(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
5047 PosInfInterval!Date(Date(2010, 7, 3)));
5048 assert(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
5049 PosInfInterval!Date(Date(2010, 7, 3)));
5050 assert(posInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
5051 PosInfInterval!Date(Date(2010, 7, 4)));
5052 assert(posInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
5053 PosInfInterval!Date(Date(2010, 7, 4)));
5054 assert(posInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
5055 PosInfInterval!Date(Date(2010, 7, 4)));
5056 assert(posInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
5057 PosInfInterval!Date(Date(2010, 7, 4)));
5058 assert(posInfInterval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
5059 PosInfInterval!Date(Date(2010, 7, 4)));
5060 assert(posInfInterval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
5061 PosInfInterval!Date(Date(2010, 7, 4)));
5062
5063 assert(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 3))) == PosInfInterval!Date(Date(2010, 7, 3)));
5064 assert(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 4))) == PosInfInterval!Date(Date(2010, 7, 4)));
5065 assert(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 5))) == PosInfInterval!Date(Date(2010, 7, 4)));
5066 assert(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 6))) == PosInfInterval!Date(Date(2010, 7, 4)));
5067 assert(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 7))) == PosInfInterval!Date(Date(2010, 7, 4)));
5068 assert(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 8))) == PosInfInterval!Date(Date(2010, 7, 4)));
5069
5070 assert(PosInfInterval!Date(Date(2010, 7, 3)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 3)));
5071 assert(PosInfInterval!Date(Date(2010, 7, 4)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5072 assert(PosInfInterval!Date(Date(2010, 7, 5)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5073 assert(PosInfInterval!Date(Date(2012, 1, 6)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5074 assert(PosInfInterval!Date(Date(2012, 1, 7)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5075 assert(PosInfInterval!Date(Date(2012, 1, 8)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5076
5077 static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 3)))));
5078 static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 4)))));
5079 static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 5)))));
5080 static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 6)))));
5081 static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 7)))));
5082 static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 8)))));
5083
5084 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
5085 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
5086 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
5087 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5088 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5089 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
5090 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
5091 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
5092 assert(!posInfInterval.span(interval).empty);
5093 assert(!posInfInterval.span(cInterval).empty);
5094 assert(!posInfInterval.span(iInterval).empty);
5095 assert(!posInfInterval.span(posInfInterval).empty);
5096 assert(!posInfInterval.span(cPosInfInterval).empty);
5097 assert(!posInfInterval.span(iPosInfInterval).empty);
5098 static assert(!__traits(compiles, posInfInterval.span(negInfInterval)));
5099 static assert(!__traits(compiles, posInfInterval.span(cNegInfInterval)));
5100 static assert(!__traits(compiles, posInfInterval.span(iNegInfInterval)));
5101 assert(!cPosInfInterval.span(interval).empty);
5102 assert(!cPosInfInterval.span(cInterval).empty);
5103 assert(!cPosInfInterval.span(iInterval).empty);
5104 assert(!cPosInfInterval.span(posInfInterval).empty);
5105 assert(!cPosInfInterval.span(cPosInfInterval).empty);
5106 assert(!cPosInfInterval.span(iPosInfInterval).empty);
5107 static assert(!__traits(compiles, cPosInfInterval.span(negInfInterval)));
5108 static assert(!__traits(compiles, cPosInfInterval.span(cNegInfInterval)));
5109 static assert(!__traits(compiles, cPosInfInterval.span(iNegInfInterval)));
5110 assert(!iPosInfInterval.span(interval).empty);
5111 assert(!iPosInfInterval.span(cInterval).empty);
5112 assert(!iPosInfInterval.span(iInterval).empty);
5113 assert(!iPosInfInterval.span(posInfInterval).empty);
5114 assert(!iPosInfInterval.span(cPosInfInterval).empty);
5115 assert(!iPosInfInterval.span(iPosInfInterval).empty);
5116 static assert(!__traits(compiles, iPosInfInterval.span(negInfInterval)));
5117 static assert(!__traits(compiles, iPosInfInterval.span(cNegInfInterval)));
5118 static assert(!__traits(compiles, iPosInfInterval.span(iNegInfInterval)));
5119
5120 //Verify Examples.
5121 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(500, 8, 9), Date(1602, 1, 31))) ==
5122 PosInfInterval!Date(Date(500, 8, 9)));
5123 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
5124 PosInfInterval!Date(Date(1990, 7, 6)));
5125 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
5126 PosInfInterval!Date(Date(1996, 1, 2)));
5127
5128 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1990, 7, 6))) ==
5129 PosInfInterval!Date(Date(1990, 7, 6)));
5130 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1999, 1, 12))) ==
5131 PosInfInterval!Date(Date(1996, 1, 2)));
5132 }
5133
5134 //Test PosInfInterval's shift().
5135 @safe unittest
5136 {
5137 import std.datetime.date;
5138
5139 auto interval = PosInfInterval!Date(Date(2010, 7, 4));
5140
testInterval(I)5141 static void testInterval(I)(I interval, scope const Duration duration,
5142 scope const I expected, size_t line = __LINE__)
5143 {
5144 interval.shift(duration);
5145 assert(interval == expected);
5146 }
5147
5148 testInterval(interval, dur!"days"(22), PosInfInterval!Date(Date(2010, 7, 26)));
5149 testInterval(interval, dur!"days"(-22), PosInfInterval!Date(Date(2010, 6, 12)));
5150
5151 const cInterval = PosInfInterval!Date(Date(2010, 7, 4));
5152 immutable iInterval = PosInfInterval!Date(Date(2010, 7, 4));
5153 static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
5154 static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
5155
5156 //Verify Examples.
5157 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
5158 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
5159
5160 interval1.shift(dur!"days"(50));
5161 assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
5162
5163 interval2.shift(dur!"days"(-50));
5164 assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
5165 }
5166
5167 //Test PosInfInterval's shift(int, int, AllowDayOverflow).
5168 @safe unittest
5169 {
5170 import std.datetime.date;
5171
5172 {
5173 auto interval = PosInfInterval!Date(Date(2010, 7, 4));
5174
testInterval(I)5175 static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
5176 in I expected, size_t line = __LINE__)
5177 {
5178 interval.shift(years, months, allow);
5179 assert(interval == expected);
5180 }
5181
5182 testInterval(interval, 5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2015, 7, 4)));
5183 testInterval(interval, -5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2005, 7, 4)));
5184
5185 auto interval2 = PosInfInterval!Date(Date(2000, 1, 29));
5186
5187 testInterval(interval2, 1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2001, 3, 1)));
5188 testInterval(interval2, 1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2000, 12, 29)));
5189 testInterval(interval2, -1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1998, 12, 29)));
5190 testInterval(interval2, -1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1999, 3, 1)));
5191
5192 testInterval(interval2, 1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(2001, 2, 28)));
5193 testInterval(interval2, 1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(2000, 12, 29)));
5194 testInterval(interval2, -1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(1998, 12, 29)));
5195 testInterval(interval2, -1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(1999, 2, 28)));
5196 }
5197
5198 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5199 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5200 static assert(!__traits(compiles, cPosInfInterval.shift(1)));
5201 static assert(!__traits(compiles, iPosInfInterval.shift(1)));
5202
5203 //Verify Examples.
5204 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
5205 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
5206
5207 interval1.shift(2);
5208 assert(interval1 == PosInfInterval!Date(Date(1998, 1, 2)));
5209
5210 interval2.shift(-2);
5211 assert(interval2 == PosInfInterval!Date(Date(1994, 1, 2)));
5212 }
5213
5214 //Test PosInfInterval's expand().
5215 @safe unittest
5216 {
5217 import std.datetime.date;
5218
5219 auto interval = PosInfInterval!Date(Date(2000, 7, 4));
5220
testInterval(I)5221 static void testInterval(I)(I interval, scope const Duration duration,
5222 scope const I expected, size_t line = __LINE__)
5223 {
5224 interval.expand(duration);
5225 assert(interval == expected);
5226 }
5227
5228 testInterval(interval, dur!"days"(22), PosInfInterval!Date(Date(2000, 6, 12)));
5229 testInterval(interval, dur!"days"(-22), PosInfInterval!Date(Date(2000, 7, 26)));
5230
5231 const cInterval = PosInfInterval!Date(Date(2010, 7, 4));
5232 immutable iInterval = PosInfInterval!Date(Date(2010, 7, 4));
5233 static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
5234 static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
5235
5236 //Verify Examples.
5237 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
5238 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
5239
5240 interval1.expand(dur!"days"(2));
5241 assert(interval1 == PosInfInterval!Date(Date(1995, 12, 31)));
5242
5243 interval2.expand(dur!"days"(-2));
5244 assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
5245 }
5246
5247 //Test PosInfInterval's expand(int, int, AllowDayOverflow).
5248 @safe unittest
5249 {
5250 import std.datetime.date;
5251
5252 {
5253 auto interval = PosInfInterval!Date(Date(2000, 7, 4));
5254
testInterval(I)5255 static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
5256 in I expected, size_t line = __LINE__)
5257 {
5258 interval.expand(years, months, allow);
5259 assert(interval == expected);
5260 }
5261
5262 testInterval(interval, 5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(1995, 7, 4)));
5263 testInterval(interval, -5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2005, 7, 4)));
5264
5265 auto interval2 = PosInfInterval!Date(Date(2000, 1, 29));
5266
5267 testInterval(interval2, 1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1998, 12, 29)));
5268 testInterval(interval2, 1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1999, 3, 1)));
5269 testInterval(interval2, -1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2001, 3, 1)));
5270 testInterval(interval2, -1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2000, 12, 29)));
5271
5272 testInterval(interval2, 1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(1998, 12, 29)));
5273 testInterval(interval2, 1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(1999, 2, 28)));
5274 testInterval(interval2, -1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(2001, 2, 28)));
5275 testInterval(interval2, -1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(2000, 12, 29)));
5276 }
5277
5278 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5279 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5280 static assert(!__traits(compiles, cPosInfInterval.expand(1)));
5281 static assert(!__traits(compiles, iPosInfInterval.expand(1)));
5282
5283 //Verify Examples.
5284 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
5285 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
5286
5287 interval1.expand(2);
5288 assert(interval1 == PosInfInterval!Date(Date(1994, 1, 2)));
5289
5290 interval2.expand(-2);
5291 assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
5292 }
5293
5294 //Test PosInfInterval's fwdRange().
5295 @system unittest
5296 {
5297 import std.datetime.date;
5298
5299 auto posInfInterval = PosInfInterval!Date(Date(2010, 9, 19));
5300
5301 static void testInterval(PosInfInterval!Date posInfInterval)
5302 {
5303 posInfInterval.fwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).popFront();
5304 }
5305
5306 assertThrown!DateTimeException(testInterval(posInfInterval));
5307
5308 assert(PosInfInterval!Date(Date(2010, 9, 12)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).front ==
5309 Date(2010, 9, 12));
5310
5311 assert(PosInfInterval!Date(Date(2010, 9, 12)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).front ==
5312 Date(2010, 9, 17));
5313
5314 //Verify Examples.
5315 auto interval = PosInfInterval!Date(Date(2010, 9, 1));
delegate(scope const Date date)5316 auto func = delegate (scope const Date date)
5317 {
5318 if ((date.day & 1) == 0)
5319 return date + dur!"days"(2);
5320 return date + dur!"days"(1);
5321 };
5322 auto range = interval.fwdRange(func);
5323
5324 assert(range.front == Date(2010, 9, 1)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
5325
5326 range.popFront();
5327 assert(range.front == Date(2010, 9, 2));
5328
5329 range.popFront();
5330 assert(range.front == Date(2010, 9, 4));
5331
5332 range.popFront();
5333 assert(range.front == Date(2010, 9, 6));
5334
5335 range.popFront();
5336 assert(range.front == Date(2010, 9, 8));
5337
5338 range.popFront();
5339 assert(!range.empty);
5340
5341 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5342 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5343 assert(!cPosInfInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
5344 assert(!iPosInfInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
5345 }
5346
5347 //Test PosInfInterval's toString().
5348 @safe unittest
5349 {
5350 import std.datetime.date;
5351 assert(PosInfInterval!Date(Date(2010, 7, 4)).toString() == "[2010-Jul-04 - ∞)");
5352
5353 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5354 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5355 assert(cPosInfInterval.toString());
5356 assert(iPosInfInterval.toString());
5357 }
5358
5359
5360 /++
5361 Represents an interval of time which has negative infinity as its starting
5362 point.
5363
5364 Any ranges which iterate over a `NegInfInterval` are infinite. So, the
5365 main purpose of using `NegInfInterval` is to create an infinite range
5366 which starts at negative infinity and goes to a fixed end point.
5367 Iterate over it in reverse.
5368 +/
NegInfInterval(TP)5369 struct NegInfInterval(TP)
5370 {
5371 public:
5372
5373 /++
5374 Params:
5375 end = The time point which ends the interval.
5376
5377 Example:
5378 --------------------
5379 auto interval = PosInfInterval!Date(Date(1996, 1, 2));
5380 --------------------
5381 +/
5382 this(scope const TP end) pure nothrow
5383 {
5384 _end = cast(TP) end;
5385 }
5386
5387
5388 /++
5389 Params:
5390 rhs = The `NegInfInterval` to assign to this one.
5391 +/
5392 ref NegInfInterval opAssign(const ref NegInfInterval rhs) pure nothrow
5393 {
5394 _end = cast(TP) rhs._end;
5395 return this;
5396 }
5397
5398
5399 /++
5400 Params:
5401 rhs = The `NegInfInterval` to assign to this one.
5402 +/
5403 ref NegInfInterval opAssign(NegInfInterval rhs) pure nothrow
5404 {
5405 _end = cast(TP) rhs._end;
5406 return this;
5407 }
5408
5409
5410 /++
5411 The end point of the interval. It is excluded from the interval.
5412
5413 Example:
5414 --------------------
5415 assert(NegInfInterval!Date(Date(2012, 3, 1)).end == Date(2012, 3, 1));
5416 --------------------
5417 +/
5418 @property TP end() const pure nothrow
5419 {
5420 return cast(TP)_end;
5421 }
5422
5423
5424 /++
5425 The end point of the interval. It is excluded from the interval.
5426
5427 Params:
5428 timePoint = The time point to set end to.
5429 +/
5430 @property void end(TP timePoint) pure nothrow
5431 {
5432 _end = timePoint;
5433 }
5434
5435
5436 /++
5437 Whether the interval's length is 0. Always returns false.
5438
5439 Example:
5440 --------------------
5441 assert(!NegInfInterval!Date(Date(1996, 1, 2)).empty);
5442 --------------------
5443 +/
5444 enum bool empty = false;
5445
5446
5447 /++
5448 Whether the given time point is within this interval.
5449
5450 Params:
5451 timePoint = The time point to check for inclusion in this interval.
5452
5453 Example:
5454 --------------------
5455 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
5456 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
5457 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
5458 --------------------
5459 +/
5460 bool contains(TP timePoint) const pure nothrow
5461 {
5462 return timePoint < _end;
5463 }
5464
5465
5466 /++
5467 Whether the given interval is completely within this interval.
5468
5469 Params:
5470 interval = The interval to check for inclusion in this interval.
5471
5472 Throws:
5473 $(REF DateTimeException,std,datetime,date) if the given interval
5474 is empty.
5475
5476 Example:
5477 --------------------
5478 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(
5479 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5480
5481 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(
5482 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
5483
5484 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(
5485 Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
5486 --------------------
5487 +/
5488 bool contains(scope const Interval!TP interval) const pure
5489 {
5490 interval._enforceNotEmpty();
5491 return interval._end <= _end;
5492 }
5493
5494
5495 /++
5496 Whether the given interval is completely within this interval.
5497
5498 Always returns false because an interval beginning at negative
5499 infinity can never contain an interval going to positive infinity.
5500
5501 Params:
5502 interval = The interval to check for inclusion in this interval.
5503
5504 Example:
5505 --------------------
5506 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(
5507 PosInfInterval!Date(Date(1999, 5, 4))));
5508 --------------------
5509 +/
5510 bool contains(scope const PosInfInterval!TP interval) const pure nothrow
5511 {
5512 return false;
5513 }
5514
5515
5516 /++
5517 Whether the given interval is completely within this interval.
5518
5519 Params:
5520 interval = The interval to check for inclusion in this interval.
5521
5522 Example:
5523 --------------------
5524 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(
5525 NegInfInterval!Date(Date(1996, 5, 4))));
5526
5527 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(
5528 NegInfInterval!Date(Date(2013, 7, 9))));
5529 --------------------
5530 +/
5531 bool contains(scope const NegInfInterval interval) const pure nothrow
5532 {
5533 return interval._end <= _end;
5534 }
5535
5536
5537 /++
5538 Whether this interval is before the given time point.
5539
5540 Params:
5541 timePoint = The time point to check whether this interval is
5542 before it.
5543
5544 Example:
5545 --------------------
5546 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
5547 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
5548 assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
5549 --------------------
5550 +/
5551 bool isBefore(scope const TP timePoint) const pure nothrow
5552 {
5553 return timePoint >= _end;
5554 }
5555
5556
5557 /++
5558 Whether this interval is before the given interval and does not
5559 intersect it.
5560
5561 Params:
5562 interval = The interval to check for against this interval.
5563
5564 Throws:
5565 $(REF DateTimeException,std,datetime,date) if the given interval
5566 is empty
5567
5568 Example:
5569 --------------------
5570 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5571 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5572
5573 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5574 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
5575
5576 assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5577 Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
5578 --------------------
5579 +/
5580 bool isBefore(scope const Interval!TP interval) const pure
5581 {
5582 interval._enforceNotEmpty();
5583 return _end <= interval._begin;
5584 }
5585
5586
5587 /++
5588 Whether this interval is before the given interval and does not
5589 intersect it.
5590
5591 Params:
5592 interval = The interval to check for against this interval.
5593
5594 Example:
5595 --------------------
5596 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5597 PosInfInterval!Date(Date(1999, 5, 4))));
5598
5599 assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5600 PosInfInterval!Date(Date(2012, 3, 1))));
5601 --------------------
5602 +/
5603 bool isBefore(scope const PosInfInterval!TP interval) const pure nothrow
5604 {
5605 return _end <= interval._begin;
5606 }
5607
5608
5609 /++
5610 Whether this interval is before the given interval and does not
5611 intersect it.
5612
5613 Always returns false because an interval beginning at negative
5614 infinity can never be before another interval beginning at negative
5615 infinity.
5616
5617 Params:
5618 interval = The interval to check for against this interval.
5619
5620 Example:
5621 --------------------
5622 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5623 NegInfInterval!Date(Date(1996, 5, 4))));
5624
5625 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5626 NegInfInterval!Date(Date(2013, 7, 9))));
5627 --------------------
5628 +/
5629 bool isBefore(scope const NegInfInterval interval) const pure nothrow
5630 {
5631 return false;
5632 }
5633
5634
5635 /++
5636 Whether this interval is after the given time point.
5637
5638 Always returns false because an interval beginning at negative infinity
5639 can never be after any time point.
5640
5641 Params:
5642 timePoint = The time point to check whether this interval is after
5643 it.
5644
5645 Example:
5646 --------------------
5647 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
5648 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
5649 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
5650 --------------------
5651 +/
5652 bool isAfter(scope const TP timePoint) const pure nothrow
5653 {
5654 return false;
5655 }
5656
5657
5658 /++
5659 Whether this interval is after the given interval and does not
5660 intersect it.
5661
5662 Always returns false (unless the given interval is empty) because an
5663 interval beginning at negative infinity can never be after any other
5664 interval.
5665
5666 Params:
5667 interval = The interval to check against this interval.
5668
5669 Throws:
5670 $(REF DateTimeException,std,datetime,date) if the given interval
5671 is empty.
5672
5673 Example:
5674 --------------------
5675 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5676 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5677
5678 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5679 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
5680
5681 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5682 Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
5683 --------------------
5684 +/
5685 bool isAfter(scope const Interval!TP interval) const pure
5686 {
5687 interval._enforceNotEmpty();
5688 return false;
5689 }
5690
5691
5692 /++
5693 Whether this interval is after the given interval and does not intersect
5694 it.
5695
5696 Always returns false because an interval beginning at negative infinity
5697 can never be after any other interval.
5698
5699 Params:
5700 interval = The interval to check against this interval.
5701
5702 Example:
5703 --------------------
5704 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5705 PosInfInterval!Date(Date(1999, 5, 4))));
5706
5707 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5708 PosInfInterval!Date(Date(2012, 3, 1))));
5709 --------------------
5710 +/
5711 bool isAfter(scope const PosInfInterval!TP interval) const pure nothrow
5712 {
5713 return false;
5714 }
5715
5716
5717 /++
5718 Whether this interval is after the given interval and does not intersect
5719 it.
5720
5721 Always returns false because an interval beginning at negative infinity
5722 can never be after any other interval.
5723
5724 Params:
5725 interval = The interval to check against this interval.
5726
5727 Example:
5728 --------------------
5729 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5730 NegInfInterval!Date(Date(1996, 5, 4))));
5731
5732 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5733 NegInfInterval!Date(Date(2013, 7, 9))));
5734 --------------------
5735 +/
5736 bool isAfter(scope const NegInfInterval interval) const pure nothrow
5737 {
5738 return false;
5739 }
5740
5741
5742 /++
5743 Whether the given interval overlaps this interval.
5744
5745 Params:
5746 interval = The interval to check for intersection with this interval.
5747
5748 Throws:
5749 $(REF DateTimeException,std,datetime,date) if the given interval
5750 is empty.
5751
5752 Example:
5753 --------------------
5754 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5755 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5756
5757 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5758 Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
5759
5760 assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5761 Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
5762 --------------------
5763 +/
5764 bool intersects(scope const Interval!TP interval) const pure
5765 {
5766 interval._enforceNotEmpty();
5767 return interval._begin < _end;
5768 }
5769
5770
5771 /++
5772 Whether the given interval overlaps this interval.
5773
5774 Params:
5775 interval = The interval to check for intersection with this
5776 interval.
5777
5778 Example:
5779 --------------------
5780 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5781 PosInfInterval!Date(Date(1999, 5, 4))));
5782
5783 assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5784 PosInfInterval!Date(Date(2012, 3, 1))));
5785 --------------------
5786 +/
5787 bool intersects(scope const PosInfInterval!TP interval) const pure nothrow
5788 {
5789 return interval._begin < _end;
5790 }
5791
5792
5793 /++
5794 Whether the given interval overlaps this interval.
5795
5796 Always returns true because two intervals beginning at negative infinity
5797 always overlap.
5798
5799 Params:
5800 interval = The interval to check for intersection with this interval.
5801
5802 Example:
5803 --------------------
5804 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5805 NegInfInterval!Date(Date(1996, 5, 4))));
5806
5807 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5808 NegInfInterval!Date(Date(2013, 7, 9))));
5809 --------------------
5810 +/
5811 bool intersects(scope const NegInfInterval!TP interval) const pure nothrow
5812 {
5813 return true;
5814 }
5815
5816
5817 /++
5818 Returns the intersection of two intervals
5819
5820 Params:
5821 interval = The interval to intersect with this interval.
5822
5823 Throws:
5824 $(REF DateTimeException,std,datetime,date) if the two intervals do
5825 not intersect or if the given interval is empty.
5826
5827 Example:
5828 --------------------
5829 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5830 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
5831 Interval!Date(Date(1990, 7 , 6), Date(2000, 8, 2)));
5832
5833 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5834 Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
5835 Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
5836 --------------------
5837 +/
5838 Interval!TP intersection(scope const Interval!TP interval) const
5839 {
5840 import std.format : format;
5841
5842 enforce(this.intersects(interval),
5843 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
5844
5845 auto end = _end < interval._end ? _end : interval._end;
5846
5847 return Interval!TP(interval._begin, end);
5848 }
5849
5850
5851 /++
5852 Returns the intersection of two intervals
5853
5854 Params:
5855 interval = The interval to intersect with this interval.
5856
5857 Throws:
5858 $(REF DateTimeException,std,datetime,date) if the two intervals do
5859 not intersect.
5860
5861 Example:
5862 --------------------
5863 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5864 PosInfInterval!Date(Date(1990, 7, 6))) ==
5865 Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
5866
5867 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5868 PosInfInterval!Date(Date(1999, 1, 12))) ==
5869 Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
5870 --------------------
5871 +/
5872 Interval!TP intersection(scope const PosInfInterval!TP interval) const
5873 {
5874 import std.format : format;
5875
5876 enforce(this.intersects(interval),
5877 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
5878
5879 return Interval!TP(interval._begin, _end);
5880 }
5881
5882
5883 /++
5884 Returns the intersection of two intervals
5885
5886 Params:
5887 interval = The interval to intersect with this interval.
5888
5889 Example:
5890 --------------------
5891 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5892 NegInfInterval!Date(Date(1999, 7, 6))) ==
5893 NegInfInterval!Date(Date(1999, 7 , 6)));
5894
5895 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5896 NegInfInterval!Date(Date(2013, 1, 12))) ==
5897 NegInfInterval!Date(Date(2012, 3 , 1)));
5898 --------------------
5899 +/
5900 NegInfInterval intersection(scope const NegInfInterval interval) const nothrow
5901 {
5902 return NegInfInterval(_end < interval._end ? _end : interval._end);
5903 }
5904
5905
5906 /++
5907 Whether the given interval is adjacent to this interval.
5908
5909 Params:
5910 interval = The interval to check whether its adjecent to this
5911 interval.
5912
5913 Throws:
5914 $(REF DateTimeException,std,datetime,date) if the given interval
5915 is empty.
5916
5917 Example:
5918 --------------------
5919 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5920 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5921
5922 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5923 Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1))));
5924
5925 assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5926 Interval!Date(Date(2012, 3, 1), Date(2019, 2, 2))));
5927
5928 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5929 Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
5930 --------------------
5931 +/
5932 bool isAdjacent(scope const Interval!TP interval) const pure
5933 {
5934 interval._enforceNotEmpty();
5935 return interval._begin == _end;
5936 }
5937
5938
5939 /++
5940 Whether the given interval is adjacent to this interval.
5941
5942 Params:
5943 interval = The interval to check whether its adjecent to this
5944 interval.
5945
5946 Example:
5947 --------------------
5948 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5949 PosInfInterval!Date(Date(1999, 5, 4))));
5950
5951 assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5952 PosInfInterval!Date(Date(2012, 3, 1))));
5953 --------------------
5954 +/
5955 bool isAdjacent(scope const PosInfInterval!TP interval) const pure nothrow
5956 {
5957 return interval._begin == _end;
5958 }
5959
5960
5961 /++
5962 Whether the given interval is adjacent to this interval.
5963
5964 Always returns false because two intervals beginning at negative
5965 infinity can never be adjacent to one another.
5966
5967 Params:
5968 interval = The interval to check whether its adjecent to this
5969 interval.
5970
5971 Example:
5972 --------------------
5973 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5974 NegInfInterval!Date(Date(1996, 5, 4))));
5975
5976 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5977 NegInfInterval!Date(Date(2012, 3, 1))));
5978 --------------------
5979 +/
5980 bool isAdjacent(scope const NegInfInterval interval) const pure nothrow
5981 {
5982 return false;
5983 }
5984
5985
5986 /++
5987 Returns the union of two intervals
5988
5989 Params:
5990 interval = The interval to merge with this interval.
5991
5992 Throws:
5993 $(REF DateTimeException,std,datetime,date) if the two intervals do
5994 not intersect and are not adjacent or if the given interval is empty.
5995
5996 Note:
5997 There is no overload for `merge` which takes a
5998 `PosInfInterval`, because an interval
5999 going from negative infinity to positive infinity
6000 is not possible.
6001
6002 Example:
6003 --------------------
6004 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
6005 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
6006 NegInfInterval!Date(Date(2012, 3 , 1)));
6007
6008 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
6009 Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
6010 NegInfInterval!Date(Date(2015, 9 , 2)));
6011 --------------------
6012 +/
6013 NegInfInterval merge(scope const Interval!TP interval) const
6014 {
6015 import std.format : format;
6016
6017 enforce(this.isAdjacent(interval) || this.intersects(interval),
6018 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
6019
6020 return NegInfInterval(_end > interval._end ? _end : interval._end);
6021 }
6022
6023
6024 /++
6025 Returns the union of two intervals
6026
6027 Params:
6028 interval = The interval to merge with this interval.
6029
6030 Note:
6031 There is no overload for `merge` which takes a
6032 `PosInfInterval`, because an interval
6033 going from negative infinity to positive infinity
6034 is not possible.
6035
6036 Example:
6037 --------------------
6038 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
6039 NegInfInterval!Date(Date(1999, 7, 6))) ==
6040 NegInfInterval!Date(Date(2012, 3 , 1)));
6041
6042 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
6043 NegInfInterval!Date(Date(2013, 1, 12))) ==
6044 NegInfInterval!Date(Date(2013, 1 , 12)));
6045 --------------------
6046 +/
6047 NegInfInterval merge(scope const NegInfInterval interval) const pure nothrow
6048 {
6049 return NegInfInterval(_end > interval._end ? _end : interval._end);
6050 }
6051
6052
6053 /++
6054 Returns an interval that covers from the earliest time point of two
6055 intervals up to (but not including) the latest time point of two
6056 intervals.
6057
6058 Params:
6059 interval = The interval to create a span together with this
6060 interval.
6061
6062 Throws:
6063 $(REF DateTimeException,std,datetime,date) if the given interval
6064 is empty.
6065
6066 Note:
6067 There is no overload for `span` which takes a
6068 `PosInfInterval`, because an interval
6069 going from negative infinity to positive infinity
6070 is not possible.
6071
6072 Example:
6073 --------------------
6074 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
6075 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
6076 NegInfInterval!Date(Date(2012, 3 , 1)));
6077
6078 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
6079 Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
6080 NegInfInterval!Date(Date(2015, 9 , 2)));
6081
6082 assert(NegInfInterval!Date(Date(1600, 1, 7)).span(
6083 Interval!Date(Date(2012, 3, 11), Date(2017, 7, 1))) ==
6084 NegInfInterval!Date(Date(2017, 7 , 1)));
6085 --------------------
6086 +/
6087 NegInfInterval span(scope const Interval!TP interval) const pure
6088 {
6089 interval._enforceNotEmpty();
6090 return NegInfInterval(_end > interval._end ? _end : interval._end);
6091 }
6092
6093
6094 /++
6095 Returns an interval that covers from the earliest time point of two
6096 intervals up to (but not including) the latest time point of two
6097 intervals.
6098
6099 Params:
6100 interval = The interval to create a span together with this
6101 interval.
6102
6103 Note:
6104 There is no overload for `span` which takes a
6105 `PosInfInterval`, because an interval
6106 going from negative infinity to positive infinity
6107 is not possible.
6108
6109 Example:
6110 --------------------
6111 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
6112 NegInfInterval!Date(Date(1999, 7, 6))) ==
6113 NegInfInterval!Date(Date(2012, 3 , 1)));
6114
6115 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
6116 NegInfInterval!Date(Date(2013, 1, 12))) ==
6117 NegInfInterval!Date(Date(2013, 1 , 12)));
6118 --------------------
6119 +/
6120 NegInfInterval span(scope const NegInfInterval interval) const pure nothrow
6121 {
6122 return NegInfInterval(_end > interval._end ? _end : interval._end);
6123 }
6124
6125
6126 /++
6127 Shifts the `end` of this interval forward or backwards in time by the
6128 given duration (a positive duration shifts the interval forward; a
6129 negative duration shifts it backward). Effectively, it does
6130 $(D end += duration).
6131
6132 Params:
6133 duration = The duration to shift the interval by.
6134
6135 Example:
6136 --------------------
6137 auto interval1 = NegInfInterval!Date(Date(2012, 4, 5));
6138 auto interval2 = NegInfInterval!Date(Date(2012, 4, 5));
6139
6140 interval1.shift(dur!"days"(50));
6141 assert(interval1 == NegInfInterval!Date(Date(2012, 5, 25)));
6142
6143 interval2.shift(dur!"days"(-50));
6144 assert(interval2 == NegInfInterval!Date( Date(2012, 2, 15)));
6145 --------------------
6146 +/
6147 void shift(D)(D duration) pure nothrow
6148 if (__traits(compiles, end + duration))
6149 {
6150 _end += duration;
6151 }
6152
6153
6154 static if (__traits(compiles, end.add!"months"(1)) &&
6155 __traits(compiles, end.add!"years"(1)))
6156 {
6157 /++
6158 Shifts the `end` of this interval forward or backwards in time by
6159 the given number of years and/or months (a positive number of years
6160 and months shifts the interval forward; a negative number shifts it
6161 backward). It adds the years the given years and months to end. It
6162 effectively calls `add!"years"()` and then `add!"months"()`
6163 on end with the given number of years and months.
6164
6165 Params:
6166 years = The number of years to shift the interval by.
6167 months = The number of months to shift the interval by.
6168 allowOverflow = Whether the days should be allowed to overflow
6169 on `end`, causing its month to increment.
6170
6171 Throws:
6172 $(REF DateTimeException,std,datetime,date) if empty is true or
6173 if the resulting interval would be invalid.
6174
6175 Example:
6176 --------------------
6177 auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
6178 auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
6179
6180 interval1.shift(2);
6181 assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
6182
6183 interval2.shift(-2);
6184 assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
6185 --------------------
6186 +/
6187 void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
6188 if (isIntegral!T)
6189 {
6190 auto end = _end;
6191
6192 end.add!"years"(years, allowOverflow);
6193 end.add!"months"(months, allowOverflow);
6194
6195 _end = end;
6196 }
6197 }
6198
6199
6200 /++
6201 Expands the interval forwards in time. Effectively, it does
6202 $(D end += duration).
6203
6204 Params:
6205 duration = The duration to expand the interval by.
6206
6207 Example:
6208 --------------------
6209 auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
6210 auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
6211
6212 interval1.expand(dur!"days"(2));
6213 assert(interval1 == NegInfInterval!Date(Date(2012, 3, 3)));
6214
6215 interval2.expand(dur!"days"(-2));
6216 assert(interval2 == NegInfInterval!Date(Date(2012, 2, 28)));
6217 --------------------
6218 +/
6219 void expand(D)(D duration) pure nothrow
6220 if (__traits(compiles, end + duration))
6221 {
6222 _end += duration;
6223 }
6224
6225
6226 static if (__traits(compiles, end.add!"months"(1)) &&
6227 __traits(compiles, end.add!"years"(1)))
6228 {
6229 /++
6230 Expands the interval forwards and/or backwards in time. Effectively,
6231 it adds the given number of months/years to end.
6232
6233 Params:
6234 years = The number of years to expand the interval by.
6235 months = The number of months to expand the interval by.
6236 allowOverflow = Whether the days should be allowed to overflow
6237 on `end`, causing their month to increment.
6238
6239 Throws:
6240 $(REF DateTimeException,std,datetime,date) if empty is true or
6241 if the resulting interval would be invalid.
6242
6243 Example:
6244 --------------------
6245 auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
6246 auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
6247
6248 interval1.expand(2);
6249 assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
6250
6251 interval2.expand(-2);
6252 assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
6253 --------------------
6254 +/
6255 void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
6256 if (isIntegral!T)
6257 {
6258 auto end = _end;
6259
6260 end.add!"years"(years, allowOverflow);
6261 end.add!"months"(months, allowOverflow);
6262
6263 _end = end;
6264 }
6265 }
6266
6267
6268 /++
6269 Returns a range which iterates backwards over the interval, starting
6270 at `end`, using $(D_PARAM func) to generate each successive time
6271 point.
6272
6273 The range's `front` is the interval's `end`. $(D_PARAM func) is
6274 used to generate the next `front` when `popFront` is called. If
6275 $(D_PARAM popFirst) is `PopFirst.yes`, then `popFront` is called
6276 before the range is returned (so that `front` is a time point which
6277 $(D_PARAM func) would generate).
6278
6279 If $(D_PARAM func) ever generates a time point greater than or equal to
6280 the current `front` of the range, then a
6281 $(REF DateTimeException,std,datetime,date) will be thrown.
6282
6283 There are helper functions in this module which generate common
6284 delegates to pass to `bwdRange`. Their documentation starts with
6285 "Range-generating function," to make them easily searchable.
6286
6287 Params:
6288 func = The function used to generate the time points of the
6289 range over the interval.
6290 popFirst = Whether `popFront` should be called on the range
6291 before returning it.
6292
6293 Throws:
6294 $(REF DateTimeException,std,datetime,date) if this interval is
6295 empty.
6296
6297 Warning:
6298 $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
6299 would be a function pointer to a pure function, but forcing
6300 $(D_PARAM func) to be pure is far too restrictive to be useful, and
6301 in order to have the ease of use of having functions which generate
6302 functions to pass to `fwdRange`, $(D_PARAM func) must be a
6303 delegate.
6304
6305 If $(D_PARAM func) retains state which changes as it is called, then
6306 some algorithms will not work correctly, because the range's
6307 `save` will have failed to have really saved the range's state.
6308 To avoid such bugs, don't pass a delegate which is
6309 not logically pure to `fwdRange`. If $(D_PARAM func) is given the
6310 same time point with two different calls, it must return the same
6311 result both times.
6312
6313 Of course, none of the functions in this module have this problem,
6314 so it's only relevant for custom delegates.
6315
6316 Example:
6317 --------------------
6318 auto interval = NegInfInterval!Date(Date(2010, 9, 9));
6319 auto func = delegate (scope const Date date) //For iterating over even-numbered days.
6320 {
6321 if ((date.day & 1) == 0)
6322 return date - dur!"days"(2);
6323
6324 return date - dur!"days"(1);
6325 };
6326 auto range = interval.bwdRange(func);
6327
6328 assert(range.front == Date(2010, 9, 9)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
6329
6330 range.popFront();
6331 assert(range.front == Date(2010, 9, 8));
6332
6333 range.popFront();
6334 assert(range.front == Date(2010, 9, 6));
6335
6336 range.popFront();
6337 assert(range.front == Date(2010, 9, 4));
6338
6339 range.popFront();
6340 assert(range.front == Date(2010, 9, 2));
6341
6342 range.popFront();
6343 assert(!range.empty);
6344 --------------------
6345 +/
6346 NegInfIntervalRange!(TP) bwdRange(TP delegate(scope const TP) func, PopFirst popFirst = PopFirst.no) const
6347 {
6348 auto range = NegInfIntervalRange!(TP)(this, func);
6349
6350 if (popFirst == PopFirst.yes)
6351 range.popFront();
6352
6353 return range;
6354 }
6355
6356
6357 /+
6358 Converts this interval to a string.
6359 +/
6360 // Due to bug https://issues.dlang.org/show_bug.cgi?id=3715 , we can't
6361 // have versions of toString() with extra modifiers,
6362 // so we define one version with modifiers and one without.
6363 string toString()
6364 {
6365 return _toStringImpl();
6366 }
6367
6368
6369 /++
6370 Converts this interval to a string.
6371 +/
6372 // Due to bug https://issues.dlang.org/show_bug.cgi?id=3715 , we can't
6373 // have versions of toString() with extra modifiers,
6374 // so we define one version with modifiers and one without.
6375 string toString() const nothrow
6376 {
6377 return _toStringImpl();
6378 }
6379
6380 private:
6381
6382 /+
6383 Since we have two versions of toString(), we have _toStringImpl()
6384 so that they can share implementations.
6385 +/
6386 string _toStringImpl() const nothrow
6387 {
6388 import std.format : format;
6389 try
6390 return format("[-∞ - %s)", _end);
6391 catch (Exception e)
6392 assert(0, "format() threw.");
6393 }
6394
6395
6396 TP _end;
6397 }
6398
6399 //Test NegInfInterval's constructor.
6400 @safe unittest
6401 {
6402 import std.datetime.date;
6403 import std.datetime.systime;
6404
6405 NegInfInterval!Date(Date.init);
6406 NegInfInterval!TimeOfDay(TimeOfDay.init);
6407 NegInfInterval!DateTime(DateTime.init);
6408 NegInfInterval!SysTime(SysTime(0));
6409 }
6410
6411 //Test NegInfInterval's end.
6412 @safe unittest
6413 {
6414 import std.datetime.date;
6415
6416 assert(NegInfInterval!Date(Date(2010, 1, 1)).end == Date(2010, 1, 1));
6417 assert(NegInfInterval!Date(Date(2010, 1, 1)).end == Date(2010, 1, 1));
6418 assert(NegInfInterval!Date(Date(1998, 1, 1)).end == Date(1998, 1, 1));
6419
6420 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6421 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6422 assert(cNegInfInterval.end != Date.init);
6423 assert(iNegInfInterval.end != Date.init);
6424
6425 //Verify Examples.
6426 assert(NegInfInterval!Date(Date(2012, 3, 1)).end == Date(2012, 3, 1));
6427 }
6428
6429 //Test NegInfInterval's empty.
6430 @safe unittest
6431 {
6432 import std.datetime.date;
6433 import std.datetime.systime;
6434
6435 assert(!NegInfInterval!Date(Date(2010, 1, 1)).empty);
6436 assert(!NegInfInterval!TimeOfDay(TimeOfDay(0, 30, 0)).empty);
6437 assert(!NegInfInterval!DateTime(DateTime(2010, 1, 1, 0, 30, 0)).empty);
6438 assert(!NegInfInterval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0))).empty);
6439
6440 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6441 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6442 assert(!cNegInfInterval.empty);
6443 assert(!iNegInfInterval.empty);
6444
6445 //Verify Examples.
6446 assert(!NegInfInterval!Date(Date(1996, 1, 2)).empty);
6447 }
6448
6449 //Test NegInfInterval's contains(time point).
6450 @safe unittest
6451 {
6452 import std.datetime.date;
6453
6454 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6455
6456 assert(negInfInterval.contains(Date(2009, 7, 4)));
6457 assert(negInfInterval.contains(Date(2010, 7, 3)));
6458 assert(negInfInterval.contains(Date(2010, 7, 4)));
6459 assert(negInfInterval.contains(Date(2010, 7, 5)));
6460 assert(negInfInterval.contains(Date(2011, 7, 1)));
6461 assert(negInfInterval.contains(Date(2012, 1, 6)));
6462 assert(!negInfInterval.contains(Date(2012, 1, 7)));
6463 assert(!negInfInterval.contains(Date(2012, 1, 8)));
6464 assert(!negInfInterval.contains(Date(2013, 1, 7)));
6465
6466 const cdate = Date(2010, 7, 6);
6467 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6468 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6469 assert(negInfInterval.contains(cdate));
6470 assert(cNegInfInterval.contains(cdate));
6471 assert(iNegInfInterval.contains(cdate));
6472
6473 //Verify Examples.
6474 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
6475 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
6476 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
6477 }
6478
6479 //Test NegInfInterval's contains(Interval).
6480 @safe unittest
6481 {
6482 import std.datetime.date;
6483
6484 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6485
6486 static void testInterval(scope const NegInfInterval!Date negInfInterval, scope const Interval!Date interval)
6487 {
6488 negInfInterval.contains(interval);
6489 }
6490
6491 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6492
6493 assert(negInfInterval.contains(negInfInterval));
6494 assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
6495 assert(!negInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
6496 assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
6497 assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
6498 assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
6499 assert(!negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
6500 assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
6501 assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
6502 assert(negInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
6503 assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
6504 assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6505 assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6506
6507 assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
6508 assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
6509 assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
6510 assert(negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
6511 assert(negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
6512 assert(!negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
6513
6514 assert(!NegInfInterval!Date(Date(2010, 7, 3)).contains(negInfInterval));
6515 assert(!NegInfInterval!Date(Date(2010, 7, 4)).contains(negInfInterval));
6516 assert(!NegInfInterval!Date(Date(2010, 7, 5)).contains(negInfInterval));
6517 assert(!NegInfInterval!Date(Date(2012, 1, 6)).contains(negInfInterval));
6518 assert(NegInfInterval!Date(Date(2012, 1, 7)).contains(negInfInterval));
6519 assert(NegInfInterval!Date(Date(2012, 1, 8)).contains(negInfInterval));
6520
6521 assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
6522 assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
6523 assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
6524 assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
6525 assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
6526 assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
6527
6528 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6529 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6530 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6531 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6532 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6533 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6534 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6535 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6536 assert(negInfInterval.contains(interval));
6537 assert(negInfInterval.contains(cInterval));
6538 assert(negInfInterval.contains(iInterval));
6539 assert(!negInfInterval.contains(posInfInterval));
6540 assert(!negInfInterval.contains(cPosInfInterval));
6541 assert(!negInfInterval.contains(iPosInfInterval));
6542 assert(negInfInterval.contains(negInfInterval));
6543 assert(negInfInterval.contains(cNegInfInterval));
6544 assert(negInfInterval.contains(iNegInfInterval));
6545 assert(cNegInfInterval.contains(interval));
6546 assert(cNegInfInterval.contains(cInterval));
6547 assert(cNegInfInterval.contains(iInterval));
6548 assert(!cNegInfInterval.contains(posInfInterval));
6549 assert(!cNegInfInterval.contains(cPosInfInterval));
6550 assert(!cNegInfInterval.contains(iPosInfInterval));
6551 assert(cNegInfInterval.contains(negInfInterval));
6552 assert(cNegInfInterval.contains(cNegInfInterval));
6553 assert(cNegInfInterval.contains(iNegInfInterval));
6554 assert(iNegInfInterval.contains(interval));
6555 assert(iNegInfInterval.contains(cInterval));
6556 assert(iNegInfInterval.contains(iInterval));
6557 assert(!iNegInfInterval.contains(posInfInterval));
6558 assert(!iNegInfInterval.contains(cPosInfInterval));
6559 assert(!iNegInfInterval.contains(iPosInfInterval));
6560 assert(iNegInfInterval.contains(negInfInterval));
6561 assert(iNegInfInterval.contains(cNegInfInterval));
6562 assert(iNegInfInterval.contains(iNegInfInterval));
6563
6564 //Verify Examples.
6565 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
6566 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
6567 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
6568
6569 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
6570
6571 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
6572 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(2013, 7, 9))));
6573 }
6574
6575 //Test NegInfInterval's isBefore(time point).
6576 @safe unittest
6577 {
6578 import std.datetime.date;
6579
6580 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6581
6582 assert(!negInfInterval.isBefore(Date(2009, 7, 4)));
6583 assert(!negInfInterval.isBefore(Date(2010, 7, 3)));
6584 assert(!negInfInterval.isBefore(Date(2010, 7, 4)));
6585 assert(!negInfInterval.isBefore(Date(2010, 7, 5)));
6586 assert(!negInfInterval.isBefore(Date(2011, 7, 1)));
6587 assert(!negInfInterval.isBefore(Date(2012, 1, 6)));
6588 assert(negInfInterval.isBefore(Date(2012, 1, 7)));
6589 assert(negInfInterval.isBefore(Date(2012, 1, 8)));
6590 assert(negInfInterval.isBefore(Date(2013, 1, 7)));
6591
6592 const cdate = Date(2010, 7, 6);
6593 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6594 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6595 assert(!negInfInterval.isBefore(cdate));
6596 assert(!cNegInfInterval.isBefore(cdate));
6597 assert(!iNegInfInterval.isBefore(cdate));
6598
6599 //Verify Examples.
6600 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
6601 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
6602 assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
6603 }
6604
6605 //Test NegInfInterval's isBefore(Interval).
6606 @safe unittest
6607 {
6608 import std.datetime.date;
6609
6610 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6611
6612 static void testInterval(scope const NegInfInterval!Date negInfInterval, scope const Interval!Date interval)
6613 {
6614 negInfInterval.isBefore(interval);
6615 }
6616
6617 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6618
6619 assert(!negInfInterval.isBefore(negInfInterval));
6620 assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
6621 assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
6622 assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
6623 assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
6624 assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
6625 assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
6626 assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
6627 assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
6628 assert(!negInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
6629 assert(!negInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
6630 assert(negInfInterval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6631 assert(negInfInterval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6632
6633 assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
6634 assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
6635 assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
6636 assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
6637 assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
6638 assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
6639
6640 assert(!NegInfInterval!Date(Date(2010, 7, 3)).isBefore(negInfInterval));
6641 assert(!NegInfInterval!Date(Date(2010, 7, 4)).isBefore(negInfInterval));
6642 assert(!NegInfInterval!Date(Date(2010, 7, 5)).isBefore(negInfInterval));
6643 assert(!NegInfInterval!Date(Date(2012, 1, 6)).isBefore(negInfInterval));
6644 assert(!NegInfInterval!Date(Date(2012, 1, 7)).isBefore(negInfInterval));
6645 assert(!NegInfInterval!Date(Date(2012, 1, 8)).isBefore(negInfInterval));
6646
6647 assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
6648 assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
6649 assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
6650 assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
6651 assert(negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
6652 assert(negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
6653
6654 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6655 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6656 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6657 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6658 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6659 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6660 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6661 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6662 assert(!negInfInterval.isBefore(interval));
6663 assert(!negInfInterval.isBefore(cInterval));
6664 assert(!negInfInterval.isBefore(iInterval));
6665 assert(!negInfInterval.isBefore(posInfInterval));
6666 assert(!negInfInterval.isBefore(cPosInfInterval));
6667 assert(!negInfInterval.isBefore(iPosInfInterval));
6668 assert(!negInfInterval.isBefore(negInfInterval));
6669 assert(!negInfInterval.isBefore(cNegInfInterval));
6670 assert(!negInfInterval.isBefore(iNegInfInterval));
6671 assert(!cNegInfInterval.isBefore(interval));
6672 assert(!cNegInfInterval.isBefore(cInterval));
6673 assert(!cNegInfInterval.isBefore(iInterval));
6674 assert(!cNegInfInterval.isBefore(posInfInterval));
6675 assert(!cNegInfInterval.isBefore(cPosInfInterval));
6676 assert(!cNegInfInterval.isBefore(iPosInfInterval));
6677 assert(!cNegInfInterval.isBefore(negInfInterval));
6678 assert(!cNegInfInterval.isBefore(cNegInfInterval));
6679 assert(!cNegInfInterval.isBefore(iNegInfInterval));
6680 assert(!iNegInfInterval.isBefore(interval));
6681 assert(!iNegInfInterval.isBefore(cInterval));
6682 assert(!iNegInfInterval.isBefore(iInterval));
6683 assert(!iNegInfInterval.isBefore(posInfInterval));
6684 assert(!iNegInfInterval.isBefore(cPosInfInterval));
6685 assert(!iNegInfInterval.isBefore(iPosInfInterval));
6686 assert(!iNegInfInterval.isBefore(negInfInterval));
6687 assert(!iNegInfInterval.isBefore(cNegInfInterval));
6688 assert(!iNegInfInterval.isBefore(iNegInfInterval));
6689
6690 //Verify Examples.
6691 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
6692 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
6693 assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
6694
6695 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
6696 assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2012, 3, 1))));
6697
6698 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
6699 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(2013, 7, 9))));
6700 }
6701
6702 //Test NegInfInterval's isAfter(time point).
6703 @safe unittest
6704 {
6705 import std.datetime.date;
6706
6707 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6708
6709 assert(!negInfInterval.isAfter(Date(2009, 7, 4)));
6710 assert(!negInfInterval.isAfter(Date(2010, 7, 3)));
6711 assert(!negInfInterval.isAfter(Date(2010, 7, 4)));
6712 assert(!negInfInterval.isAfter(Date(2010, 7, 5)));
6713 assert(!negInfInterval.isAfter(Date(2011, 7, 1)));
6714 assert(!negInfInterval.isAfter(Date(2012, 1, 6)));
6715 assert(!negInfInterval.isAfter(Date(2012, 1, 7)));
6716 assert(!negInfInterval.isAfter(Date(2012, 1, 8)));
6717 assert(!negInfInterval.isAfter(Date(2013, 1, 7)));
6718
6719 const cdate = Date(2010, 7, 6);
6720 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6721 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6722 assert(!negInfInterval.isAfter(cdate));
6723 assert(!cNegInfInterval.isAfter(cdate));
6724 assert(!iNegInfInterval.isAfter(cdate));
6725 }
6726
6727 //Test NegInfInterval's isAfter(Interval).
6728 @safe unittest
6729 {
6730 import std.datetime.date;
6731
6732 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6733
6734 static void testInterval(scope const NegInfInterval!Date negInfInterval, scope const Interval!Date interval)
6735 {
6736 negInfInterval.isAfter(interval);
6737 }
6738
6739 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6740
6741 assert(!negInfInterval.isAfter(negInfInterval));
6742 assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
6743 assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
6744 assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
6745 assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
6746 assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
6747 assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
6748 assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
6749 assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
6750 assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
6751 assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
6752 assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6753 assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6754
6755 assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
6756 assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
6757 assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
6758 assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
6759 assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
6760 assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
6761
6762 assert(!NegInfInterval!Date(Date(2010, 7, 3)).isAfter(negInfInterval));
6763 assert(!NegInfInterval!Date(Date(2010, 7, 4)).isAfter(negInfInterval));
6764 assert(!NegInfInterval!Date(Date(2010, 7, 5)).isAfter(negInfInterval));
6765 assert(!NegInfInterval!Date(Date(2012, 1, 6)).isAfter(negInfInterval));
6766 assert(!NegInfInterval!Date(Date(2012, 1, 7)).isAfter(negInfInterval));
6767 assert(!NegInfInterval!Date(Date(2012, 1, 8)).isAfter(negInfInterval));
6768
6769 assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
6770 assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
6771 assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
6772 assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
6773 assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
6774 assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
6775
6776 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6777 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6778 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6779 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6780 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6781 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6782 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6783 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6784 assert(!negInfInterval.isAfter(interval));
6785 assert(!negInfInterval.isAfter(cInterval));
6786 assert(!negInfInterval.isAfter(iInterval));
6787 assert(!negInfInterval.isAfter(posInfInterval));
6788 assert(!negInfInterval.isAfter(cPosInfInterval));
6789 assert(!negInfInterval.isAfter(iPosInfInterval));
6790 assert(!negInfInterval.isAfter(negInfInterval));
6791 assert(!negInfInterval.isAfter(cNegInfInterval));
6792 assert(!negInfInterval.isAfter(iNegInfInterval));
6793 assert(!cNegInfInterval.isAfter(interval));
6794 assert(!cNegInfInterval.isAfter(cInterval));
6795 assert(!cNegInfInterval.isAfter(iInterval));
6796 assert(!cNegInfInterval.isAfter(posInfInterval));
6797 assert(!cNegInfInterval.isAfter(cPosInfInterval));
6798 assert(!cNegInfInterval.isAfter(iPosInfInterval));
6799 assert(!cNegInfInterval.isAfter(negInfInterval));
6800 assert(!cNegInfInterval.isAfter(cNegInfInterval));
6801 assert(!cNegInfInterval.isAfter(iNegInfInterval));
6802 assert(!iNegInfInterval.isAfter(interval));
6803 assert(!iNegInfInterval.isAfter(cInterval));
6804 assert(!iNegInfInterval.isAfter(iInterval));
6805 assert(!iNegInfInterval.isAfter(posInfInterval));
6806 assert(!iNegInfInterval.isAfter(cPosInfInterval));
6807 assert(!iNegInfInterval.isAfter(iPosInfInterval));
6808 assert(!iNegInfInterval.isAfter(negInfInterval));
6809 assert(!iNegInfInterval.isAfter(cNegInfInterval));
6810 assert(!iNegInfInterval.isAfter(iNegInfInterval));
6811
6812 //Verify Examples.
6813 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
6814 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
6815 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
6816
6817 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
6818 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
6819 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
6820
6821 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
6822 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(2012, 3, 1))));
6823
6824 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 5, 4))));
6825 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(2013, 7, 9))));
6826 }
6827
6828 //Test NegInfInterval's intersects().
6829 @safe unittest
6830 {
6831 import std.datetime.date;
6832
6833 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6834
6835 static void testInterval(scope const NegInfInterval!Date negInfInterval, scope const Interval!Date interval)
6836 {
6837 negInfInterval.intersects(interval);
6838 }
6839
6840 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6841
6842 assert(negInfInterval.intersects(negInfInterval));
6843 assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
6844 assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
6845 assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
6846 assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
6847 assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
6848 assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
6849 assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
6850 assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
6851 assert(negInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
6852 assert(negInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
6853 assert(!negInfInterval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6854 assert(!negInfInterval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6855
6856 assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
6857 assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
6858 assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
6859 assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
6860 assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
6861 assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
6862
6863 assert(NegInfInterval!Date(Date(2010, 7, 3)).intersects(negInfInterval));
6864 assert(NegInfInterval!Date(Date(2010, 7, 4)).intersects(negInfInterval));
6865 assert(NegInfInterval!Date(Date(2010, 7, 5)).intersects(negInfInterval));
6866 assert(NegInfInterval!Date(Date(2012, 1, 6)).intersects(negInfInterval));
6867 assert(NegInfInterval!Date(Date(2012, 1, 7)).intersects(negInfInterval));
6868 assert(NegInfInterval!Date(Date(2012, 1, 8)).intersects(negInfInterval));
6869
6870 assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
6871 assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
6872 assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
6873 assert(negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
6874 assert(!negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
6875 assert(!negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
6876
6877 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6878 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6879 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6880 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6881 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6882 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6883 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6884 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6885 assert(negInfInterval.intersects(interval));
6886 assert(negInfInterval.intersects(cInterval));
6887 assert(negInfInterval.intersects(iInterval));
6888 assert(negInfInterval.intersects(posInfInterval));
6889 assert(negInfInterval.intersects(cPosInfInterval));
6890 assert(negInfInterval.intersects(iPosInfInterval));
6891 assert(negInfInterval.intersects(negInfInterval));
6892 assert(negInfInterval.intersects(cNegInfInterval));
6893 assert(negInfInterval.intersects(iNegInfInterval));
6894 assert(cNegInfInterval.intersects(interval));
6895 assert(cNegInfInterval.intersects(cInterval));
6896 assert(cNegInfInterval.intersects(iInterval));
6897 assert(cNegInfInterval.intersects(posInfInterval));
6898 assert(cNegInfInterval.intersects(cPosInfInterval));
6899 assert(cNegInfInterval.intersects(iPosInfInterval));
6900 assert(cNegInfInterval.intersects(negInfInterval));
6901 assert(cNegInfInterval.intersects(cNegInfInterval));
6902 assert(cNegInfInterval.intersects(iNegInfInterval));
6903 assert(iNegInfInterval.intersects(interval));
6904 assert(iNegInfInterval.intersects(cInterval));
6905 assert(iNegInfInterval.intersects(iInterval));
6906 assert(iNegInfInterval.intersects(posInfInterval));
6907 assert(iNegInfInterval.intersects(cPosInfInterval));
6908 assert(iNegInfInterval.intersects(iPosInfInterval));
6909 assert(iNegInfInterval.intersects(negInfInterval));
6910 assert(iNegInfInterval.intersects(cNegInfInterval));
6911 assert(iNegInfInterval.intersects(iNegInfInterval));
6912
6913 //Verify Examples.
6914 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
6915 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
6916 assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
6917
6918 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
6919 assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
6920
6921 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 5, 4))));
6922 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2013, 7, 9))));
6923 }
6924
6925 //Test NegInfInterval's intersection().
6926 @safe unittest
6927 {
6928 import std.datetime.date;
6929
6930 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6931
testInterval(I,J)6932 static void testInterval(I, J)(scope const I interval1, scope const J interval2)
6933 {
6934 interval1.intersection(interval2);
6935 }
6936
6937 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6938
6939 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6940 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6941
6942 assertThrown!DateTimeException(testInterval(negInfInterval, PosInfInterval!Date(Date(2012, 1, 7))));
6943 assertThrown!DateTimeException(testInterval(negInfInterval, PosInfInterval!Date(Date(2012, 1, 8))));
6944
6945 assert(negInfInterval.intersection(negInfInterval) == negInfInterval);
6946 assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
6947 Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)));
6948 assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
6949 Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
6950 assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
6951 Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)));
6952 assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
6953 Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)));
6954 assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
6955 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
6956 assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
6957 Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
6958 assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
6959 Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
6960 assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
6961 Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
6962 assert(negInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
6963 Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
6964 assert(negInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
6965 Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
6966
6967 assert(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 3))) == NegInfInterval!Date(Date(2010, 7, 3)));
6968 assert(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 4))) == NegInfInterval!Date(Date(2010, 7, 4)));
6969 assert(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 5))) == NegInfInterval!Date(Date(2010, 7, 5)));
6970 assert(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 6))) == NegInfInterval!Date(Date(2012, 1, 6)));
6971 assert(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 7))) == NegInfInterval!Date(Date(2012, 1, 7)));
6972 assert(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 8))) == NegInfInterval!Date(Date(2012, 1, 7)));
6973
6974 assert(NegInfInterval!Date(Date(2010, 7, 3)).intersection(negInfInterval) == NegInfInterval!Date(Date(2010, 7, 3)));
6975 assert(NegInfInterval!Date(Date(2010, 7, 4)).intersection(negInfInterval) == NegInfInterval!Date(Date(2010, 7, 4)));
6976 assert(NegInfInterval!Date(Date(2010, 7, 5)).intersection(negInfInterval) == NegInfInterval!Date(Date(2010, 7, 5)));
6977 assert(NegInfInterval!Date(Date(2012, 1, 6)).intersection(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 6)));
6978 assert(NegInfInterval!Date(Date(2012, 1, 7)).intersection(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
6979 assert(NegInfInterval!Date(Date(2012, 1, 8)).intersection(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
6980
6981 assert(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 3))) ==
6982 Interval!Date(Date(2010, 7, 3), Date(2012, 1 ,7)));
6983 assert(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 4))) ==
6984 Interval!Date(Date(2010, 7, 4), Date(2012, 1 ,7)));
6985 assert(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 5))) ==
6986 Interval!Date(Date(2010, 7, 5), Date(2012, 1 ,7)));
6987 assert(negInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 6))) ==
6988 Interval!Date(Date(2012, 1, 6), Date(2012, 1 ,7)));
6989
6990 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6991 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6992 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6993 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6994 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6995 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6996 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6997 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6998 assert(!negInfInterval.intersection(interval).empty);
6999 assert(!negInfInterval.intersection(cInterval).empty);
7000 assert(!negInfInterval.intersection(iInterval).empty);
7001 assert(!negInfInterval.intersection(posInfInterval).empty);
7002 assert(!negInfInterval.intersection(cPosInfInterval).empty);
7003 assert(!negInfInterval.intersection(iPosInfInterval).empty);
7004 assert(!negInfInterval.intersection(negInfInterval).empty);
7005 assert(!negInfInterval.intersection(cNegInfInterval).empty);
7006 assert(!negInfInterval.intersection(iNegInfInterval).empty);
7007 assert(!cNegInfInterval.intersection(interval).empty);
7008 assert(!cNegInfInterval.intersection(cInterval).empty);
7009 assert(!cNegInfInterval.intersection(iInterval).empty);
7010 assert(!cNegInfInterval.intersection(posInfInterval).empty);
7011 assert(!cNegInfInterval.intersection(cPosInfInterval).empty);
7012 assert(!cNegInfInterval.intersection(iPosInfInterval).empty);
7013 assert(!cNegInfInterval.intersection(negInfInterval).empty);
7014 assert(!cNegInfInterval.intersection(cNegInfInterval).empty);
7015 assert(!cNegInfInterval.intersection(iNegInfInterval).empty);
7016 assert(!iNegInfInterval.intersection(interval).empty);
7017 assert(!iNegInfInterval.intersection(cInterval).empty);
7018 assert(!iNegInfInterval.intersection(iInterval).empty);
7019 assert(!iNegInfInterval.intersection(posInfInterval).empty);
7020 assert(!iNegInfInterval.intersection(cPosInfInterval).empty);
7021 assert(!iNegInfInterval.intersection(iPosInfInterval).empty);
7022 assert(!iNegInfInterval.intersection(negInfInterval).empty);
7023 assert(!iNegInfInterval.intersection(cNegInfInterval).empty);
7024 assert(!iNegInfInterval.intersection(iNegInfInterval).empty);
7025
7026 //Verify Examples.
7027 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
7028 Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2)));
7029 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
7030 Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1)));
7031
7032 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) ==
7033 Interval!Date(Date(1990, 7, 6), Date(2012, 3, 1)));
7034 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) ==
7035 Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1)));
7036
7037 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) ==
7038 NegInfInterval!Date(Date(1999, 7, 6)));
7039 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) ==
7040 NegInfInterval!Date(Date(2012, 3, 1)));
7041 }
7042
7043 //Test NegInfInterval's isAdjacent().
7044 @safe unittest
7045 {
7046 import std.datetime.date;
7047
7048 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7049
7050 static void testInterval(scope const NegInfInterval!Date negInfInterval, scope const Interval!Date interval)
7051 {
7052 negInfInterval.isAdjacent(interval);
7053 }
7054
7055 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
7056
7057 assert(!negInfInterval.isAdjacent(negInfInterval));
7058 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
7059 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
7060 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
7061 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
7062 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
7063 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
7064 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
7065 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
7066 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
7067 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
7068 assert(negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
7069 assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
7070
7071 assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
7072 assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
7073 assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
7074 assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
7075 assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
7076 assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
7077
7078 assert(!NegInfInterval!Date(Date(2010, 7, 3)).isAdjacent(negInfInterval));
7079 assert(!NegInfInterval!Date(Date(2010, 7, 4)).isAdjacent(negInfInterval));
7080 assert(!NegInfInterval!Date(Date(2010, 7, 5)).isAdjacent(negInfInterval));
7081 assert(!NegInfInterval!Date(Date(2012, 1, 6)).isAdjacent(negInfInterval));
7082 assert(!NegInfInterval!Date(Date(2012, 1, 7)).isAdjacent(negInfInterval));
7083 assert(!NegInfInterval!Date(Date(2012, 1, 8)).isAdjacent(negInfInterval));
7084
7085 assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
7086 assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
7087 assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
7088 assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
7089 assert(negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
7090 assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
7091
7092 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7093 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7094 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7095 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7096 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7097 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7098 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7099 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7100 assert(!negInfInterval.isAdjacent(interval));
7101 assert(!negInfInterval.isAdjacent(cInterval));
7102 assert(!negInfInterval.isAdjacent(iInterval));
7103 assert(!negInfInterval.isAdjacent(posInfInterval));
7104 assert(!negInfInterval.isAdjacent(cPosInfInterval));
7105 assert(!negInfInterval.isAdjacent(iPosInfInterval));
7106 assert(!negInfInterval.isAdjacent(negInfInterval));
7107 assert(!negInfInterval.isAdjacent(cNegInfInterval));
7108 assert(!negInfInterval.isAdjacent(iNegInfInterval));
7109 assert(!cNegInfInterval.isAdjacent(interval));
7110 assert(!cNegInfInterval.isAdjacent(cInterval));
7111 assert(!cNegInfInterval.isAdjacent(iInterval));
7112 assert(!cNegInfInterval.isAdjacent(posInfInterval));
7113 assert(!cNegInfInterval.isAdjacent(cPosInfInterval));
7114 assert(!cNegInfInterval.isAdjacent(iPosInfInterval));
7115 assert(!cNegInfInterval.isAdjacent(negInfInterval));
7116 assert(!cNegInfInterval.isAdjacent(cNegInfInterval));
7117 assert(!cNegInfInterval.isAdjacent(iNegInfInterval));
7118 assert(!iNegInfInterval.isAdjacent(interval));
7119 assert(!iNegInfInterval.isAdjacent(cInterval));
7120 assert(!iNegInfInterval.isAdjacent(iInterval));
7121 assert(!iNegInfInterval.isAdjacent(posInfInterval));
7122 assert(!iNegInfInterval.isAdjacent(cPosInfInterval));
7123 assert(!iNegInfInterval.isAdjacent(iPosInfInterval));
7124 assert(!iNegInfInterval.isAdjacent(negInfInterval));
7125 assert(!iNegInfInterval.isAdjacent(cNegInfInterval));
7126 assert(!iNegInfInterval.isAdjacent(iNegInfInterval));
7127
7128 //Verify Examples.
7129 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
7130 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1))));
7131 assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2012, 3, 1), Date(2019, 2, 2))));
7132 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
7133
7134 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
7135 assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
7136
7137 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 5, 4))));
7138 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(2012, 3, 1))));
7139 }
7140
7141 //Test NegInfInterval's merge().
7142 @safe unittest
7143 {
7144 import std.datetime.date;
7145
7146 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7147
testInterval(I,J)7148 static void testInterval(I, J)(scope const I interval1, scope const J interval2)
7149 {
7150 interval1.merge(interval2);
7151 }
7152
7153 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
7154
7155 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
7156
7157 assert(negInfInterval.merge(negInfInterval) == negInfInterval);
7158 assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
7159 NegInfInterval!Date(Date(2012, 1, 7)));
7160 assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
7161 NegInfInterval!Date(Date(2013, 7, 3)));
7162 assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
7163 NegInfInterval!Date(Date(2012, 1, 7)));
7164 assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
7165 NegInfInterval!Date(Date(2012, 1, 7)));
7166 assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
7167 NegInfInterval!Date(Date(2012, 1, 7)));
7168 assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
7169 NegInfInterval!Date(Date(2012, 1, 8)));
7170 assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
7171 NegInfInterval!Date(Date(2012, 1, 7)));
7172 assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
7173 NegInfInterval!Date(Date(2012, 1, 7)));
7174 assert(negInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
7175 NegInfInterval!Date(Date(2012, 1, 7)));
7176 assert(negInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
7177 NegInfInterval!Date(Date(2012, 1, 8)));
7178 assert(negInfInterval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
7179 NegInfInterval!Date(Date(2012, 1, 8)));
7180
7181 assert(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 3))) == NegInfInterval!Date(Date(2012, 1, 7)));
7182 assert(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 4))) == NegInfInterval!Date(Date(2012, 1, 7)));
7183 assert(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 5))) == NegInfInterval!Date(Date(2012, 1, 7)));
7184 assert(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 6))) == NegInfInterval!Date(Date(2012, 1, 7)));
7185 assert(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 7))) == NegInfInterval!Date(Date(2012, 1, 7)));
7186 assert(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 8))) == NegInfInterval!Date(Date(2012, 1, 8)));
7187
7188 assert(NegInfInterval!Date(Date(2010, 7, 3)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7189 assert(NegInfInterval!Date(Date(2010, 7, 4)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7190 assert(NegInfInterval!Date(Date(2010, 7, 5)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7191 assert(NegInfInterval!Date(Date(2012, 1, 6)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7192 assert(NegInfInterval!Date(Date(2012, 1, 7)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7193 assert(NegInfInterval!Date(Date(2012, 1, 8)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 8)));
7194
7195 static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 3)))));
7196 static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 4)))));
7197 static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 5)))));
7198 static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 6)))));
7199 static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 7)))));
7200 static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 8)))));
7201
7202 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7203 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7204 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7205 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7206 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7207 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7208 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7209 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7210 assert(!negInfInterval.merge(interval).empty);
7211 assert(!negInfInterval.merge(cInterval).empty);
7212 assert(!negInfInterval.merge(iInterval).empty);
7213 static assert(!__traits(compiles, negInfInterval.merge(posInfInterval)));
7214 static assert(!__traits(compiles, negInfInterval.merge(cPosInfInterval)));
7215 static assert(!__traits(compiles, negInfInterval.merge(iPosInfInterval)));
7216 assert(!negInfInterval.merge(negInfInterval).empty);
7217 assert(!negInfInterval.merge(cNegInfInterval).empty);
7218 assert(!negInfInterval.merge(iNegInfInterval).empty);
7219 assert(!cNegInfInterval.merge(interval).empty);
7220 assert(!cNegInfInterval.merge(cInterval).empty);
7221 assert(!cNegInfInterval.merge(iInterval).empty);
7222 static assert(!__traits(compiles, cNegInfInterval.merge(posInfInterval)));
7223 static assert(!__traits(compiles, cNegInfInterval.merge(cPosInfInterval)));
7224 static assert(!__traits(compiles, cNegInfInterval.merge(iPosInfInterval)));
7225 assert(!cNegInfInterval.merge(negInfInterval).empty);
7226 assert(!cNegInfInterval.merge(cNegInfInterval).empty);
7227 assert(!cNegInfInterval.merge(iNegInfInterval).empty);
7228 assert(!iNegInfInterval.merge(interval).empty);
7229 assert(!iNegInfInterval.merge(cInterval).empty);
7230 assert(!iNegInfInterval.merge(iInterval).empty);
7231 static assert(!__traits(compiles, iNegInfInterval.merge(posInfInterval)));
7232 static assert(!__traits(compiles, iNegInfInterval.merge(cPosInfInterval)));
7233 static assert(!__traits(compiles, iNegInfInterval.merge(iPosInfInterval)));
7234 assert(!iNegInfInterval.merge(negInfInterval).empty);
7235 assert(!iNegInfInterval.merge(cNegInfInterval).empty);
7236 assert(!iNegInfInterval.merge(iNegInfInterval).empty);
7237
7238 //Verify Examples.
7239 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
7240 NegInfInterval!Date(Date(2012, 3, 1)));
7241 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
7242 NegInfInterval!Date(Date(2015, 9, 2)));
7243
7244 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1999, 7, 6))) ==
7245 NegInfInterval!Date(Date(2012, 3, 1)));
7246 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) ==
7247 NegInfInterval!Date(Date(2013, 1, 12)));
7248 }
7249
7250 //Test NegInfInterval's span().
7251 @safe unittest
7252 {
7253 import std.datetime.date;
7254
7255 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7256
testInterval(I,J)7257 static void testInterval(I, J)(scope const I interval1, scope const J interval2)
7258 {
7259 interval1.span(interval2);
7260 }
7261
7262 assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
7263
7264 assert(negInfInterval.span(negInfInterval) == negInfInterval);
7265 assert(negInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
7266 NegInfInterval!Date(Date(2012, 1, 7)));
7267 assert(negInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
7268 NegInfInterval!Date(Date(2013, 7, 3)));
7269 assert(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
7270 NegInfInterval!Date(Date(2012, 1, 7)));
7271 assert(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
7272 NegInfInterval!Date(Date(2012, 1, 7)));
7273 assert(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
7274 NegInfInterval!Date(Date(2012, 1, 7)));
7275 assert(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
7276 NegInfInterval!Date(Date(2012, 1, 8)));
7277 assert(negInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
7278 NegInfInterval!Date(Date(2012, 1, 7)));
7279 assert(negInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
7280 NegInfInterval!Date(Date(2012, 1, 7)));
7281 assert(negInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
7282 NegInfInterval!Date(Date(2012, 1, 7)));
7283 assert(negInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
7284 NegInfInterval!Date(Date(2012, 1, 8)));
7285 assert(negInfInterval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
7286 NegInfInterval!Date(Date(2012, 1, 8)));
7287 assert(negInfInterval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
7288 NegInfInterval!Date(Date(2012, 1, 9)));
7289
7290 assert(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 3))) == NegInfInterval!Date(Date(2012, 1, 7)));
7291 assert(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 4))) == NegInfInterval!Date(Date(2012, 1, 7)));
7292 assert(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 5))) == NegInfInterval!Date(Date(2012, 1, 7)));
7293 assert(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 6))) == NegInfInterval!Date(Date(2012, 1, 7)));
7294 assert(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 7))) == NegInfInterval!Date(Date(2012, 1, 7)));
7295 assert(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 8))) == NegInfInterval!Date(Date(2012, 1, 8)));
7296
7297 assert(NegInfInterval!Date(Date(2010, 7, 3)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7298 assert(NegInfInterval!Date(Date(2010, 7, 4)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7299 assert(NegInfInterval!Date(Date(2010, 7, 5)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7300 assert(NegInfInterval!Date(Date(2012, 1, 6)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7301 assert(NegInfInterval!Date(Date(2012, 1, 7)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7302 assert(NegInfInterval!Date(Date(2012, 1, 8)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 8)));
7303
7304 static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 3)))));
7305 static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 4)))));
7306 static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 5)))));
7307 static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 6)))));
7308 static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 7)))));
7309 static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 8)))));
7310
7311 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7312 const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7313 immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7314 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7315 const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7316 immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7317 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7318 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7319 assert(!negInfInterval.span(interval).empty);
7320 assert(!negInfInterval.span(cInterval).empty);
7321 assert(!negInfInterval.span(iInterval).empty);
7322 static assert(!__traits(compiles, negInfInterval.span(posInfInterval)));
7323 static assert(!__traits(compiles, negInfInterval.span(cPosInfInterval)));
7324 static assert(!__traits(compiles, negInfInterval.span(iPosInfInterval)));
7325 assert(!negInfInterval.span(negInfInterval).empty);
7326 assert(!negInfInterval.span(cNegInfInterval).empty);
7327 assert(!negInfInterval.span(iNegInfInterval).empty);
7328 assert(!cNegInfInterval.span(interval).empty);
7329 assert(!cNegInfInterval.span(cInterval).empty);
7330 assert(!cNegInfInterval.span(iInterval).empty);
7331 static assert(!__traits(compiles, cNegInfInterval.span(posInfInterval)));
7332 static assert(!__traits(compiles, cNegInfInterval.span(cPosInfInterval)));
7333 static assert(!__traits(compiles, cNegInfInterval.span(iPosInfInterval)));
7334 assert(!cNegInfInterval.span(negInfInterval).empty);
7335 assert(!cNegInfInterval.span(cNegInfInterval).empty);
7336 assert(!cNegInfInterval.span(iNegInfInterval).empty);
7337 assert(!iNegInfInterval.span(interval).empty);
7338 assert(!iNegInfInterval.span(cInterval).empty);
7339 assert(!iNegInfInterval.span(iInterval).empty);
7340 static assert(!__traits(compiles, iNegInfInterval.span(posInfInterval)));
7341 static assert(!__traits(compiles, iNegInfInterval.span(cPosInfInterval)));
7342 static assert(!__traits(compiles, iNegInfInterval.span(iPosInfInterval)));
7343 assert(!iNegInfInterval.span(negInfInterval).empty);
7344 assert(!iNegInfInterval.span(cNegInfInterval).empty);
7345 assert(!iNegInfInterval.span(iNegInfInterval).empty);
7346
7347 //Verify Examples.
7348 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
7349 NegInfInterval!Date(Date(2012, 3, 1)));
7350 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
7351 NegInfInterval!Date(Date(2015, 9, 2)));
7352 assert(NegInfInterval!Date(Date(1600, 1, 7)).span(Interval!Date(Date(2012, 3, 11), Date(2017, 7, 1))) ==
7353 NegInfInterval!Date(Date(2017, 7, 1)));
7354
7355 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1999, 7, 6))) ==
7356 NegInfInterval!Date(Date(2012, 3, 1)));
7357 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) ==
7358 NegInfInterval!Date(Date(2013, 1, 12)));
7359 }
7360
7361 //Test NegInfInterval's shift().
7362 @safe unittest
7363 {
7364 import std.datetime.date;
7365
7366 auto interval = NegInfInterval!Date(Date(2012, 1, 7));
7367
testInterval(I)7368 static void testInterval(I)(I interval, scope const Duration duration,
7369 scope const I expected, size_t line = __LINE__)
7370 {
7371 interval.shift(duration);
7372 assert(interval == expected);
7373 }
7374
7375 testInterval(interval, dur!"days"(22), NegInfInterval!Date(Date(2012, 1, 29)));
7376 testInterval(interval, dur!"days"(-22), NegInfInterval!Date(Date(2011, 12, 16)));
7377
7378 const cInterval = NegInfInterval!Date(Date(2012, 1, 7));
7379 immutable iInterval = NegInfInterval!Date(Date(2012, 1, 7));
7380 static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
7381 static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
7382
7383 //Verify Examples.
7384 auto interval1 = NegInfInterval!Date(Date(2012, 4, 5));
7385 auto interval2 = NegInfInterval!Date(Date(2012, 4, 5));
7386
7387 interval1.shift(dur!"days"(50));
7388 assert(interval1 == NegInfInterval!Date(Date(2012, 5, 25)));
7389
7390 interval2.shift(dur!"days"(-50));
7391 assert(interval2 == NegInfInterval!Date( Date(2012, 2, 15)));
7392 }
7393
7394 //Test NegInfInterval's shift(int, int, AllowDayOverflow).
7395 @safe unittest
7396 {
7397 import std.datetime.date;
7398
7399 {
7400 auto interval = NegInfInterval!Date(Date(2012, 1, 7));
7401
testIntervalFail(I)7402 static void testIntervalFail(I)(I interval, int years, int months)
7403 {
7404 interval.shift(years, months);
7405 }
7406
testInterval(I)7407 static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
7408 in I expected, size_t line = __LINE__)
7409 {
7410 interval.shift(years, months, allow);
7411 assert(interval == expected);
7412 }
7413
7414 testInterval(interval, 5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2017, 1, 7)));
7415 testInterval(interval, -5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2007, 1, 7)));
7416
7417 auto interval2 = NegInfInterval!Date(Date(2010, 5, 31));
7418
7419 testInterval(interval2, 1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 7, 1)));
7420 testInterval(interval2, 1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 5, 1)));
7421 testInterval(interval2, -1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 5, 1)));
7422 testInterval(interval2, -1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 7, 1)));
7423
7424 testInterval(interval2, 1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 6, 30)));
7425 testInterval(interval2, 1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 4, 30)));
7426 testInterval(interval2, -1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 4, 30)));
7427 testInterval(interval2, -1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 6, 30)));
7428 }
7429
7430 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7431 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7432 static assert(!__traits(compiles, cNegInfInterval.shift(1)));
7433 static assert(!__traits(compiles, iNegInfInterval.shift(1)));
7434
7435 //Verify Examples.
7436 auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
7437 auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
7438
7439 interval1.shift(2);
7440 assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
7441
7442 interval2.shift(-2);
7443 assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
7444 }
7445
7446 //Test NegInfInterval's expand().
7447 @safe unittest
7448 {
7449 import std.datetime.date;
7450
7451 auto interval = NegInfInterval!Date(Date(2012, 1, 7));
7452
testInterval(I)7453 static void testInterval(I)(I interval,
7454 scope const Duration duration, scope const I expected, size_t line = __LINE__)
7455 {
7456 interval.expand(duration);
7457 assert(interval == expected);
7458 }
7459
7460 testInterval(interval, dur!"days"(22), NegInfInterval!Date(Date(2012, 1, 29)));
7461 testInterval(interval, dur!"days"(-22), NegInfInterval!Date(Date(2011, 12, 16)));
7462
7463 const cInterval = NegInfInterval!Date(Date(2012, 1, 7));
7464 immutable iInterval = NegInfInterval!Date(Date(2012, 1, 7));
7465 static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
7466 static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
7467
7468 //Verify Examples.
7469 auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
7470 auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
7471
7472 interval1.expand(dur!"days"(2));
7473 assert(interval1 == NegInfInterval!Date(Date(2012, 3, 3)));
7474
7475 interval2.expand(dur!"days"(-2));
7476 assert(interval2 == NegInfInterval!Date(Date(2012, 2, 28)));
7477 }
7478
7479 //Test NegInfInterval's expand(int, int, AllowDayOverflow).
7480 @safe unittest
7481 {
7482 import std.datetime.date;
7483
7484 {
7485 auto interval = NegInfInterval!Date(Date(2012, 1, 7));
7486
testInterval(I)7487 static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
7488 in I expected, size_t line = __LINE__)
7489 {
7490 interval.expand(years, months, allow);
7491 assert(interval == expected);
7492 }
7493
7494 testInterval(interval, 5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2017, 1, 7)));
7495 testInterval(interval, -5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2007, 1, 7)));
7496
7497 auto interval2 = NegInfInterval!Date(Date(2010, 5, 31));
7498
7499 testInterval(interval2, 1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 7, 1)));
7500 testInterval(interval2, 1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 5, 1)));
7501 testInterval(interval2, -1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 5, 1)));
7502 testInterval(interval2, -1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 7, 1)));
7503
7504 testInterval(interval2, 1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 6, 30)));
7505 testInterval(interval2, 1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 4, 30)));
7506 testInterval(interval2, -1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 4, 30)));
7507 testInterval(interval2, -1, 1, AllowDayOverflow.no, NegInfInterval!Date( Date(2009, 6, 30)));
7508 }
7509
7510 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7511 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7512 static assert(!__traits(compiles, cNegInfInterval.expand(1)));
7513 static assert(!__traits(compiles, iNegInfInterval.expand(1)));
7514
7515 //Verify Examples.
7516 auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
7517 auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
7518
7519 interval1.expand(2);
7520 assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
7521
7522 interval2.expand(-2);
7523 assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
7524 }
7525
7526 //Test NegInfInterval's bwdRange().
7527 @system unittest
7528 {
7529 import std.datetime.date;
7530
7531 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7532
7533 static void testInterval(NegInfInterval!Date negInfInterval)
7534 {
7535 negInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.fwd)(DayOfWeek.fri)).popFront();
7536 }
7537
7538 assertThrown!DateTimeException(testInterval(negInfInterval));
7539
7540 assert(NegInfInterval!Date(Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).front ==
7541 Date(2010, 10, 1));
7542
7543 assert(NegInfInterval!Date(Date(2010, 10, 1)).bwdRange(
7544 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).front == Date(2010, 9, 24));
7545
7546 //Verify Examples.
7547 auto interval = NegInfInterval!Date(Date(2010, 9, 9));
delegate(scope const Date date)7548 auto func = delegate (scope const Date date)
7549 {
7550 if ((date.day & 1) == 0)
7551 return date - dur!"days"(2);
7552 return date - dur!"days"(1);
7553 };
7554 auto range = interval.bwdRange(func);
7555
7556 //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
7557 assert(range.front == Date(2010, 9, 9));
7558
7559 range.popFront();
7560 assert(range.front == Date(2010, 9, 8));
7561
7562 range.popFront();
7563 assert(range.front == Date(2010, 9, 6));
7564
7565 range.popFront();
7566 assert(range.front == Date(2010, 9, 4));
7567
7568 range.popFront();
7569 assert(range.front == Date(2010, 9, 2));
7570
7571 range.popFront();
7572 assert(!range.empty);
7573
7574 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7575 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7576 assert(!cNegInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).empty);
7577 assert(!iNegInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).empty);
7578 }
7579
7580 //Test NegInfInterval's toString().
7581 @safe unittest
7582 {
7583 import std.datetime.date;
7584
7585 assert(NegInfInterval!Date(Date(2012, 1, 7)).toString() == "[-∞ - 2012-Jan-07)");
7586
7587 const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7588 immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7589 assert(cNegInfInterval.toString());
7590 assert(iNegInfInterval.toString());
7591 }
7592
7593
7594 /++
7595 Range-generating function.
7596
7597 Returns a delegate which returns the next time point with the given
7598 `DayOfWeek` in a range.
7599
7600 Using this delegate allows iteration over successive time points which
7601 are all the same day of the week. e.g. passing `DayOfWeek.mon` to
7602 `everyDayOfWeek` would result in a delegate which could be used to
7603 iterate over all of the Mondays in a range.
7604
7605 Params:
7606 dir = The direction to iterate in. If passing the return value to
7607 `fwdRange`, use `Direction.fwd`. If passing it to
7608 `bwdRange`, use `Direction.bwd`.
7609 dayOfWeek = The week that each time point in the range will be.
7610 +/
7611 TP delegate(scope const TP) everyDayOfWeek(TP, Direction dir = Direction.fwd)(DayOfWeek dayOfWeek) nothrow
7612 if (isTimePoint!TP &&
7613 (dir == Direction.fwd || dir == Direction.bwd) &&
7614 __traits(hasMember, TP, "dayOfWeek") &&
7615 !__traits(isStaticFunction, TP.dayOfWeek) &&
7616 is(typeof(TP.dayOfWeek) == DayOfWeek))
7617 {
func(scope const TP tp)7618 TP func(scope const TP tp)
7619 {
7620 TP retval = cast(TP) tp;
7621 immutable days = daysToDayOfWeek(retval.dayOfWeek, dayOfWeek);
7622
7623 static if (dir == Direction.fwd)
7624 immutable adjustedDays = days == 0 ? 7 : days;
7625 else
7626 immutable adjustedDays = days == 0 ? -7 : days - 7;
7627
7628 return retval += dur!"days"(adjustedDays);
7629 }
7630
7631 return &func;
7632 }
7633
7634 ///
7635 @system unittest
7636 {
7637 import std.datetime.date : Date, DayOfWeek;
7638
7639 auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
7640 auto func = everyDayOfWeek!Date(DayOfWeek.mon);
7641 auto range = interval.fwdRange(func);
7642
7643 // A Thursday. Using PopFirst.yes would have made this Date(2010, 9, 6).
7644 assert(range.front == Date(2010, 9, 2));
7645
7646 range.popFront();
7647 assert(range.front == Date(2010, 9, 6));
7648
7649 range.popFront();
7650 assert(range.front == Date(2010, 9, 13));
7651
7652 range.popFront();
7653 assert(range.front == Date(2010, 9, 20));
7654
7655 range.popFront();
7656 assert(range.empty);
7657 }
7658
7659 @system unittest
7660 {
7661 import std.datetime.date;
7662 import std.datetime.systime;
7663
7664 auto funcFwd = everyDayOfWeek!Date(DayOfWeek.mon);
7665 auto funcBwd = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.mon);
7666
7667 assert(funcFwd(Date(2010, 8, 28)) == Date(2010, 8, 30));
7668 assert(funcFwd(Date(2010, 8, 29)) == Date(2010, 8, 30));
7669 assert(funcFwd(Date(2010, 8, 30)) == Date(2010, 9, 6));
7670 assert(funcFwd(Date(2010, 8, 31)) == Date(2010, 9, 6));
7671 assert(funcFwd(Date(2010, 9, 1)) == Date(2010, 9, 6));
7672 assert(funcFwd(Date(2010, 9, 2)) == Date(2010, 9, 6));
7673 assert(funcFwd(Date(2010, 9, 3)) == Date(2010, 9, 6));
7674 assert(funcFwd(Date(2010, 9, 4)) == Date(2010, 9, 6));
7675 assert(funcFwd(Date(2010, 9, 5)) == Date(2010, 9, 6));
7676 assert(funcFwd(Date(2010, 9, 6)) == Date(2010, 9, 13));
7677 assert(funcFwd(Date(2010, 9, 7)) == Date(2010, 9, 13));
7678
7679 assert(funcBwd(Date(2010, 8, 28)) == Date(2010, 8, 23));
7680 assert(funcBwd(Date(2010, 8, 29)) == Date(2010, 8, 23));
7681 assert(funcBwd(Date(2010, 8, 30)) == Date(2010, 8, 23));
7682 assert(funcBwd(Date(2010, 8, 31)) == Date(2010, 8, 30));
7683 assert(funcBwd(Date(2010, 9, 1)) == Date(2010, 8, 30));
7684 assert(funcBwd(Date(2010, 9, 2)) == Date(2010, 8, 30));
7685 assert(funcBwd(Date(2010, 9, 3)) == Date(2010, 8, 30));
7686 assert(funcBwd(Date(2010, 9, 4)) == Date(2010, 8, 30));
7687 assert(funcBwd(Date(2010, 9, 5)) == Date(2010, 8, 30));
7688 assert(funcBwd(Date(2010, 9, 6)) == Date(2010, 8, 30));
7689 assert(funcBwd(Date(2010, 9, 7)) == Date(2010, 9, 6));
7690
7691 static assert(!__traits(compiles, everyDayOfWeek!TimeOfDay(DayOfWeek.mon)));
7692 assert(everyDayOfWeek!DateTime(DayOfWeek.mon) !is null);
7693 assert(everyDayOfWeek!SysTime(DayOfWeek.mon) !is null);
7694 }
7695
7696
7697 /++
7698 Range-generating function.
7699
7700 Returns a delegate which returns the next time point with the given month
7701 which would be reached by adding months to the given time point.
7702
7703 So, using this delegate allows iteration over successive time points
7704 which are in the same month but different years. For example,
7705 iterate over each successive December 25th in an interval by starting with a
7706 date which had the 25th as its day and passed `Month.dec` to
7707 `everyMonth` to create the delegate.
7708
7709 Since it wouldn't really make sense to be iterating over a specific month
7710 and end up with some of the time points in the succeeding month or two years
7711 after the previous time point, `AllowDayOverflow.no` is always used when
7712 calculating the next time point.
7713
7714 Params:
7715 dir = The direction to iterate in. If passing the return value to
7716 `fwdRange`, use `Direction.fwd`. If passing it to
7717 `bwdRange`, use `Direction.bwd`.
7718 month = The month that each time point in the range will be in
7719 (January is 1).
7720 +/
7721 TP delegate(scope const TP) everyMonth(TP, Direction dir = Direction.fwd)(int month)
7722 if (isTimePoint!TP &&
7723 (dir == Direction.fwd || dir == Direction.bwd) &&
7724 __traits(hasMember, TP, "month") &&
7725 !__traits(isStaticFunction, TP.month) &&
7726 is(typeof(TP.month) == Month))
7727 {
7728 import std.datetime.date : enforceValid, monthsToMonth;
7729
7730 enforceValid!"months"(month);
7731
func(scope const TP tp)7732 TP func(scope const TP tp)
7733 {
7734 TP retval = cast(TP) tp;
7735 immutable months = monthsToMonth(retval.month, month);
7736
7737 static if (dir == Direction.fwd)
7738 immutable adjustedMonths = months == 0 ? 12 : months;
7739 else
7740 immutable adjustedMonths = months == 0 ? -12 : months - 12;
7741
7742 retval.add!"months"(adjustedMonths, AllowDayOverflow.no);
7743
7744 if (retval.month != month)
7745 {
7746 retval.add!"months"(-1);
7747 assert(retval.month == month);
7748 }
7749
7750 return retval;
7751 }
7752
7753 return &func;
7754 }
7755
7756 ///
7757 @system unittest
7758 {
7759 import std.datetime.date : Date, Month;
7760
7761 auto interval = Interval!Date(Date(2000, 1, 30), Date(2004, 8, 5));
7762 auto func = everyMonth!Date(Month.feb);
7763 auto range = interval.fwdRange(func);
7764
7765 // Using PopFirst.yes would have made this Date(2010, 2, 29).
7766 assert(range.front == Date(2000, 1, 30));
7767
7768 range.popFront();
7769 assert(range.front == Date(2000, 2, 29));
7770
7771 range.popFront();
7772 assert(range.front == Date(2001, 2, 28));
7773
7774 range.popFront();
7775 assert(range.front == Date(2002, 2, 28));
7776
7777 range.popFront();
7778 assert(range.front == Date(2003, 2, 28));
7779
7780 range.popFront();
7781 assert(range.front == Date(2004, 2, 28));
7782
7783 range.popFront();
7784 assert(range.empty);
7785 }
7786
7787 @system unittest
7788 {
7789 import std.datetime.date;
7790 import std.datetime.systime;
7791
7792 auto funcFwd = everyMonth!Date(Month.jun);
7793 auto funcBwd = everyMonth!(Date, Direction.bwd)(Month.jun);
7794
7795 assert(funcFwd(Date(2010, 5, 31)) == Date(2010, 6, 30));
7796 assert(funcFwd(Date(2010, 6, 30)) == Date(2011, 6, 30));
7797 assert(funcFwd(Date(2010, 7, 31)) == Date(2011, 6, 30));
7798 assert(funcFwd(Date(2010, 8, 31)) == Date(2011, 6, 30));
7799 assert(funcFwd(Date(2010, 9, 30)) == Date(2011, 6, 30));
7800 assert(funcFwd(Date(2010, 10, 31)) == Date(2011, 6, 30));
7801 assert(funcFwd(Date(2010, 11, 30)) == Date(2011, 6, 30));
7802 assert(funcFwd(Date(2010, 12, 31)) == Date(2011, 6, 30));
7803 assert(funcFwd(Date(2011, 1, 31)) == Date(2011, 6, 30));
7804 assert(funcFwd(Date(2011, 2, 28)) == Date(2011, 6, 28));
7805 assert(funcFwd(Date(2011, 3, 31)) == Date(2011, 6, 30));
7806 assert(funcFwd(Date(2011, 4, 30)) == Date(2011, 6, 30));
7807 assert(funcFwd(Date(2011, 5, 31)) == Date(2011, 6, 30));
7808 assert(funcFwd(Date(2011, 6, 30)) == Date(2012, 6, 30));
7809 assert(funcFwd(Date(2011, 7, 31)) == Date(2012, 6, 30));
7810
7811 assert(funcBwd(Date(2010, 5, 31)) == Date(2009, 6, 30));
7812 assert(funcBwd(Date(2010, 6, 30)) == Date(2009, 6, 30));
7813 assert(funcBwd(Date(2010, 7, 31)) == Date(2010, 6, 30));
7814 assert(funcBwd(Date(2010, 8, 31)) == Date(2010, 6, 30));
7815 assert(funcBwd(Date(2010, 9, 30)) == Date(2010, 6, 30));
7816 assert(funcBwd(Date(2010, 10, 31)) == Date(2010, 6, 30));
7817 assert(funcBwd(Date(2010, 11, 30)) == Date(2010, 6, 30));
7818 assert(funcBwd(Date(2010, 12, 31)) == Date(2010, 6, 30));
7819 assert(funcBwd(Date(2011, 1, 31)) == Date(2010, 6, 30));
7820 assert(funcBwd(Date(2011, 2, 28)) == Date(2010, 6, 28));
7821 assert(funcBwd(Date(2011, 3, 31)) == Date(2010, 6, 30));
7822 assert(funcBwd(Date(2011, 4, 30)) == Date(2010, 6, 30));
7823 assert(funcBwd(Date(2011, 5, 31)) == Date(2010, 6, 30));
7824 assert(funcBwd(Date(2011, 6, 30)) == Date(2010, 6, 30));
7825 assert(funcBwd(Date(2011, 7, 30)) == Date(2011, 6, 30));
7826
7827 static assert(!__traits(compiles, everyMonth!TimeOfDay(Month.jan)));
7828 assert(everyMonth!DateTime(Month.jan) !is null);
7829 assert(everyMonth!SysTime(Month.jan) !is null);
7830 }
7831
7832
7833 /++
7834 Range-generating function.
7835
7836 Returns a delegate which returns the next time point which is the given
7837 duration later.
7838
7839 Using this delegate allows iteration over successive time points which
7840 are apart by the given duration e.g. passing `dur!"days"(3)` to
7841 `everyDuration` would result in a delegate which could be used to iterate
7842 over a range of days which are each 3 days apart.
7843
7844 Params:
7845 dir = The direction to iterate in. If passing the return value to
7846 `fwdRange`, use `Direction.fwd`. If passing it to
7847 `bwdRange`, use `Direction.bwd`.
7848 duration = The duration which separates each successive time point in
7849 the range.
7850 +/
7851 TP delegate(return scope const TP) everyDuration(TP, Direction dir = Direction.fwd, D)(D duration) nothrow
7852 if (isTimePoint!TP &&
7853 __traits(compiles, TP.init + duration) &&
7854 (dir == Direction.fwd || dir == Direction.bwd))
7855 {
7856 TP func(return scope const TP tp)
7857 {
7858 static if (dir == Direction.fwd)
7859 return tp + duration;
7860 else
7861 return tp - duration;
7862 }
7863
7864 return &func;
7865 }
7866
7867 ///
7868 @system unittest
7869 {
7870 import core.time : dur;
7871 import std.datetime.date : Date;
7872
7873 auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
7874 auto func = everyDuration!Date(dur!"days"(8));
7875 auto range = interval.fwdRange(func);
7876
7877 // Using PopFirst.yes would have made this Date(2010, 9, 10).
7878 assert(range.front == Date(2010, 9, 2));
7879
7880 range.popFront();
7881 assert(range.front == Date(2010, 9, 10));
7882
7883 range.popFront();
7884 assert(range.front == Date(2010, 9, 18));
7885
7886 range.popFront();
7887 assert(range.front == Date(2010, 9, 26));
7888
7889 range.popFront();
7890 assert(range.empty);
7891 }
7892
7893 @system unittest
7894 {
7895 import std.datetime.date;
7896 import std.datetime.systime;
7897
7898 auto funcFwd = everyDuration!Date(dur!"days"(27));
7899 auto funcBwd = everyDuration!(Date, Direction.bwd)(dur!"days"(27));
7900
7901 assert(funcFwd(Date(2009, 12, 25)) == Date(2010, 1, 21));
7902 assert(funcFwd(Date(2009, 12, 26)) == Date(2010, 1, 22));
7903 assert(funcFwd(Date(2009, 12, 27)) == Date(2010, 1, 23));
7904 assert(funcFwd(Date(2009, 12, 28)) == Date(2010, 1, 24));
7905
7906 assert(funcBwd(Date(2010, 1, 21)) == Date(2009, 12, 25));
7907 assert(funcBwd(Date(2010, 1, 22)) == Date(2009, 12, 26));
7908 assert(funcBwd(Date(2010, 1, 23)) == Date(2009, 12, 27));
7909 assert(funcBwd(Date(2010, 1, 24)) == Date(2009, 12, 28));
7910
7911 assert(everyDuration!Date(dur!"hnsecs"(1)) !is null);
7912 assert(everyDuration!TimeOfDay(dur!"hnsecs"(1)) !is null);
7913 assert(everyDuration!DateTime(dur!"hnsecs"(1)) !is null);
7914 assert(everyDuration!SysTime(dur!"hnsecs"(1)) !is null);
7915 }
7916
7917
7918 /++
7919 Range-generating function.
7920
7921 Returns a delegate which returns the next time point which is the given
7922 number of years, month, and duration later.
7923
7924 The difference between this version of `everyDuration` and the version
7925 which just takes a $(REF Duration, core,time) is that this one also takes
7926 the number of years and months (along with an `AllowDayOverflow` to
7927 indicate whether adding years and months should allow the days to overflow).
7928
7929 Note that if iterating forward, `add!"years"()` is called on the given
7930 time point, then `add!"months"()`, and finally the duration is added
7931 to it. However, if iterating backwards, the duration is added first, then
7932 `add!"months"()` is called, and finally `add!"years"()` is called.
7933 That way, going backwards generates close to the same time points that
7934 iterating forward does, but since adding years and months is not entirely
7935 reversible (due to possible day overflow, regardless of whether
7936 `AllowDayOverflow.yes` or `AllowDayOverflow.no` is used), it can't be
7937 guaranteed that iterating backwards will give the same time points as
7938 iterating forward would have (even assuming that the end of the range is a
7939 time point which would be returned by the delegate when iterating forward
7940 from `begin`).
7941
7942 Params:
7943 dir = The direction to iterate in. If passing the return
7944 value to `fwdRange`, use `Direction.fwd`. If
7945 passing it to `bwdRange`, use `Direction.bwd`.
7946 years = The number of years to add to the time point passed to
7947 the delegate.
7948 months = The number of months to add to the time point passed to
7949 the delegate.
7950 allowOverflow = Whether the days should be allowed to overflow on
7951 `begin` and `end`, causing their month to
7952 increment.
7953 duration = The duration to add to the time point passed to the
7954 delegate.
7955 +/
7956 TP delegate(scope const TP) everyDuration(TP, Direction dir = Direction.fwd, D)
7957 (int years,
7958 int months = 0,
7959 AllowDayOverflow allowOverflow = AllowDayOverflow.yes,
7960 D duration = dur!"days"(0)) nothrow
7961 if (isTimePoint!TP &&
7962 __traits(compiles, TP.init + duration) &&
7963 __traits(compiles, TP.init.add!"years"(years)) &&
7964 __traits(compiles, TP.init.add!"months"(months)) &&
7965 (dir == Direction.fwd || dir == Direction.bwd))
7966 {
7967 TP func(scope const TP tp)
7968 {
7969 static if (dir == Direction.fwd)
7970 {
7971 TP retval = cast(TP) tp;
7972
7973 retval.add!"years"(years, allowOverflow);
7974 retval.add!"months"(months, allowOverflow);
7975
7976 return retval + duration;
7977 }
7978 else
7979 {
7980 TP retval = tp - duration;
7981
7982 retval.add!"months"(-months, allowOverflow);
7983 retval.add!"years"(-years, allowOverflow);
7984
7985 return retval;
7986 }
7987 }
7988
7989 return &func;
7990 }
7991
7992 ///
7993 @system unittest
7994 {
7995 import core.time : dur;
7996 import std.datetime.date : AllowDayOverflow, Date;
7997
7998 auto interval = Interval!Date(Date(2010, 9, 2), Date(2025, 9, 27));
7999 auto func = everyDuration!Date(4, 1, AllowDayOverflow.yes, dur!"days"(2));
8000 auto range = interval.fwdRange(func);
8001
8002 // Using PopFirst.yes would have made this Date(2014, 10, 12).
8003 assert(range.front == Date(2010, 9, 2));
8004
8005 range.popFront();
8006 assert(range.front == Date(2014, 10, 4));
8007
8008 range.popFront();
8009 assert(range.front == Date(2018, 11, 6));
8010
8011 range.popFront();
8012 assert(range.front == Date(2022, 12, 8));
8013
8014 range.popFront();
8015 assert(range.empty);
8016 }
8017
8018 @system unittest
8019 {
8020 import std.datetime.date;
8021 import std.datetime.systime;
8022
8023 {
8024 auto funcFwd = everyDuration!Date(1, 2, AllowDayOverflow.yes, dur!"days"(3));
8025 auto funcBwd = everyDuration!(Date, Direction.bwd)(1, 2, AllowDayOverflow.yes, dur!"days"(3));
8026
8027 assert(funcFwd(Date(2009, 12, 25)) == Date(2011, 2, 28));
8028 assert(funcFwd(Date(2009, 12, 26)) == Date(2011, 3, 1));
8029 assert(funcFwd(Date(2009, 12, 27)) == Date(2011, 3, 2));
8030 assert(funcFwd(Date(2009, 12, 28)) == Date(2011, 3, 3));
8031 assert(funcFwd(Date(2009, 12, 29)) == Date(2011, 3, 4));
8032
8033 assert(funcBwd(Date(2011, 2, 28)) == Date(2009, 12, 25));
8034 assert(funcBwd(Date(2011, 3, 1)) == Date(2009, 12, 26));
8035 assert(funcBwd(Date(2011, 3, 2)) == Date(2009, 12, 27));
8036 assert(funcBwd(Date(2011, 3, 3)) == Date(2009, 12, 28));
8037 assert(funcBwd(Date(2011, 3, 4)) == Date(2010, 1, 1));
8038 }
8039
8040 {
8041 auto funcFwd = everyDuration!Date(1, 2, AllowDayOverflow.no, dur!"days"(3));
8042 auto funcBwd = everyDuration!(Date, Direction.bwd)(1, 2, AllowDayOverflow.yes, dur!"days"(3));
8043
8044 assert(funcFwd(Date(2009, 12, 25)) == Date(2011, 2, 28));
8045 assert(funcFwd(Date(2009, 12, 26)) == Date(2011, 3, 1));
8046 assert(funcFwd(Date(2009, 12, 27)) == Date(2011, 3, 2));
8047 assert(funcFwd(Date(2009, 12, 28)) == Date(2011, 3, 3));
8048 assert(funcFwd(Date(2009, 12, 29)) == Date(2011, 3, 3));
8049
8050 assert(funcBwd(Date(2011, 2, 28)) == Date(2009, 12, 25));
8051 assert(funcBwd(Date(2011, 3, 1)) == Date(2009, 12, 26));
8052 assert(funcBwd(Date(2011, 3, 2)) == Date(2009, 12, 27));
8053 assert(funcBwd(Date(2011, 3, 3)) == Date(2009, 12, 28));
8054 assert(funcBwd(Date(2011, 3, 4)) == Date(2010, 1, 1));
8055 }
8056
8057 assert(everyDuration!Date(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1)) !is null);
8058 static assert(!__traits(compiles, everyDuration!TimeOfDay(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
8059 assert(everyDuration!DateTime(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1)) !is null);
8060 assert(everyDuration!SysTime(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1)) !is null);
8061 }
8062
8063
8064 /++
8065 A range over an $(LREF Interval).
8066
8067 `IntervalRange` is only ever constructed by $(LREF Interval). However, when
8068 it is constructed, it is given a function, `func`, which is used to
8069 generate the time points which are iterated over. `func` takes a time
8070 point and returns a time point of the same type. For instance,
8071 to iterate over all of the days in
8072 the interval `Interval!Date`, pass a function to $(LREF Interval)'s
8073 `fwdRange` where that function took a $(REF Date,std,datetime,date) and
8074 returned a $(REF Date,std,datetime,date) which was one day later. That
8075 function would then be used by `IntervalRange`'s `popFront` to iterate
8076 over the $(REF Date,std,datetime,date)s in the interval.
8077
8078 If $(D dir == Direction.fwd), then a range iterates forward in time, whereas
8079 if $(D dir == Direction.bwd), then it iterates backwards in time. So, if
8080 $(D dir == Direction.fwd) then $(D front == interval.begin), whereas if
8081 $(D dir == Direction.bwd) then $(D front == interval.end). `func` must
8082 generate a time point going in the proper direction of iteration, or a
8083 $(REF DateTimeException,std,datetime,date) will be thrown. So, to iterate
8084 forward in time, the time point that `func` generates must be later in
8085 time than the one passed to it. If it's either identical or earlier in time,
8086 then a $(REF DateTimeException,std,datetime,date) will be thrown. To
8087 iterate backwards, then the generated time point must be before the time
8088 point which was passed in.
8089
8090 If the generated time point is ever passed the edge of the range in the
8091 proper direction, then the edge of that range will be used instead. So, if
8092 iterating forward, and the generated time point is past the interval's
8093 `end`, then `front` becomes `end`. If iterating backwards, and the
8094 generated time point is before `begin`, then `front` becomes
8095 `begin`. In either case, the range would then be empty.
8096
8097 Also note that while normally the `begin` of an interval is included in
8098 it and its `end` is excluded from it, if $(D dir == Direction.bwd), then
8099 `begin` is treated as excluded and `end` is treated as included. This
8100 allows for the same behavior in both directions. This works because none of
8101 $(LREF Interval)'s functions which care about whether `begin` or `end`
8102 is included or excluded are ever called by `IntervalRange`. `interval`
8103 returns a normal interval, regardless of whether $(D dir == Direction.fwd)
8104 or if $(D dir == Direction.bwd), so any $(LREF Interval) functions which are
8105 called on it which care about whether `begin` or `end` are included or
8106 excluded will treat `begin` as included and `end` as excluded.
8107 +/
8108 struct IntervalRange(TP, Direction dir)
8109 if (isTimePoint!TP && dir != Direction.both)
8110 {
8111 public:
8112
8113 /++
8114 Params:
8115 rhs = The `IntervalRange` to assign to this one.
8116 +/
opAssign(ref IntervalRange rhs)8117 ref IntervalRange opAssign(ref IntervalRange rhs) pure nothrow
8118 {
8119 _interval = rhs._interval;
8120 _func = rhs._func;
8121 return this;
8122 }
8123
8124
8125 /++ Ditto +/
8126 ref IntervalRange opAssign(IntervalRange rhs) pure nothrow
8127 {
8128 return this = rhs;
8129 }
8130
8131
8132 /++
8133 Whether this `IntervalRange` is empty.
8134 +/
8135 @property bool empty() const pure nothrow
8136 {
8137 return _interval.empty;
8138 }
8139
8140
8141 /++
8142 The first time point in the range.
8143
8144 Throws:
8145 $(REF DateTimeException,std,datetime,date) if the range is empty.
8146 +/
8147 @property TP front() const pure
8148 {
8149 _enforceNotEmpty();
8150
8151 static if (dir == Direction.fwd)
8152 return _interval.begin;
8153 else
8154 return _interval.end;
8155 }
8156
8157
8158 /++
8159 Pops `front` from the range, using `func` to generate the next
8160 time point in the range. If the generated time point is beyond the edge
8161 of the range, then `front` is set to that edge, and the range is then
8162 empty. So, if iterating forwards, and the generated time point is
8163 greater than the interval's `end`, then `front` is set to
8164 `end`. If iterating backwards, and the generated time point is less
8165 than the interval's `begin`, then `front` is set to `begin`.
8166
8167 Throws:
8168 $(REF DateTimeException,std,datetime,date) if the range is empty
8169 or if the generated time point is in the wrong direction (i.e. if
8170 iterating forward and the generated time point is before `front`,
8171 or if iterating backwards and the generated time point is after
8172 `front`).
8173 +/
8174 void popFront()
8175 {
8176 _enforceNotEmpty();
8177
8178 static if (dir == Direction.fwd)
8179 {
8180 auto begin = _func(_interval.begin);
8181
8182 if (begin > _interval.end)
8183 begin = _interval.end;
8184
8185 _enforceCorrectDirection(begin);
8186
8187 _interval.begin = begin;
8188 }
8189 else
8190 {
8191 auto end = _func(_interval.end);
8192
8193 if (end < _interval.begin)
8194 end = _interval.begin;
8195
8196 _enforceCorrectDirection(end);
8197
8198 _interval.end = end;
8199 }
8200 }
8201
8202
8203 /++
8204 Returns a copy of `this`.
8205 +/
8206 @property IntervalRange save() pure nothrow
8207 {
8208 return this;
8209 }
8210
8211
8212 /++
8213 The interval that this `IntervalRange` currently covers.
8214 +/
8215 @property Interval!TP interval() const pure nothrow
8216 {
8217 return cast(Interval!TP)_interval;
8218 }
8219
8220
8221 /++
8222 The function used to generate the next time point in the range.
8223 +/
8224 TP delegate(scope const TP) func() pure nothrow @property
8225 {
8226 return _func;
8227 }
8228
8229
8230 /++
8231 The `Direction` that this range iterates in.
8232 +/
8233 @property Direction direction() const pure nothrow
8234 {
8235 return dir;
8236 }
8237
8238
8239 private:
8240
8241 /+
8242 Params:
8243 interval = The interval that this range covers.
8244 func = The function used to generate the time points which are
8245 iterated over.
8246 +/
8247 this(const Interval!TP interval, TP delegate(scope const TP) func) pure nothrow @safe
8248 {
8249 _func = func;
8250 _interval = interval;
8251 }
8252
8253
8254 /+
8255 Throws:
8256 $(REF DateTimeException,std,datetime,date) if this interval is
8257 empty.
8258 +/
8259 void _enforceNotEmpty(size_t line = __LINE__) const pure
8260 {
8261 if (empty)
8262 throw new DateTimeException("Invalid operation for an empty IntervalRange.", __FILE__, line);
8263 }
8264
8265
8266 /+
8267 Throws:
8268 $(REF DateTimeException,std,datetime,date) if $(D_PARAM newTP) is
8269 in the wrong direction.
8270 +/
8271 void _enforceCorrectDirection(scope const TP newTP, size_t line = __LINE__) const
8272 {
8273 import std.format : format;
8274
8275 static if (dir == Direction.fwd)
8276 {
8277 enforce(newTP > _interval._begin,
8278 new DateTimeException(format("Generated time point is before previous begin: prev [%s] new [%s]",
8279 interval._begin,
8280 newTP),
8281 __FILE__,
8282 line));
8283 }
8284 else
8285 {
8286 enforce(newTP < _interval._end,
8287 new DateTimeException(format("Generated time point is after previous end: prev [%s] new [%s]",
8288 interval._end,
8289 newTP),
8290 __FILE__,
8291 line));
8292 }
8293 }
8294
8295
8296 Interval!TP _interval;
8297 TP delegate(scope const TP) _func;
8298 }
8299
8300 //Test that IntervalRange satisfies the range predicates that it's supposed to satisfy.
8301 @safe unittest
8302 {
8303 import std.datetime.date;
8304 import std.datetime.systime;
8305 import std.range.primitives;
8306
8307 static assert(isInputRange!(IntervalRange!(Date, Direction.fwd)));
8308 static assert(isForwardRange!(IntervalRange!(Date, Direction.fwd)));
8309
8310 // Commented out due to bug https://issues.dlang.org/show_bug.cgi?id=4895
8311 // static assert(!isOutputRange!(IntervalRange!(Date, Direction.fwd), Date));
8312
8313 static assert(!isBidirectionalRange!(IntervalRange!(Date, Direction.fwd)));
8314 static assert(!isRandomAccessRange!(IntervalRange!(Date, Direction.fwd)));
8315 static assert(!hasSwappableElements!(IntervalRange!(Date, Direction.fwd)));
8316 static assert(!hasAssignableElements!(IntervalRange!(Date, Direction.fwd)));
8317 static assert(!hasLength!(IntervalRange!(Date, Direction.fwd)));
8318 static assert(!isInfinite!(IntervalRange!(Date, Direction.fwd)));
8319 static assert(!hasSlicing!(IntervalRange!(Date, Direction.fwd)));
8320
8321 static assert(is(ElementType!(IntervalRange!(Date, Direction.fwd)) == Date));
8322 static assert(is(ElementType!(IntervalRange!(TimeOfDay, Direction.fwd)) == TimeOfDay));
8323 static assert(is(ElementType!(IntervalRange!(DateTime, Direction.fwd)) == DateTime));
8324 static assert(is(ElementType!(IntervalRange!(SysTime, Direction.fwd)) == SysTime));
8325 }
8326
8327 //Test construction of IntervalRange.
8328 @safe unittest
8329 {
8330 import std.datetime.date;
8331 import std.datetime.systime;
8332
8333 {
dateFunc(scope const Date date)8334 Date dateFunc(scope const Date date) { return date; }
8335 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8336 auto ir = IntervalRange!(Date, Direction.fwd)(interval, &dateFunc);
8337 }
8338
8339 {
todFunc(scope const TimeOfDay tod)8340 TimeOfDay todFunc(scope const TimeOfDay tod) { return tod; }
8341 auto interval = Interval!TimeOfDay(TimeOfDay(12, 1, 7), TimeOfDay(14, 0, 0));
8342 auto ir = IntervalRange!(TimeOfDay, Direction.fwd)(interval, &todFunc);
8343 }
8344
8345 {
dtFunc(scope const DateTime dt)8346 DateTime dtFunc(scope const DateTime dt) { return dt; }
8347 auto interval = Interval!DateTime(DateTime(2010, 7, 4, 12, 1, 7), DateTime(2012, 1, 7, 14, 0, 0));
8348 auto ir = IntervalRange!(DateTime, Direction.fwd)(interval, &dtFunc);
8349 }
8350
8351 {
stFunc(scope const SysTime st)8352 SysTime stFunc(scope const SysTime st) { return SysTime.init; }
8353 auto interval = Interval!SysTime(SysTime(DateTime(2010, 7, 4, 12, 1, 7)),
8354 SysTime(DateTime(2012, 1, 7, 14, 0, 0)));
8355 auto ir = IntervalRange!(SysTime, Direction.fwd)(interval, &stFunc);
8356 }
8357 }
8358
8359 //Test IntervalRange's empty().
8360 @system unittest
8361 {
8362 import std.datetime.date;
8363
8364 //fwd
8365 {
8366 auto range = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8367
8368 assert(!range.empty);
8369 range.popFront();
8370 assert(range.empty);
8371
8372 const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8373 assert(!cRange.empty);
8374
8375 //Apparently, creating an immutable IntervalRange!Date doesn't work, so we can't test if
8376 //empty works with it. However, since an immutable range is pretty useless, it's no great loss.
8377 }
8378
8379 //bwd
8380 {
8381 auto range = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21)).bwdRange(
8382 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
8383
8384 assert(!range.empty);
8385 range.popFront();
8386 assert(range.empty);
8387
8388 const cRange = Interval!Date( Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8389 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
8390 assert(!cRange.empty);
8391
8392 //Apparently, creating an immutable IntervalRange!Date doesn't work, so we can't test if
8393 //empty works with it. However, since an immutable range is pretty useless, it's no great loss.
8394 }
8395 }
8396
8397 //Test IntervalRange's front.
8398 @system unittest
8399 {
8400 import std.datetime.date;
8401
8402 //fwd
8403 {
8404 auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).fwdRange(
8405 everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8406 assertThrown!DateTimeException(
8407 (scope const IntervalRange!(Date, Direction.fwd) range){range.front;}(emptyRange));
8408
8409 auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed));
8410 assert(range.front == Date(2010, 7, 4));
8411
8412 auto poppedRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(
8413 everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8414 assert(poppedRange.front == Date(2010, 7, 7));
8415
8416 const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8417 assert(cRange.front != Date.init);
8418 }
8419
8420 //bwd
8421 {
8422 auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).bwdRange(
8423 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
8424 assertThrown!DateTimeException(
8425 (scope const IntervalRange!(Date, Direction.bwd) range){range.front;}(emptyRange));
8426
8427 auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8428 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed));
8429 assert(range.front == Date(2012, 1, 7));
8430
8431 auto poppedRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8432 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
8433 assert(poppedRange.front == Date(2012, 1, 4));
8434
8435 const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8436 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
8437 assert(cRange.front != Date.init);
8438 }
8439 }
8440
8441 //Test IntervalRange's popFront().
8442 @system unittest
8443 {
8444 import std.datetime.date;
8445 import std.range.primitives : walkLength;
8446
8447 //fwd
8448 {
8449 auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).fwdRange(
8450 everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8451 assertThrown!DateTimeException((IntervalRange!(Date, Direction.fwd) range){range.popFront();}(emptyRange));
8452
8453 auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(
8454 everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8455 auto expected = range.front;
8456
foreach(date;range)8457 foreach (date; range)
8458 {
8459 assert(date == expected);
8460 expected += dur!"days"(7);
8461 }
8462
8463 assert(walkLength(range) == 79);
8464
8465 const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8466 assert(cRange.front != Date.init);
8467 }
8468
8469 //bwd
8470 {
8471 auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).bwdRange(
8472 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
8473 assertThrown!DateTimeException((IntervalRange!(Date, Direction.bwd) range){range.popFront();}(emptyRange));
8474
8475 auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8476 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
8477 auto expected = range.front;
8478
foreach(date;range)8479 foreach (date; range)
8480 {
8481 assert(date == expected);
8482 expected += dur!"days"(-7);
8483 }
8484
8485 assert(walkLength(range) == 79);
8486
8487 const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8488 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
8489 static assert(!__traits(compiles, cRange.popFront()));
8490 }
8491 }
8492
8493 //Test IntervalRange's save.
8494 @system unittest
8495 {
8496 import std.datetime.date;
8497
8498 //fwd
8499 {
8500 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8501 auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8502 auto range = interval.fwdRange(func);
8503
8504 assert(range.save == range);
8505 }
8506
8507 //bwd
8508 {
8509 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8510 auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
8511 auto range = interval.bwdRange(func);
8512
8513 assert(range.save == range);
8514 }
8515 }
8516
8517 //Test IntervalRange's interval.
8518 @system unittest
8519 {
8520 import std.datetime.date;
8521
8522 //fwd
8523 {
8524 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8525 auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8526 auto range = interval.fwdRange(func);
8527
8528 assert(range.interval == interval);
8529
8530 const cRange = range;
8531 assert(!cRange.interval.empty);
8532 }
8533
8534 //bwd
8535 {
8536 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8537 auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
8538 auto range = interval.bwdRange(func);
8539
8540 assert(range.interval == interval);
8541
8542 const cRange = range;
8543 assert(!cRange.interval.empty);
8544 }
8545 }
8546
8547 //Test IntervalRange's func.
8548 @system unittest
8549 {
8550 import std.datetime.date;
8551
8552 //fwd
8553 {
8554 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8555 auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8556 auto range = interval.fwdRange(func);
8557
8558 assert(range.func == func);
8559 }
8560
8561 //bwd
8562 {
8563 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8564 auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
8565 auto range = interval.bwdRange(func);
8566
8567 assert(range.func == func);
8568 }
8569 }
8570
8571 //Test IntervalRange's direction.
8572 @system unittest
8573 {
8574 import std.datetime.date;
8575
8576 //fwd
8577 {
8578 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8579 auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8580 auto range = interval.fwdRange(func);
8581
8582 assert(range.direction == Direction.fwd);
8583
8584 const cRange = range;
8585 assert(cRange.direction == Direction.fwd);
8586 }
8587
8588 //bwd
8589 {
8590 auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8591 auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
8592 auto range = interval.bwdRange(func);
8593
8594 assert(range.direction == Direction.bwd);
8595
8596 const cRange = range;
8597 assert(cRange.direction == Direction.bwd);
8598 }
8599 }
8600
8601
8602 /++
8603 A range over a `PosInfInterval`. It is an infinite range.
8604
8605 `PosInfIntervalRange` is only ever constructed by `PosInfInterval`.
8606 However, when it is constructed, it is given a function, `func`, which
8607 is used to generate the time points which are iterated over. `func`
8608 takes a time point and returns a time point of the same type. For
8609 instance, to iterate
8610 over all of the days in the interval `PosInfInterval!Date`, pass a
8611 function to `PosInfInterval`'s `fwdRange` where that function took a
8612 $(REF Date,std,datetime,date) and returned a $(REF Date,std,datetime,date)
8613 which was one day later. That function would then be used by
8614 `PosInfIntervalRange`'s `popFront` to iterate over the
8615 $(REF Date,std,datetime,date)s in the interval - though obviously, since the
8616 range is infinite, use a function such as `std.range.take` with it rather
8617 than iterating over $(I all) of the dates.
8618
8619 As the interval goes to positive infinity, the range is always iterated over
8620 forwards, never backwards. `func` must generate a time point going in
8621 the proper direction of iteration, or a
8622 $(REF DateTimeException,std,datetime,date) will be thrown. So, the time
8623 points that `func` generates must be later in time than the one passed to
8624 it. If it's either identical or earlier in time, then a
8625 $(REF DateTimeException,std,datetime,date) will be thrown.
8626 +/
8627 struct PosInfIntervalRange(TP)
8628 if (isTimePoint!TP)
8629 {
8630 public:
8631
8632 /++
8633 Params:
8634 rhs = The `PosInfIntervalRange` to assign to this one.
8635 +/
opAssign(ref PosInfIntervalRange rhs)8636 ref PosInfIntervalRange opAssign(ref PosInfIntervalRange rhs) pure nothrow
8637 {
8638 _interval = rhs._interval;
8639 _func = rhs._func;
8640 return this;
8641 }
8642
8643
8644 /++ Ditto +/
8645 ref PosInfIntervalRange opAssign(PosInfIntervalRange rhs) pure nothrow
8646 {
8647 return this = rhs;
8648 }
8649
8650
8651 /++
8652 This is an infinite range, so it is never empty.
8653 +/
8654 enum bool empty = false;
8655
8656
8657 /++
8658 The first time point in the range.
8659 +/
8660 @property TP front() const pure nothrow
8661 {
8662 return _interval.begin;
8663 }
8664
8665
8666 /++
8667 Pops `front` from the range, using `func` to generate the next
8668 time point in the range.
8669
8670 Throws:
8671 $(REF DateTimeException,std,datetime,date) if the generated time
8672 point is less than `front`.
8673 +/
8674 void popFront()
8675 {
8676 auto begin = _func(_interval.begin);
8677 _enforceCorrectDirection(begin);
8678 _interval.begin = begin;
8679 }
8680
8681
8682 /++
8683 Returns a copy of `this`.
8684 +/
8685 @property PosInfIntervalRange save() pure nothrow
8686 {
8687 return this;
8688 }
8689
8690
8691 /++
8692 The interval that this range currently covers.
8693 +/
8694 @property PosInfInterval!TP interval() const pure nothrow
8695 {
8696 return cast(PosInfInterval!TP)_interval;
8697 }
8698
8699
8700 /++
8701 The function used to generate the next time point in the range.
8702 +/
8703 TP delegate(scope const TP) func() pure nothrow @property
8704 {
8705 return _func;
8706 }
8707
8708
8709 private:
8710
8711 /+
8712 Params:
8713 interval = The interval that this range covers.
8714 func = The function used to generate the time points which are
8715 iterated over.
8716 +/
8717 this(const PosInfInterval!TP interval, TP delegate(scope const TP) func) pure nothrow
8718 {
8719 _func = func;
8720 _interval = interval;
8721 }
8722
8723
8724 /+
8725 Throws:
8726 $(REF DateTimeException,std,datetime,date) if $(D_PARAM newTP) is
8727 in the wrong direction.
8728 +/
8729 void _enforceCorrectDirection(scope const TP newTP, size_t line = __LINE__) const
8730 {
8731 import std.format : format;
8732
8733 enforce(newTP > _interval._begin,
8734 new DateTimeException(format("Generated time point is before previous begin: prev [%s] new [%s]",
8735 interval._begin,
8736 newTP),
8737 __FILE__,
8738 line));
8739 }
8740
8741
8742 PosInfInterval!TP _interval;
8743 TP delegate(scope const TP) _func;
8744 }
8745
8746 //Test that PosInfIntervalRange satisfies the range predicates that it's supposed to satisfy.
8747 @safe unittest
8748 {
8749 import std.datetime.date;
8750 import std.datetime.systime;
8751 import std.range.primitives;
8752
8753 static assert(isInputRange!(PosInfIntervalRange!Date));
8754 static assert(isForwardRange!(PosInfIntervalRange!Date));
8755 static assert(isInfinite!(PosInfIntervalRange!Date));
8756
8757 // Commented out due to bug https://issues.dlang.org/show_bug.cgi?id=4895
8758 // static assert(!isOutputRange!(PosInfIntervalRange!Date, Date));
8759 static assert(!isBidirectionalRange!(PosInfIntervalRange!Date));
8760 static assert(!isRandomAccessRange!(PosInfIntervalRange!Date));
8761 static assert(!hasSwappableElements!(PosInfIntervalRange!Date));
8762 static assert(!hasAssignableElements!(PosInfIntervalRange!Date));
8763 static assert(!hasLength!(PosInfIntervalRange!Date));
8764 static assert(!hasSlicing!(PosInfIntervalRange!Date));
8765
8766 static assert(is(ElementType!(PosInfIntervalRange!Date) == Date));
8767 static assert(is(ElementType!(PosInfIntervalRange!TimeOfDay) == TimeOfDay));
8768 static assert(is(ElementType!(PosInfIntervalRange!DateTime) == DateTime));
8769 static assert(is(ElementType!(PosInfIntervalRange!SysTime) == SysTime));
8770 }
8771
8772 //Test construction of PosInfIntervalRange.
8773 @safe unittest
8774 {
8775 import std.datetime.date;
8776 import std.datetime.systime;
8777
8778 {
dateFunc(scope const Date date)8779 Date dateFunc(scope const Date date) { return date; }
8780 auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
8781 auto ir = PosInfIntervalRange!Date(posInfInterval, &dateFunc);
8782 }
8783
8784 {
todFunc(scope const TimeOfDay tod)8785 TimeOfDay todFunc(scope const TimeOfDay tod) { return tod; }
8786 auto posInfInterval = PosInfInterval!TimeOfDay(TimeOfDay(12, 1, 7));
8787 auto ir = PosInfIntervalRange!(TimeOfDay)(posInfInterval, &todFunc);
8788 }
8789
8790 {
dtFunc(scope const DateTime dt)8791 DateTime dtFunc(scope const DateTime dt) { return dt; }
8792 auto posInfInterval = PosInfInterval!DateTime(DateTime(2010, 7, 4, 12, 1, 7));
8793 auto ir = PosInfIntervalRange!(DateTime)(posInfInterval, &dtFunc);
8794 }
8795
8796 {
stFunc(scope const SysTime st)8797 SysTime stFunc(scope const SysTime st) { return SysTime.init; }
8798 auto posInfInterval = PosInfInterval!SysTime(SysTime(DateTime(2010, 7, 4, 12, 1, 7)));
8799 auto ir = PosInfIntervalRange!SysTime(posInfInterval, &stFunc);
8800 }
8801 }
8802
8803 //Test PosInfIntervalRange's front.
8804 @system unittest
8805 {
8806 import std.datetime.date;
8807
8808 auto range = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed));
8809 assert(range.front == Date(2010, 7, 4));
8810
8811 auto poppedRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8812 assert(poppedRange.front == Date(2010, 7, 7));
8813
8814 const cRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8815 assert(cRange.front != Date.init);
8816 }
8817
8818 //Test PosInfIntervalRange's popFront().
8819 @system unittest
8820 {
8821 import std.datetime.date;
8822 import std.range : take;
8823
8824 auto range = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8825 auto expected = range.front;
8826
8827 foreach (date; take(range, 79))
8828 {
8829 assert(date == expected);
8830 expected += dur!"days"(7);
8831 }
8832
8833 const cRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8834 static assert(!__traits(compiles, cRange.popFront()));
8835 }
8836
8837 //Test PosInfIntervalRange's save.
8838 @system unittest
8839 {
8840 import std.datetime.date;
8841
8842 auto interval = PosInfInterval!Date(Date(2010, 7, 4));
8843 auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8844 auto range = interval.fwdRange(func);
8845
8846 assert(range.save == range);
8847 }
8848
8849 //Test PosInfIntervalRange's interval.
8850 @system unittest
8851 {
8852 import std.datetime.date;
8853
8854 auto interval = PosInfInterval!Date(Date(2010, 7, 4));
8855 auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8856 auto range = interval.fwdRange(func);
8857
8858 assert(range.interval == interval);
8859
8860 const cRange = range;
8861 assert(!cRange.interval.empty);
8862 }
8863
8864 //Test PosInfIntervalRange's func.
8865 @system unittest
8866 {
8867 import std.datetime.date;
8868
8869 auto interval = PosInfInterval!Date(Date(2010, 7, 4));
8870 auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8871 auto range = interval.fwdRange(func);
8872
8873 assert(range.func == func);
8874 }
8875
8876
8877 /++
8878 A range over a `NegInfInterval`. It is an infinite range.
8879
8880 `NegInfIntervalRange` is only ever constructed by `NegInfInterval`.
8881 However, when it is constructed, it is given a function, `func`, which
8882 is used to generate the time points which are iterated over. `func`
8883 takes a time point and returns a time point of the same type. For
8884 instance, to iterate over all of the days in the interval
8885 `NegInfInterval!Date`, pass a function to `NegInfInterval`'s
8886 `bwdRange` where that function took a $(REF Date,std,datetime,date) and
8887 returned a $(REF Date,std,datetime,date) which was one day earlier. That
8888 function would then be used by `NegInfIntervalRange`'s `popFront` to
8889 iterate over the $(REF Date,std,datetime,date)s in the interval - though
8890 obviously, since the range is infinite, use a function such as
8891 `std.range.take` with it rather than iterating over $(I all) of the dates.
8892
8893 As the interval goes to negative infinity, the range is always iterated over
8894 backwards, never forwards. `func` must generate a time point going in
8895 the proper direction of iteration, or a
8896 $(REF DateTimeException,std,datetime,date) will be thrown. So, the time
8897 points that `func` generates must be earlier in time than the one passed
8898 to it. If it's either identical or later in time, then a
8899 $(REF DateTimeException,std,datetime,date) will be thrown.
8900
8901 Also note that while normally the `end` of an interval is excluded from
8902 it, `NegInfIntervalRange` treats it as if it were included. This allows
8903 for the same behavior as with `PosInfIntervalRange`. This works
8904 because none of `NegInfInterval`'s functions which care about whether
8905 `end` is included or excluded are ever called by
8906 `NegInfIntervalRange`. `interval` returns a normal interval, so any
8907 `NegInfInterval` functions which are called on it which care about
8908 whether `end` is included or excluded will treat `end` as excluded.
8909 +/
8910 struct NegInfIntervalRange(TP)
8911 if (isTimePoint!TP)
8912 {
8913 public:
8914
8915 /++
8916 Params:
8917 rhs = The `NegInfIntervalRange` to assign to this one.
8918 +/
opAssign(ref NegInfIntervalRange rhs)8919 ref NegInfIntervalRange opAssign(ref NegInfIntervalRange rhs) pure nothrow
8920 {
8921 _interval = rhs._interval;
8922 _func = rhs._func;
8923
8924 return this;
8925 }
8926
8927
8928 /++ Ditto +/
opAssign(NegInfIntervalRange rhs)8929 ref NegInfIntervalRange opAssign(NegInfIntervalRange rhs) pure nothrow
8930 {
8931 return this = rhs;
8932 }
8933
8934
8935 /++
8936 This is an infinite range, so it is never empty.
8937 +/
8938 enum bool empty = false;
8939
8940
8941 /++
8942 The first time point in the range.
8943 +/
front()8944 @property TP front() const pure nothrow
8945 {
8946 return _interval.end;
8947 }
8948
8949
8950 /++
8951 Pops `front` from the range, using `func` to generate the next
8952 time point in the range.
8953
8954 Throws:
8955 $(REF DateTimeException,std,datetime,date) if the generated time
8956 point is greater than `front`.
8957 +/
popFront()8958 void popFront()
8959 {
8960 auto end = _func(_interval.end);
8961 _enforceCorrectDirection(end);
8962 _interval.end = end;
8963 }
8964
8965
8966 /++
8967 Returns a copy of `this`.
8968 +/
save()8969 @property NegInfIntervalRange save() pure nothrow
8970 {
8971 return this;
8972 }
8973
8974
8975 /++
8976 The interval that this range currently covers.
8977 +/
8978 @property NegInfInterval!TP interval() const pure nothrow
8979 {
8980 return cast(NegInfInterval!TP)_interval;
8981 }
8982
8983
8984 /++
8985 The function used to generate the next time point in the range.
8986 +/
delegate(scope const TP)8987 TP delegate(scope const TP) func() pure nothrow @property
8988 {
8989 return _func;
8990 }
8991
8992
8993 private:
8994
8995 /+
8996 Params:
8997 interval = The interval that this range covers.
8998 func = The function used to generate the time points which are
8999 iterated over.
9000 +/
9001 this(const NegInfInterval!TP interval, TP delegate(scope const TP) func) pure nothrow
9002 {
9003 _func = func;
9004 _interval = interval;
9005 }
9006
9007
9008 /+
9009 Throws:
9010 $(REF DateTimeException,std,datetime,date) if $(D_PARAM newTP) is
9011 in the wrong direction.
9012 +/
9013 void _enforceCorrectDirection(scope const TP newTP, size_t line = __LINE__) const
9014 {
9015 import std.format : format;
9016
9017 enforce(newTP < _interval._end,
9018 new DateTimeException(format("Generated time point is before previous end: prev [%s] new [%s]",
9019 interval._end,
9020 newTP),
9021 __FILE__,
9022 line));
9023 }
9024
9025
9026 NegInfInterval!TP _interval;
9027 TP delegate(scope const TP) _func;
9028 }
9029
9030 //Test that NegInfIntervalRange satisfies the range predicates that it's supposed to satisfy.
9031 @safe unittest
9032 {
9033 import std.datetime.date;
9034 import std.range.primitives;
9035
9036 static assert(isInputRange!(NegInfIntervalRange!Date));
9037 static assert(isForwardRange!(NegInfIntervalRange!Date));
9038 static assert(isInfinite!(NegInfIntervalRange!Date));
9039
9040 // Commented out due to bug https://issues.dlang.org/show_bug.cgi?id=4895
9041 // static assert(!isOutputRange!(NegInfIntervalRange!Date, Date));
9042 static assert(!isBidirectionalRange!(NegInfIntervalRange!Date));
9043 static assert(!isRandomAccessRange!(NegInfIntervalRange!Date));
9044 static assert(!hasSwappableElements!(NegInfIntervalRange!Date));
9045 static assert(!hasAssignableElements!(NegInfIntervalRange!Date));
9046 static assert(!hasLength!(NegInfIntervalRange!Date));
9047 static assert(!hasSlicing!(NegInfIntervalRange!Date));
9048
9049 static assert(is(ElementType!(NegInfIntervalRange!Date) == Date));
9050 static assert(is(ElementType!(NegInfIntervalRange!TimeOfDay) == TimeOfDay));
9051 static assert(is(ElementType!(NegInfIntervalRange!DateTime) == DateTime));
9052 }
9053
9054 //Test construction of NegInfIntervalRange.
9055 @safe unittest
9056 {
9057 import std.datetime.date;
9058 import std.datetime.systime;
9059
9060 {
dateFunc(scope const Date date)9061 Date dateFunc(scope const Date date) { return date; }
9062 auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
9063 auto ir = NegInfIntervalRange!Date(negInfInterval, &dateFunc);
9064 }
9065
9066 {
todFunc(scope const TimeOfDay tod)9067 TimeOfDay todFunc(scope const TimeOfDay tod) { return tod; }
9068 auto negInfInterval = NegInfInterval!TimeOfDay(TimeOfDay(14, 0, 0));
9069 auto ir = NegInfIntervalRange!(TimeOfDay)(negInfInterval, &todFunc);
9070 }
9071
9072 {
dtFunc(scope const DateTime dt)9073 DateTime dtFunc(scope const DateTime dt) { return dt; }
9074 auto negInfInterval = NegInfInterval!DateTime(DateTime(2012, 1, 7, 14, 0, 0));
9075 auto ir = NegInfIntervalRange!(DateTime)(negInfInterval, &dtFunc);
9076 }
9077
9078 {
stFunc(scope const SysTime st)9079 SysTime stFunc(scope const SysTime st) { return SysTime.init; }
9080 auto negInfInterval = NegInfInterval!SysTime(SysTime(DateTime(2012, 1, 7, 14, 0, 0)));
9081 auto ir = NegInfIntervalRange!(SysTime)(negInfInterval, &stFunc);
9082 }
9083 }
9084
9085 //Test NegInfIntervalRange's front.
9086 @system unittest
9087 {
9088 import std.datetime.date;
9089
9090 auto range = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed));
9091 assert(range.front == Date(2012, 1, 7));
9092
9093 auto poppedRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(
9094 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
9095 assert(poppedRange.front == Date(2012, 1, 4));
9096
9097 const cRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
9098 assert(cRange.front != Date.init);
9099 }
9100
9101 //Test NegInfIntervalRange's popFront().
9102 @system unittest
9103 {
9104 import std.datetime.date;
9105 import std.range : take;
9106
9107 auto range = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(
9108 everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
9109 auto expected = range.front;
9110
9111 foreach (date; take(range, 79))
9112 {
9113 assert(date == expected);
9114 expected += dur!"days"(-7);
9115 }
9116
9117 const cRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
9118 static assert(!__traits(compiles, cRange.popFront()));
9119 }
9120
9121 //Test NegInfIntervalRange's save.
9122 @system unittest
9123 {
9124 import std.datetime.date;
9125
9126 auto interval = NegInfInterval!Date(Date(2012, 1, 7));
9127 auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
9128 auto range = interval.bwdRange(func);
9129
9130 assert(range.save == range);
9131 }
9132
9133 //Test NegInfIntervalRange's interval.
9134 @system unittest
9135 {
9136 import std.datetime.date;
9137
9138 auto interval = NegInfInterval!Date(Date(2012, 1, 7));
9139 auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
9140 auto range = interval.bwdRange(func);
9141
9142 assert(range.interval == interval);
9143
9144 const cRange = range;
9145 assert(!cRange.interval.empty);
9146 }
9147
9148 //Test NegInfIntervalRange's func.
9149 @system unittest
9150 {
9151 import std.datetime.date;
9152
9153 auto interval = NegInfInterval!Date(Date(2012, 1, 7));
9154 auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
9155 auto range = interval.bwdRange(func);
9156
9157 assert(range.func == func);
9158 }
9159