1 // Written in the D programming language
2 
3 /++
4     License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
5     Authors:   Jonathan M Davis
6     Source:    $(PHOBOSSRC std/datetime/_interval.d)
7 +/
8 module std.datetime.interval;
9 
10 import core.time : Duration, dur;
11 import std.datetime.date : AllowDayOverflow, DateTimeException, daysToDayOfWeek,
12                            DayOfWeek, isTimePoint, Month;
13 import std.exception : enforce;
14 import std.traits : isIntegral, Unqual;
15 import std.typecons : Flag;
16 
17 version (unittest) import std.exception : assertThrown;
18 
19 
20 /++
21     Indicates a direction in time. One example of its use is $(LREF Interval)'s
22     $(LREF expand) function which uses it to indicate whether the interval
23     should be expanded backwards (into the past), forwards (into the future), or
24     both.
25   +/
26 enum Direction
27 {
28     /// Backward.
29     bwd,
30 
31     /// Forward.
32     fwd,
33 
34     /// Both backward and forward.
35     both
36 }
37 
38 
39 /++
40     Used to indicate whether $(D popFront) should be called immediately upon
41     creating a range. The idea is that for some functions used to generate a
42     range for an interval, $(D front) is not necessarily a time point which
43     would ever be generated by the range (e.g. if the range were every Sunday
44     within an interval, but the interval started on a Monday), so there needs
45     to be a way to deal with that. To get the first time point in the range to
46     match what the function generates, then use $(D PopFirst.yes) to indicate
47     that the range should have $(D popFront) called on it before the range is
48     returned so that $(D front) is a time point which the function would
49     generate. To let the first time point not match the generator function,
50     use $(D PopFront.no).
51 
52     For instance, if the function used to generate a range of time points
53     generated successive Easters (i.e. you're iterating over all of the Easters
54     within the interval), the initial date probably isn't an Easter. Using
55     $(D PopFirst.yes) would tell the function which returned the range that
56     $(D popFront) was to be called so that front would then be an Easter - the
57     next one generated by the function (which when iterating forward would be
58     the Easter following the original $(D front), while when iterating backward,
59     it would be the Easter prior to the original $(D front)). If
60     $(D PopFirst.no) were used, then $(D front) would remain the original time
61     point and it would not necessarily be a time point which would be generated
62     by the range-generating function (which in many cases is exactly what is
63     desired - e.g. if iterating over every day starting at the beginning of the
64     interval).
65 
66     If set to $(D PopFirst.no), then popFront is not called before returning
67     the range.
68 
69     Otherwise, if set to $(D PopFirst.yes), then popFront is called before
70     returning the range.
71   +/
72 alias PopFirst = Flag!"popFirst";
73 
74 
75 /++
76     Represents an interval of time.
77 
78     An $(D Interval) has a starting point and an end point. The interval of time
79     is therefore the time starting at the starting point up to, but not
80     including, the end point. e.g.
81 
82     $(BOOKTABLE,
83     $(TR $(TD [January 5th, 2010 - March 10th, 2010$(RPAREN)))
84     $(TR $(TD [05:00:30 - 12:00:00$(RPAREN)))
85     $(TR $(TD [1982-01-04T08:59:00 - 2010-07-04T12:00:00$(RPAREN)))
86     )
87 
88     A range can be obtained from an $(D Interval), allowing iteration over
89     that interval, with the exact time points which are iterated over depending
90     on the function which generates the range.
91   +/
Interval(TP)92 struct Interval(TP)
93 {
94 public:
95 
96     /++
97         Params:
98             begin = The time point which begins the interval.
99             end   = The time point which ends (but is not included in) the
100                     interval.
101 
102         Throws:
103             $(REF DateTimeException,std,datetime,date) if $(D_PARAM end) is
104             before $(D_PARAM begin).
105 
106         Example:
107         --------------------
108         Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
109         --------------------
110       +/
111     this(U)(in TP begin, in U end) pure
112         if (is(Unqual!TP == Unqual!U))
113     {
114         if (!_valid(begin, end))
115             throw new DateTimeException("Arguments would result in an invalid Interval.");
116         _begin = cast(TP) begin;
117         _end = cast(TP) end;
118     }
119 
120 
121     /++
122         Params:
123             begin    = The time point which begins the interval.
124             duration = The duration from the starting point to the end point.
125 
126         Throws:
127             $(REF DateTimeException,std,datetime,date) if the resulting
128             $(D end) is before $(D begin).
129 
130         Example:
131         --------------------
132         assert(Interval!Date(Date(1996, 1, 2), dur!"days"(3)) ==
133                Interval!Date(Date(1996, 1, 2), Date(1996, 1, 5)));
134         --------------------
135       +/
136     this(D)(in TP begin, in D duration) pure
137         if (__traits(compiles, begin + duration))
138     {
139         _begin = cast(TP) begin;
140         _end = begin + duration;
141         if (!_valid(_begin, _end))
142             throw new DateTimeException("Arguments would result in an invalid Interval.");
143     }
144 
145 
146     /++
147         Params:
148             rhs = The $(LREF Interval) to assign to this one.
149       +/
150     ref Interval opAssign(const ref Interval rhs) pure nothrow
151     {
152         _begin = cast(TP) rhs._begin;
153         _end = cast(TP) rhs._end;
154         return this;
155     }
156 
157 
158     /++
159         Params:
160             rhs = The $(LREF Interval) to assign to this one.
161       +/
162     ref Interval opAssign(Interval rhs) pure nothrow
163     {
164         _begin = cast(TP) rhs._begin;
165         _end = cast(TP) rhs._end;
166         return this;
167     }
168 
169 
170     /++
171         The starting point of the interval. It is included in the interval.
172 
173         Example:
174         --------------------
175         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin ==
176                Date(1996, 1, 2));
177         --------------------
178       +/
179     @property TP begin() const pure nothrow
180     {
181         return cast(TP) _begin;
182     }
183 
184 
185     /++
186         The starting point of the interval. It is included in the interval.
187 
188         Params:
189             timePoint = The time point to set $(D begin) to.
190 
191         Throws:
192             $(REF DateTimeException,std,datetime,date) if the resulting
193             interval would be invalid.
194       +/
195     @property void begin(TP timePoint) pure
196     {
197         if (!_valid(timePoint, _end))
198             throw new DateTimeException("Arguments would result in an invalid Interval.");
199         _begin = timePoint;
200     }
201 
202 
203     /++
204         The end point of the interval. It is excluded from the interval.
205 
206         Example:
207         --------------------
208         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end ==
209                Date(2012, 3, 1));
210         --------------------
211       +/
212     @property TP end() const pure nothrow
213     {
214         return cast(TP) _end;
215     }
216 
217 
218     /++
219         The end point of the interval. It is excluded from the interval.
220 
221         Params:
222             timePoint = The time point to set end to.
223 
224         Throws:
225             $(REF DateTimeException,std,datetime,date) if the resulting
226             interval would be invalid.
227       +/
228     @property void end(TP timePoint) pure
229     {
230         if (!_valid(_begin, timePoint))
231             throw new DateTimeException("Arguments would result in an invalid Interval.");
232         _end = timePoint;
233     }
234 
235 
236     /++
237         Returns the duration between $(D begin) and $(D end).
238 
239         Example:
240         --------------------
241         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length ==
242                dur!"days"(5903));
243         --------------------
244       +/
245     @property auto length() const pure nothrow
246     {
247         return _end - _begin;
248     }
249 
250 
251     /++
252         Whether the interval's length is 0, that is, whether $(D begin == end).
253 
254         Example:
255         --------------------
256         assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
257         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
258         --------------------
259       +/
260     @property bool empty() const pure nothrow
261     {
262         return _begin == _end;
263     }
264 
265 
266     /++
267         Whether the given time point is within this interval.
268 
269         Params:
270             timePoint = The time point to check for inclusion in this interval.
271 
272         Throws:
273             $(REF DateTimeException,std,datetime,date) if this interval is
274             empty.
275 
276         Example:
277         --------------------
278         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
279                     Date(1994, 12, 24)));
280 
281         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
282                     Date(2000, 1, 5)));
283         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
284                     Date(2012, 3, 1)));
285         --------------------
286       +/
287     bool contains(in TP timePoint) const pure
288     {
289         _enforceNotEmpty();
290         return timePoint >= _begin && timePoint < _end;
291     }
292 
293 
294     /++
295         Whether the given interval is completely within this interval.
296 
297         Params:
298             interval = The interval to check for inclusion in this interval.
299 
300         Throws:
301             $(REF DateTimeException,std,datetime,date) if either interval is
302             empty.
303 
304         Example:
305         --------------------
306         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
307                     Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
308 
309         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
310                     Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
311 
312         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
313                     Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
314         --------------------
315       +/
316     bool contains(in Interval interval) const pure
317     {
318         _enforceNotEmpty();
319         interval._enforceNotEmpty();
320         return interval._begin >= _begin &&
321                interval._begin < _end &&
322                interval._end <= _end;
323     }
324 
325 
326     /++
327         Whether the given interval is completely within this interval.
328 
329         Always returns false (unless this interval is empty), because an
330         interval going to positive infinity can never be contained in a finite
331         interval.
332 
333         Params:
334             interval = The interval to check for inclusion in this interval.
335 
336         Throws:
337             $(REF DateTimeException,std,datetime,date) if this interval is
338             empty.
339 
340         Example:
341         --------------------
342         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
343                     PosInfInterval!Date(Date(1999, 5, 4))));
344         --------------------
345       +/
346     bool contains(in PosInfInterval!TP interval) const pure
347     {
348         _enforceNotEmpty();
349         return false;
350     }
351 
352 
353     /++
354         Whether the given interval is completely within this interval.
355 
356         Always returns false (unless this interval is empty), because an
357         interval beginning at negative infinity can never be contained in a
358         finite interval.
359 
360         Params:
361             interval = The interval to check for inclusion in this interval.
362 
363         Throws:
364             $(REF DateTimeException,std,datetime,date) if this interval is
365             empty.
366 
367         Example:
368         --------------------
369         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
370                     NegInfInterval!Date(Date(1996, 5, 4))));
371         --------------------
372       +/
373     bool contains(in NegInfInterval!TP interval) const pure
374     {
375         _enforceNotEmpty();
376         return false;
377     }
378 
379 
380     /++
381         Whether this interval is before the given time point.
382 
383         Params:
384             timePoint = The time point to check whether this interval is before
385                         it.
386 
387         Throws:
388             $(REF DateTimeException,std,datetime,date) if this interval is
389             empty.
390 
391         Example:
392         --------------------
393         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
394                     Date(1994, 12, 24)));
395 
396         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
397                     Date(2000, 1, 5)));
398 
399         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
400                     Date(2012, 3, 1)));
401         --------------------
402       +/
403     bool isBefore(in TP timePoint) const pure
404     {
405         _enforceNotEmpty();
406         return _end <= timePoint;
407     }
408 
409 
410     /++
411         Whether this interval is before the given interval and does not
412         intersect with it.
413 
414         Params:
415             interval = The interval to check for against this interval.
416 
417         Throws:
418             $(REF DateTimeException,std,datetime,date) if either interval is
419             empty.
420 
421         Example:
422         --------------------
423         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
424                     Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
425 
426         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
427                     Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
428 
429         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
430                     Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
431         --------------------
432       +/
433     bool isBefore(in Interval interval) const pure
434     {
435         _enforceNotEmpty();
436         interval._enforceNotEmpty();
437         return _end <= interval._begin;
438     }
439 
440 
441     /++
442         Whether this interval is before the given interval and does not
443         intersect with it.
444 
445         Params:
446             interval = The interval to check for against this interval.
447 
448         Throws:
449             $(REF DateTimeException,std,datetime,date) if this interval is
450             empty.
451 
452         Example:
453         --------------------
454         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
455                     PosInfInterval!Date(Date(1999, 5, 4))));
456 
457         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
458                     PosInfInterval!Date(Date(2013, 3, 7))));
459         --------------------
460       +/
461     bool isBefore(in PosInfInterval!TP interval) const pure
462     {
463         _enforceNotEmpty();
464         return _end <= interval._begin;
465     }
466 
467 
468     /++
469         Whether this interval is before the given interval and does not
470         intersect with it.
471 
472         Always returns false (unless this interval is empty) because a finite
473         interval can never be before an interval beginning at negative infinity.
474 
475         Params:
476             interval = The interval to check for against this interval.
477 
478         Throws:
479             $(REF DateTimeException,std,datetime,date) if this interval is
480             empty.
481 
482         Example:
483         --------------------
484         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
485                     NegInfInterval!Date(Date(1996, 5, 4))));
486         --------------------
487       +/
488     bool isBefore(in NegInfInterval!TP interval) const pure
489     {
490         _enforceNotEmpty();
491         return false;
492     }
493 
494 
495     /++
496         Whether this interval is after the given time point.
497 
498         Params:
499             timePoint = The time point to check whether this interval is after
500                         it.
501 
502         Throws:
503             $(REF DateTimeException,std,datetime,date) if this interval is
504             empty.
505 
506         Example:
507         --------------------
508         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
509                     Date(1994, 12, 24)));
510 
511         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
512                     Date(2000, 1, 5)));
513 
514         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
515                     Date(2012, 3, 1)));
516         --------------------
517       +/
518     bool isAfter(in TP timePoint) const pure
519     {
520         _enforceNotEmpty();
521         return timePoint < _begin;
522     }
523 
524 
525     /++
526         Whether this interval is after the given interval and does not intersect
527         it.
528 
529         Params:
530             interval = The interval to check against this interval.
531 
532         Throws:
533             $(REF DateTimeException,std,datetime,date) if either interval is
534             empty.
535 
536         Example:
537         --------------------
538         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
539                     Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
540 
541         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
542                     Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
543 
544         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
545                     Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
546         --------------------
547       +/
548     bool isAfter(in Interval interval) const pure
549     {
550         _enforceNotEmpty();
551         interval._enforceNotEmpty();
552         return _begin >= interval._end;
553     }
554 
555 
556     /++
557         Whether this interval is after the given interval and does not intersect
558         it.
559 
560         Always returns false (unless this interval is empty) because a finite
561         interval can never be after an interval going to positive infinity.
562 
563         Params:
564             interval = The interval to check against this interval.
565 
566         Throws:
567             $(REF DateTimeException,std,datetime,date) if this interval is
568             empty.
569 
570         Example:
571         --------------------
572         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
573                     PosInfInterval!Date(Date(1999, 5, 4))));
574         --------------------
575       +/
576     bool isAfter(in PosInfInterval!TP interval) const pure
577     {
578         _enforceNotEmpty();
579         return false;
580     }
581 
582 
583     /++
584         Whether this interval is after the given interval and does not intersect
585         it.
586 
587         Params:
588             interval = The interval to check against this interval.
589 
590         Throws:
591             $(REF DateTimeException,std,datetime,date) if this interval is
592             empty.
593 
594         Example:
595         --------------------
596         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
597                     NegInfInterval!Date(Date(1996, 1, 2))));
598         --------------------
599       +/
600     bool isAfter(in NegInfInterval!TP interval) const pure
601     {
602         _enforceNotEmpty();
603         return _begin >= interval._end;
604     }
605 
606 
607     /++
608         Whether the given interval overlaps this interval.
609 
610         Params:
611             interval = The interval to check for intersection with this interval.
612 
613         Throws:
614             $(REF DateTimeException,std,datetime,date) if either interval is
615             empty.
616 
617         Example:
618         --------------------
619         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
620                     Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
621 
622         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
623                     Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
624 
625         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
626                     Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
627         --------------------
628       +/
629     bool intersects(in Interval interval) const pure
630     {
631         _enforceNotEmpty();
632         interval._enforceNotEmpty();
633         return interval._begin < _end && interval._end > _begin;
634     }
635 
636 
637     /++
638         Whether the given interval overlaps this interval.
639 
640         Params:
641             interval = The interval to check for intersection with this interval.
642 
643         Throws:
644             $(REF DateTimeException,std,datetime,date) if this interval is
645             empty.
646 
647         Example:
648         --------------------
649         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
650                     PosInfInterval!Date(Date(1999, 5, 4))));
651 
652         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
653                     PosInfInterval!Date(Date(2012, 3, 1))));
654         --------------------
655       +/
656     bool intersects(in PosInfInterval!TP interval) const pure
657     {
658         _enforceNotEmpty();
659         return _end > interval._begin;
660     }
661 
662 
663     /++
664         Whether the given interval overlaps this interval.
665 
666         Params:
667             interval = The interval to check for intersection with this interval.
668 
669         Throws:
670             $(REF DateTimeException,std,datetime,date) if this interval is
671             empty.
672 
673         Example:
674         --------------------
675         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
676                     NegInfInterval!Date(Date(1996, 1, 2))));
677 
678         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
679                     NegInfInterval!Date(Date(2000, 1, 2))));
680         --------------------
681       +/
682     bool intersects(in NegInfInterval!TP interval) const pure
683     {
684         _enforceNotEmpty();
685         return _begin < interval._end;
686     }
687 
688 
689     /++
690         Returns the intersection of two intervals
691 
692         Params:
693             interval = The interval to intersect with this interval.
694 
695         Throws:
696             $(REF DateTimeException,std,datetime,date) if the two intervals do
697             not intersect or if either interval is empty.
698 
699         Example:
700         --------------------
701         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
702                     Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
703                Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
704 
705         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
706                     Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
707                Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
708         --------------------
709       +/
710     Interval intersection(in Interval interval) const
711     {
712         import std.format : format;
713 
714         enforce(this.intersects(interval),
715                 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
716 
717         auto begin = _begin > interval._begin ? _begin : interval._begin;
718         auto end = _end < interval._end ? _end : interval._end;
719 
720         return Interval(begin, end);
721     }
722 
723 
724     /++
725         Returns the intersection of two intervals
726 
727         Params:
728             interval = The interval to intersect with this interval.
729 
730         Throws:
731             $(REF DateTimeException,std,datetime,date) if the two intervals do
732             not intersect or if this interval is empty.
733 
734         Example:
735         --------------------
736         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
737                     PosInfInterval!Date(Date(1990, 7, 6))) ==
738                Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
739 
740         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
741                     PosInfInterval!Date(Date(1999, 1, 12))) ==
742                Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
743         --------------------
744       +/
745     Interval intersection(in PosInfInterval!TP interval) const
746     {
747         import std.format : format;
748 
749         enforce(this.intersects(interval),
750                 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
751 
752         return Interval(_begin > interval._begin ? _begin : interval._begin, _end);
753     }
754 
755 
756     /++
757         Returns the intersection of two intervals
758 
759         Params:
760             interval = The interval to intersect with this interval.
761 
762         Throws:
763             $(REF DateTimeException,std,datetime,date) if the two intervals do
764             not intersect or if this interval is empty.
765 
766         Example:
767         --------------------
768         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
769                     NegInfInterval!Date(Date(1999, 7, 6))) ==
770                Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
771 
772         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
773                     NegInfInterval!Date(Date(2013, 1, 12))) ==
774                Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
775         --------------------
776       +/
777     Interval intersection(in NegInfInterval!TP interval) const
778     {
779         import std.format : format;
780 
781         enforce(this.intersects(interval),
782                 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
783 
784         return Interval(_begin, _end < interval._end ? _end : interval._end);
785     }
786 
787 
788     /++
789         Whether the given interval is adjacent to this interval.
790 
791         Params:
792             interval = The interval to check whether its adjecent to this
793                        interval.
794 
795         Throws:
796             $(REF DateTimeException,std,datetime,date) if either interval is
797             empty.
798 
799         Example:
800         --------------------
801         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
802                     Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
803 
804         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
805                     Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
806 
807         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
808                     Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
809         --------------------
810       +/
811     bool isAdjacent(in Interval interval) const pure
812     {
813         _enforceNotEmpty();
814         interval._enforceNotEmpty();
815         return _begin == interval._end || _end == interval._begin;
816     }
817 
818 
819     /++
820         Whether the given interval is adjacent to this interval.
821 
822         Params:
823             interval = The interval to check whether its adjecent to this
824                        interval.
825 
826         Throws:
827             $(REF DateTimeException,std,datetime,date) if this interval is
828             empty.
829 
830         Example:
831         --------------------
832         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
833                     PosInfInterval!Date(Date(1999, 5, 4))));
834 
835         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
836                     PosInfInterval!Date(Date(2012, 3, 1))));
837         --------------------
838       +/
839     bool isAdjacent(in PosInfInterval!TP interval) const pure
840     {
841         _enforceNotEmpty();
842         return _end == interval._begin;
843     }
844 
845 
846     /++
847         Whether the given interval is adjacent to this interval.
848 
849         Params:
850             interval = The interval to check whether its adjecent to this
851                        interval.
852 
853         Throws:
854             $(REF DateTimeException,std,datetime,date) if this interval is
855             empty.
856 
857         Example:
858         --------------------
859         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
860                     NegInfInterval!Date(Date(1996, 1, 2))));
861 
862         assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
863                     NegInfInterval!Date(Date(2000, 1, 2))));
864         --------------------
865       +/
866     bool isAdjacent(in NegInfInterval!TP interval) const pure
867     {
868         _enforceNotEmpty();
869         return _begin == interval._end;
870     }
871 
872 
873     /++
874         Returns the union of two intervals
875 
876         Params:
877             interval = The interval to merge with this interval.
878 
879         Throws:
880             $(REF DateTimeException,std,datetime,date) if the two intervals do
881             not intersect and are not adjacent or if either interval is empty.
882 
883         Example:
884         --------------------
885         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
886                     Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
887                Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
888 
889         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
890                     Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
891                Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
892         --------------------
893       +/
894     Interval merge(in Interval interval) const
895     {
896         import std.format : format;
897 
898         enforce(this.isAdjacent(interval) || this.intersects(interval),
899                 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
900 
901         auto begin = _begin < interval._begin ? _begin : interval._begin;
902         auto end = _end > interval._end ? _end : interval._end;
903 
904         return Interval(begin, end);
905     }
906 
907 
908     /++
909         Returns the union of two intervals
910 
911         Params:
912             interval = The interval to merge with this interval.
913 
914         Throws:
915             $(REF DateTimeException,std,datetime,date) if the two intervals do
916             not intersect and are not adjacent or if this interval is empty.
917 
918         Example:
919         --------------------
920         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
921                     PosInfInterval!Date(Date(1990, 7, 6))) ==
922                PosInfInterval!Date(Date(1990, 7 , 6)));
923 
924         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
925                     PosInfInterval!Date(Date(2012, 3, 1))) ==
926                PosInfInterval!Date(Date(1996, 1 , 2)));
927         --------------------
928       +/
929     PosInfInterval!TP merge(in PosInfInterval!TP interval) const
930     {
931         import std.format : format;
932 
933         enforce(this.isAdjacent(interval) || this.intersects(interval),
934                 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
935 
936         return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
937     }
938 
939 
940     /++
941         Returns the union of two intervals
942 
943         Params:
944             interval = The interval to merge with this interval.
945 
946         Throws:
947             $(REF DateTimeException,std,datetime,date) if the two intervals do
948             not intersect and are not adjacent or if this interval is empty.
949 
950         Example:
951         --------------------
952         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
953                     NegInfInterval!Date(Date(1996, 1, 2))) ==
954                NegInfInterval!Date(Date(2012, 3 , 1)));
955 
956         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
957                     NegInfInterval!Date(Date(2013, 1, 12))) ==
958                NegInfInterval!Date(Date(2013, 1 , 12)));
959         --------------------
960       +/
961     NegInfInterval!TP merge(in NegInfInterval!TP interval) const
962     {
963         import std.format : format;
964 
965         enforce(this.isAdjacent(interval) || this.intersects(interval),
966                 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
967 
968         return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
969     }
970 
971 
972     /++
973         Returns an interval that covers from the earliest time point of two
974         intervals up to (but not including) the latest time point of two
975         intervals.
976 
977         Params:
978             interval = The interval to create a span together with this interval.
979 
980         Throws:
981             $(REF DateTimeException,std,datetime,date) if either interval is
982             empty.
983 
984         Example:
985         --------------------
986         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
987                     Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) ==
988                Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
989 
990         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
991                     Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
992                Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
993         --------------------
994       +/
995     Interval span(in Interval interval) const pure
996     {
997         _enforceNotEmpty();
998         interval._enforceNotEmpty();
999 
1000         auto begin = _begin < interval._begin ? _begin : interval._begin;
1001         auto end = _end > interval._end ? _end : interval._end;
1002 
1003         return Interval(begin, end);
1004     }
1005 
1006 
1007     /++
1008         Returns an interval that covers from the earliest time point of two
1009         intervals up to (but not including) the latest time point of two
1010         intervals.
1011 
1012         Params:
1013             interval = The interval to create a span together with this interval.
1014 
1015         Throws:
1016             $(REF DateTimeException,std,datetime,date) if this interval is
1017             empty.
1018 
1019         Example:
1020         --------------------
1021         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1022                     PosInfInterval!Date(Date(1990, 7, 6))) ==
1023                PosInfInterval!Date(Date(1990, 7 , 6)));
1024 
1025         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1026                     PosInfInterval!Date(Date(2050, 1, 1))) ==
1027                PosInfInterval!Date(Date(1996, 1 , 2)));
1028         --------------------
1029       +/
1030     PosInfInterval!TP span(in PosInfInterval!TP interval) const pure
1031     {
1032         _enforceNotEmpty();
1033         return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
1034     }
1035 
1036 
1037     /++
1038         Returns an interval that covers from the earliest time point of two
1039         intervals up to (but not including) the latest time point of two
1040         intervals.
1041 
1042         Params:
1043             interval = The interval to create a span together with this interval.
1044 
1045         Throws:
1046             $(REF DateTimeException,std,datetime,date) if this interval is
1047             empty.
1048 
1049         Example:
1050         --------------------
1051         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1052                     NegInfInterval!Date(Date(1602, 5, 21))) ==
1053                NegInfInterval!Date(Date(2012, 3 , 1)));
1054 
1055         assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
1056                     NegInfInterval!Date(Date(2013, 1, 12))) ==
1057                NegInfInterval!Date(Date(2013, 1 , 12)));
1058         --------------------
1059       +/
1060     NegInfInterval!TP span(in NegInfInterval!TP interval) const pure
1061     {
1062         _enforceNotEmpty();
1063         return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
1064     }
1065 
1066 
1067     /++
1068         Shifts the interval forward or backwards in time by the given duration
1069         (a positive duration shifts the interval forward; a negative duration
1070         shifts it backward). Effectively, it does $(D begin += duration) and
1071         $(D end += duration).
1072 
1073         Params:
1074             duration = The duration to shift the interval by.
1075 
1076         Throws:
1077             $(REF DateTimeException,std,datetime,date) this interval is empty
1078             or if the resulting interval would be invalid.
1079 
1080         Example:
1081         --------------------
1082         auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
1083         auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
1084 
1085         interval1.shift(dur!"days"(50));
1086         assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
1087 
1088         interval2.shift(dur!"days"(-50));
1089         assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
1090         --------------------
1091       +/
1092     void shift(D)(D duration) pure
1093         if (__traits(compiles, begin + duration))
1094     {
1095         _enforceNotEmpty();
1096 
1097         auto begin = _begin + duration;
1098         auto end = _end + duration;
1099 
1100         if (!_valid(begin, end))
1101             throw new DateTimeException("Argument would result in an invalid Interval.");
1102 
1103         _begin = begin;
1104         _end = end;
1105     }
1106 
1107 
1108     static if (__traits(compiles, begin.add!"months"(1)) &&
1109                __traits(compiles, begin.add!"years"(1)))
1110     {
1111         /++
1112             Shifts the interval forward or backwards in time by the given number
1113             of years and/or months (a positive number of years and months shifts
1114             the interval forward; a negative number shifts it backward).
1115             It adds the years the given years and months to both begin and end.
1116             It effectively calls $(D add!"years"()) and then $(D add!"months"())
1117             on begin and end with the given number of years and months.
1118 
1119             Params:
1120                 years         = The number of years to shift the interval by.
1121                 months        = The number of months to shift the interval by.
1122                 allowOverflow = Whether the days should be allowed to overflow
1123                                 on $(D begin) and $(D end), causing their month
1124                                 to increment.
1125 
1126             Throws:
1127                 $(REF DateTimeException,std,datetime,date) if this interval is
1128                 empty or if the resulting interval would be invalid.
1129 
1130             Example:
1131             --------------------
1132             auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1133             auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1134 
1135             interval1.shift(2);
1136             assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
1137 
1138             interval2.shift(-2);
1139             assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
1140             --------------------
1141           +/
1142         void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
1143             if (isIntegral!T)
1144         {
1145             _enforceNotEmpty();
1146 
1147             auto begin = _begin;
1148             auto end = _end;
1149 
1150             begin.add!"years"(years, allowOverflow);
1151             begin.add!"months"(months, allowOverflow);
1152             end.add!"years"(years, allowOverflow);
1153             end.add!"months"(months, allowOverflow);
1154 
1155             enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
1156 
1157             _begin = begin;
1158             _end = end;
1159         }
1160     }
1161 
1162 
1163     /++
1164         Expands the interval forwards and/or backwards in time. Effectively,
1165         it does $(D begin -= duration) and/or $(D end += duration). Whether
1166         it expands forwards and/or backwards in time is determined by
1167         $(D_PARAM dir).
1168 
1169         Params:
1170             duration = The duration to expand the interval by.
1171             dir      = The direction in time to expand the interval.
1172 
1173         Throws:
1174             $(REF DateTimeException,std,datetime,date) this interval is empty
1175             or if the resulting interval would be invalid.
1176 
1177         Example:
1178         --------------------
1179         auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1180         auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1181 
1182         interval1.expand(2);
1183         assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
1184 
1185         interval2.expand(-2);
1186         assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
1187         --------------------
1188       +/
1189     void expand(D)(D duration, Direction dir = Direction.both) pure
1190         if (__traits(compiles, begin + duration))
1191     {
1192         _enforceNotEmpty();
1193 
1194         switch (dir)
1195         {
1196             case Direction.both:
1197             {
1198                 auto begin = _begin - duration;
1199                 auto end = _end + duration;
1200 
1201                 if (!_valid(begin, end))
1202                     throw new DateTimeException("Argument would result in an invalid Interval.");
1203 
1204                 _begin = begin;
1205                 _end = end;
1206 
1207                 return;
1208             }
1209             case Direction.fwd:
1210             {
1211                 auto end = _end + duration;
1212 
1213                 if (!_valid(_begin, end))
1214                     throw new DateTimeException("Argument would result in an invalid Interval.");
1215                 _end = end;
1216 
1217                 return;
1218             }
1219             case Direction.bwd:
1220             {
1221                 auto begin = _begin - duration;
1222 
1223                 if (!_valid(begin, _end))
1224                     throw new DateTimeException("Argument would result in an invalid Interval.");
1225                 _begin = begin;
1226 
1227                 return;
1228             }
1229             default:
1230                 assert(0, "Invalid Direction.");
1231         }
1232     }
1233 
1234     static if (__traits(compiles, begin.add!"months"(1)) &&
1235                __traits(compiles, begin.add!"years"(1)))
1236     {
1237         /++
1238             Expands the interval forwards and/or backwards in time. Effectively,
1239             it subtracts the given number of months/years from $(D begin) and
1240             adds them to $(D end). Whether it expands forwards and/or backwards
1241             in time is determined by $(D_PARAM dir).
1242 
1243             Params:
1244                 years         = The number of years to expand the interval by.
1245                 months        = The number of months to expand the interval by.
1246                 allowOverflow = Whether the days should be allowed to overflow
1247                                 on $(D begin) and $(D end), causing their month
1248                                 to increment.
1249                 dir           = The direction in time to expand the interval.
1250 
1251             Throws:
1252                 $(REF DateTimeException,std,datetime,date) if this interval is
1253                 empty or if the resulting interval would be invalid.
1254 
1255             Example:
1256             --------------------
1257             auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1258             auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1259 
1260             interval1.expand(2);
1261             assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
1262 
1263             interval2.expand(-2);
1264             assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
1265             --------------------
1266           +/
1267         void expand(T)(T years,
1268                        T months = 0,
1269                        AllowDayOverflow allowOverflow = AllowDayOverflow.yes,
1270                        Direction dir = Direction.both)
1271         if (isIntegral!T)
1272         {
1273             _enforceNotEmpty();
1274 
1275             switch (dir)
1276             {
1277                 case Direction.both:
1278                 {
1279                     auto begin = _begin;
1280                     auto end = _end;
1281 
1282                     begin.add!"years"(-years, allowOverflow);
1283                     begin.add!"months"(-months, allowOverflow);
1284                     end.add!"years"(years, allowOverflow);
1285                     end.add!"months"(months, allowOverflow);
1286 
1287                     enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
1288                     _begin = begin;
1289                     _end = end;
1290 
1291                     return;
1292                 }
1293                 case Direction.fwd:
1294                 {
1295                     auto end = _end;
1296 
1297                     end.add!"years"(years, allowOverflow);
1298                     end.add!"months"(months, allowOverflow);
1299 
1300                     enforce(_valid(_begin, end),
1301                             new DateTimeException("Argument would result in an invalid Interval."));
1302                     _end = end;
1303 
1304                     return;
1305                 }
1306                 case Direction.bwd:
1307                 {
1308                     auto begin = _begin;
1309 
1310                     begin.add!"years"(-years, allowOverflow);
1311                     begin.add!"months"(-months, allowOverflow);
1312 
1313                     enforce(_valid(begin, _end),
1314                             new DateTimeException("Argument would result in an invalid Interval."));
1315                     _begin = begin;
1316 
1317                     return;
1318                 }
1319                 default:
1320                     assert(0, "Invalid Direction.");
1321             }
1322         }
1323     }
1324 
1325 
1326     /++
1327         Returns a range which iterates forward over the interval, starting
1328         at $(D begin), using $(D_PARAM func) to generate each successive time
1329         point.
1330 
1331         The range's $(D front) is the interval's $(D begin). $(D_PARAM func) is
1332         used to generate the next $(D front) when $(D popFront) is called. If
1333         $(D_PARAM popFirst) is $(D PopFirst.yes), then $(D popFront) is called
1334         before the range is returned (so that $(D front) is a time point which
1335         $(D_PARAM func) would generate).
1336 
1337         If $(D_PARAM func) ever generates a time point less than or equal to the
1338         current $(D front) of the range, then a
1339         $(REF DateTimeException,std,datetime,date) will be thrown. The range
1340         will be empty and iteration complete when $(D_PARAM func) generates a
1341         time point equal to or beyond the $(D end) of the interval.
1342 
1343         There are helper functions in this module which generate common
1344         delegates to pass to $(D fwdRange). Their documentation starts with
1345         "Range-generating function," making them easily searchable.
1346 
1347         Params:
1348             func     = The function used to generate the time points of the
1349                        range over the interval.
1350             popFirst = Whether $(D popFront) should be called on the range
1351                        before returning it.
1352 
1353         Throws:
1354             $(REF DateTimeException,std,datetime,date) if this interval is
1355             empty.
1356 
1357         Warning:
1358             $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
1359             would be a function pointer to a pure function, but forcing
1360             $(D_PARAM func) to be pure is far too restrictive to be useful, and
1361             in order to have the ease of use of having functions which generate
1362             functions to pass to $(D fwdRange), $(D_PARAM func) must be a
1363             delegate.
1364 
1365             If $(D_PARAM func) retains state which changes as it is called, then
1366             some algorithms will not work correctly, because the range's
1367             $(D save) will have failed to have really saved the range's state.
1368             To avoid such bugs, don't pass a delegate which is
1369             not logically pure to $(D fwdRange). If $(D_PARAM func) is given the
1370             same time point with two different calls, it must return the same
1371             result both times.
1372 
1373             Of course, none of the functions in this module have this problem,
1374             so it's only relevant if when creating a custom delegate.
1375 
1376         Example:
1377         --------------------
1378         auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
1379         auto func = delegate (in Date date) // For iterating over even-numbered days.
1380                     {
1381                         if ((date.day & 1) == 0)
1382                             return date + dur!"days"(2);
1383 
1384                         return date + dur!"days"(1);
1385                     };
1386         auto range = interval.fwdRange(func);
1387 
1388         // An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
1389         assert(range.front == Date(2010, 9, 1));
1390 
1391         range.popFront();
1392         assert(range.front == Date(2010, 9, 2));
1393 
1394         range.popFront();
1395         assert(range.front == Date(2010, 9, 4));
1396 
1397         range.popFront();
1398         assert(range.front == Date(2010, 9, 6));
1399 
1400         range.popFront();
1401         assert(range.front == Date(2010, 9, 8));
1402 
1403         range.popFront();
1404         assert(range.empty);
1405         --------------------
1406       +/
1407     IntervalRange!(TP, Direction.fwd) fwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
1408     {
1409         _enforceNotEmpty();
1410 
1411         auto range = IntervalRange!(TP, Direction.fwd)(this, func);
1412 
1413         if (popFirst == PopFirst.yes)
1414             range.popFront();
1415 
1416         return range;
1417     }
1418 
1419 
1420     /++
1421         Returns a range which iterates backwards over the interval, starting
1422         at $(D end), using $(D_PARAM func) to generate each successive time
1423         point.
1424 
1425         The range's $(D front) is the interval's $(D end). $(D_PARAM func) is
1426         used to generate the next $(D front) when $(D popFront) is called. If
1427         $(D_PARAM popFirst) is $(D PopFirst.yes), then $(D popFront) is called
1428         before the range is returned (so that $(D front) is a time point which
1429         $(D_PARAM func) would generate).
1430 
1431         If $(D_PARAM func) ever generates a time point greater than or equal to
1432         the current $(D front) of the range, then a
1433         $(REF DateTimeException,std,datetime,date) will be thrown. The range
1434         will be empty and iteration complete when $(D_PARAM func) generates a
1435         time point equal to or less than the $(D begin) of the interval.
1436 
1437         There are helper functions in this module which generate common
1438         delegates to pass to $(D bwdRange). Their documentation starts with
1439         "Range-generating function," making them easily searchable.
1440 
1441         Params:
1442             func     = The function used to generate the time points of the
1443                        range over the interval.
1444             popFirst = Whether $(D popFront) should be called on the range
1445                        before returning it.
1446 
1447         Throws:
1448             $(REF DateTimeException,std,datetime,date) if this interval is
1449             empty.
1450 
1451         Warning:
1452             $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
1453             would be a function pointer to a pure function, but forcing
1454             $(D_PARAM func) to be pure is far too restrictive to be useful, and
1455             in order to have the ease of use of having functions which generate
1456             functions to pass to $(D fwdRange), $(D_PARAM func) must be a
1457             delegate.
1458 
1459             If $(D_PARAM func) retains state which changes as it is called, then
1460             some algorithms will not work correctly, because the range's
1461             $(D save) will have failed to have really saved the range's state.
1462             To avoid such bugs, don't pass a delegate which is
1463             not logically pure to $(D fwdRange). If $(D_PARAM func) is given the
1464             same time point with two different calls, it must return the same
1465             result both times.
1466 
1467             Of course, none of the functions in this module have this problem,
1468             so it's only relevant for custom delegates.
1469 
1470         Example:
1471         --------------------
1472         auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
1473         auto func = delegate (in Date date) // For iterating over even-numbered days.
1474                     {
1475                         if ((date.day & 1) == 0)
1476                             return date - dur!"days"(2);
1477 
1478                         return date - dur!"days"(1);
1479                     };
1480         auto range = interval.bwdRange(func);
1481 
1482         // An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
1483         assert(range.front == Date(2010, 9, 9));
1484 
1485         range.popFront();
1486         assert(range.front == Date(2010, 9, 8));
1487 
1488         range.popFront();
1489         assert(range.front == Date(2010, 9, 6));
1490 
1491         range.popFront();
1492         assert(range.front == Date(2010, 9, 4));
1493 
1494         range.popFront();
1495         assert(range.front == Date(2010, 9, 2));
1496 
1497         range.popFront();
1498         assert(range.empty);
1499         --------------------
1500       +/
1501     IntervalRange!(TP, Direction.bwd) bwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
1502     {
1503         _enforceNotEmpty();
1504 
1505         auto range = IntervalRange!(TP, Direction.bwd)(this, func);
1506 
1507         if (popFirst == PopFirst.yes)
1508             range.popFront();
1509 
1510         return range;
1511     }
1512 
1513 
1514     /+
1515         Converts this interval to a string.
1516       +/
1517     // Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
1518     // have versions of toString() with extra modifiers, so we define one version
1519     // with modifiers and one without.
1520     string toString()
1521     {
1522         return _toStringImpl();
1523     }
1524 
1525 
1526     /++
1527         Converts this interval to a string.
1528       +/
1529     // Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
1530     // have versions of toString() with extra modifiers, so we define one version
1531     // with modifiers and one without.
1532     string toString() const nothrow
1533     {
1534         return _toStringImpl();
1535     }
1536 
1537 
1538 private:
1539 
1540     /+
1541         Since we have two versions of toString, we have _toStringImpl
1542         so that they can share implementations.
1543       +/
1544     string _toStringImpl() const nothrow
1545     {
1546         import std.format : format;
1547         try
1548             return format("[%s - %s)", _begin, _end);
1549         catch (Exception e)
1550             assert(0, "format() threw.");
1551     }
1552 
1553 
1554     /+
1555         Throws:
1556             $(REF DateTimeException,std,datetime,date) if this interval is
1557             empty.
1558       +/
1559     void _enforceNotEmpty(size_t line = __LINE__) const pure
1560     {
1561         if (empty)
1562             throw new DateTimeException("Invalid operation for an empty Interval.", __FILE__, line);
1563     }
1564 
1565 
1566     /+
1567         Whether the given values form a valid time interval.
1568 
1569         Params:
1570             begin = The starting point of the interval.
1571             end   = The end point of the interval.
1572      +/
1573     static bool _valid(in TP begin, in TP end) pure nothrow
1574     {
1575         return begin <= end;
1576     }
1577 
1578 
1579     pure invariant()
1580     {
1581         assert(_valid(_begin, _end), "Invariant Failure: begin is not before or equal to end.");
1582     }
1583 
1584 
1585     TP _begin;
1586     TP _end;
1587 }
1588 
1589 // Test Interval's constructors.
1590 @safe unittest
1591 {
1592     import std.datetime.date;
1593     import std.datetime.systime;
1594 
1595     assertThrown!DateTimeException(Interval!Date(Date(2010, 1, 1), Date(1, 1, 1)));
1596 
1597     Interval!Date(Date.init, Date.init);
1598     Interval!TimeOfDay(TimeOfDay.init, TimeOfDay.init);
1599     Interval!DateTime(DateTime.init, DateTime.init);
1600     Interval!SysTime(SysTime(0), SysTime(0));
1601 
1602     Interval!DateTime(DateTime.init, dur!"days"(7));
1603 
1604     // Verify Examples.
1605     Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
1606     assert(Interval!Date(Date(1996, 1, 2), dur!"weeks"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 23)));
1607     assert(Interval!Date(Date(1996, 1, 2), dur!"days"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 5)));
1608     assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"hours"(3)) ==
1609            Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 15, 0, 0)));
1610     assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"minutes"(3)) ==
1611            Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 3, 0)));
1612     assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"seconds"(3)) ==
1613            Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
1614     assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"msecs"(3000)) ==
1615            Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
1616 }
1617 
1618 // Test Interval's begin.
1619 @safe unittest
1620 {
1621     import std.datetime.date;
1622 
1623     assert(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).begin == Date(1, 1, 1));
1624     assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).begin == Date(2010, 1, 1));
1625     assert(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).begin == Date(1997, 12, 31));
1626 
1627     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1628     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1629     assert(cInterval.begin == Date(2010, 7, 4));
1630     assert(iInterval.begin == Date(2010, 7, 4));
1631 
1632     // Verify Examples.
1633     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin == Date(1996, 1, 2));
1634 }
1635 
1636 // Test Interval's end.
1637 @safe unittest
1638 {
1639     import std.datetime.date;
1640 
1641     assert(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).end == Date(2010, 1, 1));
1642     assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).end == Date(2010, 1, 1));
1643     assert(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).end == Date(1998, 1, 1));
1644 
1645     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1646     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1647     assert(cInterval.end == Date(2012, 1, 7));
1648     assert(iInterval.end == Date(2012, 1, 7));
1649 
1650     // Verify Examples.
1651     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end == Date(2012, 3, 1));
1652 }
1653 
1654 // Test Interval's length.
1655 @safe unittest
1656 {
1657     import std.datetime.date;
1658     import std.datetime.systime;
1659 
1660     assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).length == dur!"days"(0));
1661     assert(Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).length == dur!"days"(90));
1662     assert(Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).length == dur!"seconds"(42_727));
1663     assert(Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).length ==
1664            dur!"seconds"(129_127));
1665     assert(Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)),SysTime(DateTime(2010, 1, 2, 12, 22, 7))).length ==
1666            dur!"seconds"(129_127));
1667 
1668     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1669     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1670     assert(cInterval.length != Duration.zero);
1671     assert(iInterval.length != Duration.zero);
1672 
1673     // Verify Examples.
1674     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length == dur!"days"(5903));
1675 }
1676 
1677 // Test Interval's empty.
1678 @safe unittest
1679 {
1680     import std.datetime.date;
1681     import std.datetime.systime;
1682 
1683     assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).empty);
1684     assert(!Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).empty);
1685     assert(!Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).empty);
1686     assert(!Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).empty);
1687     assert(!Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)), SysTime(DateTime(2010, 1, 2, 12, 22, 7))).empty);
1688 
1689     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1690     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1691     assert(!cInterval.empty);
1692     assert(!iInterval.empty);
1693 
1694     // Verify Examples.
1695     assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
1696     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
1697 }
1698 
1699 // Test Interval's contains(time point).
1700 @safe unittest
1701 {
1702     import std.datetime.date;
1703 
1704     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1705 
1706     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(Date(2010, 7, 4)));
1707 
1708     assert(!interval.contains(Date(2009, 7, 4)));
1709     assert(!interval.contains(Date(2010, 7, 3)));
1710     assert(interval.contains(Date(2010, 7, 4)));
1711     assert(interval.contains(Date(2010, 7, 5)));
1712     assert(interval.contains(Date(2011, 7, 1)));
1713     assert(interval.contains(Date(2012, 1, 6)));
1714     assert(!interval.contains(Date(2012, 1, 7)));
1715     assert(!interval.contains(Date(2012, 1, 8)));
1716     assert(!interval.contains(Date(2013, 1, 7)));
1717 
1718     const cdate = Date(2010, 7, 6);
1719     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1720     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1721     assert(interval.contains(cdate));
1722     assert(cInterval.contains(cdate));
1723     assert(iInterval.contains(cdate));
1724 
1725     // Verify Examples.
1726     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
1727     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
1728     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
1729 }
1730 
1731 // Test Interval's contains(Interval).
1732 @safe unittest
1733 {
1734     import std.datetime.date;
1735 
1736     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1737 
1738     assertThrown!DateTimeException(interval.contains(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
1739     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(interval));
1740     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4),dur!"days"(0)).contains(
1741                                        Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
1742 
1743     assert(interval.contains(interval));
1744     assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
1745     assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
1746     assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
1747     assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
1748     assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
1749     assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
1750     assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
1751     assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
1752     assert(interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
1753     assert(!interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
1754     assert(!interval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
1755     assert(!interval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
1756 
1757     assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).contains(interval));
1758     assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).contains(interval));
1759     assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).contains(interval));
1760     assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).contains(interval));
1761     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).contains(interval));
1762     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).contains(interval));
1763     assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).contains(interval));
1764     assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).contains(interval));
1765     assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).contains(interval));
1766     assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).contains(interval));
1767     assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).contains(interval));
1768     assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).contains(interval));
1769 
1770     assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
1771     assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
1772     assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
1773     assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
1774     assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
1775     assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
1776 
1777     assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
1778     assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
1779     assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
1780     assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
1781     assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
1782     assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
1783 
1784     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1785     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1786     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1787     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1788     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1789     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1790     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1791     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1792     assert(interval.contains(interval));
1793     assert(interval.contains(cInterval));
1794     assert(interval.contains(iInterval));
1795     assert(!interval.contains(posInfInterval));
1796     assert(!interval.contains(cPosInfInterval));
1797     assert(!interval.contains(iPosInfInterval));
1798     assert(!interval.contains(negInfInterval));
1799     assert(!interval.contains(cNegInfInterval));
1800     assert(!interval.contains(iNegInfInterval));
1801     assert(cInterval.contains(interval));
1802     assert(cInterval.contains(cInterval));
1803     assert(cInterval.contains(iInterval));
1804     assert(!cInterval.contains(posInfInterval));
1805     assert(!cInterval.contains(cPosInfInterval));
1806     assert(!cInterval.contains(iPosInfInterval));
1807     assert(!cInterval.contains(negInfInterval));
1808     assert(!cInterval.contains(cNegInfInterval));
1809     assert(!cInterval.contains(iNegInfInterval));
1810     assert(iInterval.contains(interval));
1811     assert(iInterval.contains(cInterval));
1812     assert(iInterval.contains(iInterval));
1813     assert(!iInterval.contains(posInfInterval));
1814     assert(!iInterval.contains(cPosInfInterval));
1815     assert(!iInterval.contains(iPosInfInterval));
1816     assert(!iInterval.contains(negInfInterval));
1817     assert(!iInterval.contains(cNegInfInterval));
1818     assert(!iInterval.contains(iNegInfInterval));
1819 
1820     // Verify Examples.
1821     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
1822                Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
1823     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
1824                Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
1825     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
1826                Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
1827 
1828     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
1829 
1830     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
1831 }
1832 
1833 // Test Interval's isBefore(time point).
1834 @safe unittest
1835 {
1836     import std.datetime.date;
1837 
1838     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1839 
1840     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(Date(2010, 7, 4)));
1841 
1842     assert(!interval.isBefore(Date(2009, 7, 3)));
1843     assert(!interval.isBefore(Date(2010, 7, 3)));
1844     assert(!interval.isBefore(Date(2010, 7, 4)));
1845     assert(!interval.isBefore(Date(2010, 7, 5)));
1846     assert(!interval.isBefore(Date(2011, 7, 1)));
1847     assert(!interval.isBefore(Date(2012, 1, 6)));
1848     assert(interval.isBefore(Date(2012, 1, 7)));
1849     assert(interval.isBefore(Date(2012, 1, 8)));
1850     assert(interval.isBefore(Date(2013, 1, 7)));
1851 
1852     const cdate = Date(2010, 7, 6);
1853     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1854     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1855     assert(!interval.isBefore(cdate));
1856     assert(!cInterval.isBefore(cdate));
1857     assert(!iInterval.isBefore(cdate));
1858 
1859     // Verify Examples.
1860     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
1861     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
1862     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
1863 }
1864 
1865 // Test Interval's isBefore(Interval).
1866 @safe unittest
1867 {
1868     import std.datetime.date;
1869 
1870     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1871 
1872     assertThrown!DateTimeException(interval.isBefore(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
1873     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(interval));
1874     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(
1875                                        Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
1876 
1877     assert(!interval.isBefore(interval));
1878     assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
1879     assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
1880     assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
1881     assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
1882     assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
1883     assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
1884     assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
1885     assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
1886     assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
1887     assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
1888     assert(interval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
1889     assert(interval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
1890 
1891     assert(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isBefore(interval));
1892     assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isBefore(interval));
1893     assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isBefore(interval));
1894     assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isBefore(interval));
1895     assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isBefore(interval));
1896     assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isBefore(interval));
1897     assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isBefore(interval));
1898     assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isBefore(interval));
1899     assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isBefore(interval));
1900     assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isBefore(interval));
1901     assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isBefore(interval));
1902     assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isBefore(interval));
1903 
1904     assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
1905     assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
1906     assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
1907     assert(!interval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
1908     assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
1909     assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
1910 
1911     assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
1912     assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
1913     assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
1914     assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
1915     assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
1916     assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
1917 
1918     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1919     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1920     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1921     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1922     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
1923     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1924     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1925     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
1926     assert(!interval.isBefore(interval));
1927     assert(!interval.isBefore(cInterval));
1928     assert(!interval.isBefore(iInterval));
1929     assert(!interval.isBefore(posInfInterval));
1930     assert(!interval.isBefore(cPosInfInterval));
1931     assert(!interval.isBefore(iPosInfInterval));
1932     assert(!interval.isBefore(negInfInterval));
1933     assert(!interval.isBefore(cNegInfInterval));
1934     assert(!interval.isBefore(iNegInfInterval));
1935     assert(!cInterval.isBefore(interval));
1936     assert(!cInterval.isBefore(cInterval));
1937     assert(!cInterval.isBefore(iInterval));
1938     assert(!cInterval.isBefore(posInfInterval));
1939     assert(!cInterval.isBefore(cPosInfInterval));
1940     assert(!cInterval.isBefore(iPosInfInterval));
1941     assert(!cInterval.isBefore(negInfInterval));
1942     assert(!cInterval.isBefore(cNegInfInterval));
1943     assert(!cInterval.isBefore(iNegInfInterval));
1944     assert(!iInterval.isBefore(interval));
1945     assert(!iInterval.isBefore(cInterval));
1946     assert(!iInterval.isBefore(iInterval));
1947     assert(!iInterval.isBefore(posInfInterval));
1948     assert(!iInterval.isBefore(cPosInfInterval));
1949     assert(!iInterval.isBefore(iPosInfInterval));
1950     assert(!iInterval.isBefore(negInfInterval));
1951     assert(!iInterval.isBefore(cNegInfInterval));
1952     assert(!iInterval.isBefore(iNegInfInterval));
1953 
1954     // Verify Examples.
1955     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
1956                Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
1957     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
1958                Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
1959     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
1960                Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
1961 
1962     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
1963     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
1964 
1965     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
1966 }
1967 
1968 // Test Interval's isAfter(time point).
1969 @safe unittest
1970 {
1971     import std.datetime.date;
1972 
1973     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1974 
1975     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(Date(2010, 7, 4)));
1976 
1977     assert(interval.isAfter(Date(2009, 7, 4)));
1978     assert(interval.isAfter(Date(2010, 7, 3)));
1979     assert(!interval.isAfter(Date(2010, 7, 4)));
1980     assert(!interval.isAfter(Date(2010, 7, 5)));
1981     assert(!interval.isAfter(Date(2011, 7, 1)));
1982     assert(!interval.isAfter(Date(2012, 1, 6)));
1983     assert(!interval.isAfter(Date(2012, 1, 7)));
1984     assert(!interval.isAfter(Date(2012, 1, 8)));
1985     assert(!interval.isAfter(Date(2013, 1, 7)));
1986 
1987     const cdate = Date(2010, 7, 6);
1988     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1989     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
1990     assert(!interval.isAfter(cdate));
1991     assert(!cInterval.isAfter(cdate));
1992     assert(!iInterval.isAfter(cdate));
1993 
1994     // Verify Examples.
1995     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
1996     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
1997     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
1998 }
1999 
2000 // Test Interval's isAfter(Interval).
2001 @safe unittest
2002 {
2003     import std.datetime.date;
2004 
2005     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2006 
2007     assertThrown!DateTimeException(interval.isAfter(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2008     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(interval));
2009     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(
2010                                        Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2011 
2012     assert(!interval.isAfter(interval));
2013     assert(interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2014     assert(!interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
2015     assert(interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
2016     assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
2017     assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
2018     assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
2019     assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
2020     assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
2021     assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
2022     assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
2023     assert(!interval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
2024     assert(!interval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2025 
2026     assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAfter(interval));
2027     assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAfter(interval));
2028     assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAfter(interval));
2029     assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAfter(interval));
2030     assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAfter(interval));
2031     assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAfter(interval));
2032     assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAfter(interval));
2033     assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAfter(interval));
2034     assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAfter(interval));
2035     assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAfter(interval));
2036     assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAfter(interval));
2037     assert(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAfter(interval));
2038 
2039     assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
2040     assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
2041     assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
2042     assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
2043     assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
2044     assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
2045 
2046     assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
2047     assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
2048     assert(!interval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
2049     assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
2050     assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
2051     assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
2052 
2053     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2054     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2055     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2056     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2057     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2058     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2059     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2060     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2061     assert(!interval.isAfter(interval));
2062     assert(!interval.isAfter(cInterval));
2063     assert(!interval.isAfter(iInterval));
2064     assert(!interval.isAfter(posInfInterval));
2065     assert(!interval.isAfter(cPosInfInterval));
2066     assert(!interval.isAfter(iPosInfInterval));
2067     assert(!interval.isAfter(negInfInterval));
2068     assert(!interval.isAfter(cNegInfInterval));
2069     assert(!interval.isAfter(iNegInfInterval));
2070     assert(!cInterval.isAfter(interval));
2071     assert(!cInterval.isAfter(cInterval));
2072     assert(!cInterval.isAfter(iInterval));
2073     assert(!cInterval.isAfter(posInfInterval));
2074     assert(!cInterval.isAfter(cPosInfInterval));
2075     assert(!cInterval.isAfter(iPosInfInterval));
2076     assert(!cInterval.isAfter(negInfInterval));
2077     assert(!cInterval.isAfter(cNegInfInterval));
2078     assert(!cInterval.isAfter(iNegInfInterval));
2079     assert(!iInterval.isAfter(interval));
2080     assert(!iInterval.isAfter(cInterval));
2081     assert(!iInterval.isAfter(iInterval));
2082     assert(!iInterval.isAfter(posInfInterval));
2083     assert(!iInterval.isAfter(cPosInfInterval));
2084     assert(!iInterval.isAfter(iPosInfInterval));
2085     assert(!iInterval.isAfter(negInfInterval));
2086     assert(!iInterval.isAfter(cNegInfInterval));
2087     assert(!iInterval.isAfter(iNegInfInterval));
2088 
2089     // Verify Examples.
2090     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
2091                Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
2092     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
2093                Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
2094     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
2095                Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
2096 
2097     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
2098 
2099     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
2100 }
2101 
2102 // Test Interval's intersects().
2103 @safe unittest
2104 {
2105     import std.datetime.date;
2106 
2107     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2108 
2109     assertThrown!DateTimeException(interval.intersects(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2110     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(interval));
2111     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(
2112                                        Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2113 
2114     assert(interval.intersects(interval));
2115     assert(!interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2116     assert(interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
2117     assert(!interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
2118     assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
2119     assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
2120     assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
2121     assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
2122     assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
2123     assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
2124     assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
2125     assert(!interval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
2126     assert(!interval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2127 
2128     assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersects(interval));
2129     assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersects(interval));
2130     assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersects(interval));
2131     assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersects(interval));
2132     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersects(interval));
2133     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersects(interval));
2134     assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersects(interval));
2135     assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersects(interval));
2136     assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersects(interval));
2137     assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersects(interval));
2138     assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersects(interval));
2139     assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersects(interval));
2140 
2141     assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
2142     assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
2143     assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
2144     assert(interval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
2145     assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
2146     assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
2147 
2148     assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
2149     assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
2150     assert(interval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
2151     assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
2152     assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
2153     assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
2154 
2155     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2156     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2157     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2158     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2159     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2160     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2161     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2162     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2163     assert(interval.intersects(interval));
2164     assert(interval.intersects(cInterval));
2165     assert(interval.intersects(iInterval));
2166     assert(interval.intersects(posInfInterval));
2167     assert(interval.intersects(cPosInfInterval));
2168     assert(interval.intersects(iPosInfInterval));
2169     assert(interval.intersects(negInfInterval));
2170     assert(interval.intersects(cNegInfInterval));
2171     assert(interval.intersects(iNegInfInterval));
2172     assert(cInterval.intersects(interval));
2173     assert(cInterval.intersects(cInterval));
2174     assert(cInterval.intersects(iInterval));
2175     assert(cInterval.intersects(posInfInterval));
2176     assert(cInterval.intersects(cPosInfInterval));
2177     assert(cInterval.intersects(iPosInfInterval));
2178     assert(cInterval.intersects(negInfInterval));
2179     assert(cInterval.intersects(cNegInfInterval));
2180     assert(cInterval.intersects(iNegInfInterval));
2181     assert(iInterval.intersects(interval));
2182     assert(iInterval.intersects(cInterval));
2183     assert(iInterval.intersects(iInterval));
2184     assert(iInterval.intersects(posInfInterval));
2185     assert(iInterval.intersects(cPosInfInterval));
2186     assert(iInterval.intersects(iPosInfInterval));
2187     assert(iInterval.intersects(negInfInterval));
2188     assert(iInterval.intersects(cNegInfInterval));
2189     assert(iInterval.intersects(iNegInfInterval));
2190 
2191     // Verify Examples.
2192     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
2193                Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
2194     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
2195                Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
2196     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
2197                Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
2198 
2199     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
2200     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
2201 
2202     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
2203     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2000, 1, 2))));
2204 }
2205 
2206 // Test Interval's intersection().
2207 @safe unittest
2208 {
2209     import std.datetime.date;
2210 
2211     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2212 
2213     assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2214     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(interval));
2215     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(
2216                                        Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2217 
2218     assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2219     assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
2220     assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
2221     assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2222 
2223     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersection(interval));
2224     assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersection(interval));
2225     assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersection(interval));
2226     assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersection(interval));
2227 
2228     assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 7))));
2229     assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 8))));
2230 
2231     assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 3))));
2232     assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 4))));
2233 
2234     assert(interval.intersection(interval) == interval);
2235     assert(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
2236            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2237     assert(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
2238            Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
2239     assert(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
2240            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2241     assert(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
2242            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2243     assert(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
2244            Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
2245     assert(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
2246            Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
2247     assert(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
2248            Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2249     assert(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
2250            Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2251 
2252     assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersection(interval) ==
2253            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2254     assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersection(interval) ==
2255            Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
2256     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersection(interval) ==
2257            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2258     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersection(interval) ==
2259            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2260     assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersection(interval) ==
2261            Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
2262     assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersection(interval) ==
2263            Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
2264     assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersection(interval) ==
2265            Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2266     assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersection(interval) ==
2267            Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2268 
2269     assert(interval.intersection(PosInfInterval!Date(Date(2010, 7, 3))) ==
2270            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2271     assert(interval.intersection(PosInfInterval!Date(Date(2010, 7, 4))) ==
2272            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2273     assert(interval.intersection(PosInfInterval!Date(Date(2010, 7, 5))) ==
2274            Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
2275     assert(interval.intersection(PosInfInterval!Date(Date(2012, 1, 6))) ==
2276            Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
2277 
2278     assert(interval.intersection(NegInfInterval!Date(Date(2010, 7, 5))) ==
2279            Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
2280     assert(interval.intersection(NegInfInterval!Date(Date(2012, 1, 6))) ==
2281            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 6)));
2282     assert(interval.intersection(NegInfInterval!Date(Date(2012, 1, 7))) ==
2283            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2284     assert(interval.intersection(NegInfInterval!Date(Date(2012, 1, 8))) ==
2285            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2286 
2287     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2288     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2289     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2290     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2291     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2292     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2293     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2294     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2295     assert(!interval.intersection(interval).empty);
2296     assert(!interval.intersection(cInterval).empty);
2297     assert(!interval.intersection(iInterval).empty);
2298     assert(!interval.intersection(posInfInterval).empty);
2299     assert(!interval.intersection(cPosInfInterval).empty);
2300     assert(!interval.intersection(iPosInfInterval).empty);
2301     assert(!interval.intersection(negInfInterval).empty);
2302     assert(!interval.intersection(cNegInfInterval).empty);
2303     assert(!interval.intersection(iNegInfInterval).empty);
2304     assert(!cInterval.intersection(interval).empty);
2305     assert(!cInterval.intersection(cInterval).empty);
2306     assert(!cInterval.intersection(iInterval).empty);
2307     assert(!cInterval.intersection(posInfInterval).empty);
2308     assert(!cInterval.intersection(cPosInfInterval).empty);
2309     assert(!cInterval.intersection(iPosInfInterval).empty);
2310     assert(!cInterval.intersection(negInfInterval).empty);
2311     assert(!cInterval.intersection(cNegInfInterval).empty);
2312     assert(!cInterval.intersection(iNegInfInterval).empty);
2313     assert(!iInterval.intersection(interval).empty);
2314     assert(!iInterval.intersection(cInterval).empty);
2315     assert(!iInterval.intersection(iInterval).empty);
2316     assert(!iInterval.intersection(posInfInterval).empty);
2317     assert(!iInterval.intersection(cPosInfInterval).empty);
2318     assert(!iInterval.intersection(iPosInfInterval).empty);
2319     assert(!iInterval.intersection(negInfInterval).empty);
2320     assert(!iInterval.intersection(cNegInfInterval).empty);
2321     assert(!iInterval.intersection(iNegInfInterval).empty);
2322 
2323     // Verify Examples.
2324     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2325                Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
2326            Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
2327     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2328                Interval!Date(Date(1999, 1, 12),Date(2011, 9, 17))) ==
2329            Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
2330 
2331     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2332                PosInfInterval!Date(Date(1990, 7, 6))) ==
2333            Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
2334     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2335                PosInfInterval!Date(Date(1999, 1, 12))) ==
2336            Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
2337 
2338     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2339                NegInfInterval!Date(Date(1999, 7, 6))) ==
2340            Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
2341     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
2342                NegInfInterval!Date(Date(2013, 1, 12))) ==
2343            Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
2344 }
2345 
2346 // Test Interval's isAdjacent().
2347 @safe unittest
2348 {
2349     import std.datetime.date;
2350 
2351     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2352 
2353     static void testInterval(in Interval!Date interval1, in Interval!Date interval2)
2354     {
2355         interval1.isAdjacent(interval2);
2356     }
2357 
2358     assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2359     assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
2360     assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),
2361                                                 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2362 
2363     assert(!interval.isAdjacent(interval));
2364     assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2365     assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
2366     assert(interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
2367     assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
2368     assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
2369     assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
2370     assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
2371     assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
2372     assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
2373     assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
2374     assert(interval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
2375     assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2376 
2377     assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAdjacent(interval));
2378     assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAdjacent(interval));
2379     assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAdjacent(interval));
2380     assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAdjacent(interval));
2381     assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAdjacent(interval));
2382     assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAdjacent(interval));
2383     assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAdjacent(interval));
2384     assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAdjacent(interval));
2385     assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAdjacent(interval));
2386     assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAdjacent(interval));
2387     assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAdjacent(interval));
2388     assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAdjacent(interval));
2389 
2390     assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
2391     assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
2392     assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
2393     assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
2394     assert(interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
2395     assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
2396 
2397     assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
2398     assert(interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
2399     assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
2400     assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
2401     assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
2402     assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
2403 
2404     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2405     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2406     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2407     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2408     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2409     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2410     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2411     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2412     assert(!interval.isAdjacent(interval));
2413     assert(!interval.isAdjacent(cInterval));
2414     assert(!interval.isAdjacent(iInterval));
2415     assert(!interval.isAdjacent(posInfInterval));
2416     assert(!interval.isAdjacent(cPosInfInterval));
2417     assert(!interval.isAdjacent(iPosInfInterval));
2418     assert(!interval.isAdjacent(negInfInterval));
2419     assert(!interval.isAdjacent(cNegInfInterval));
2420     assert(!interval.isAdjacent(iNegInfInterval));
2421     assert(!cInterval.isAdjacent(interval));
2422     assert(!cInterval.isAdjacent(cInterval));
2423     assert(!cInterval.isAdjacent(iInterval));
2424     assert(!cInterval.isAdjacent(posInfInterval));
2425     assert(!cInterval.isAdjacent(cPosInfInterval));
2426     assert(!cInterval.isAdjacent(iPosInfInterval));
2427     assert(!cInterval.isAdjacent(negInfInterval));
2428     assert(!cInterval.isAdjacent(cNegInfInterval));
2429     assert(!cInterval.isAdjacent(iNegInfInterval));
2430     assert(!iInterval.isAdjacent(interval));
2431     assert(!iInterval.isAdjacent(cInterval));
2432     assert(!iInterval.isAdjacent(iInterval));
2433     assert(!iInterval.isAdjacent(posInfInterval));
2434     assert(!iInterval.isAdjacent(cPosInfInterval));
2435     assert(!iInterval.isAdjacent(iPosInfInterval));
2436     assert(!iInterval.isAdjacent(negInfInterval));
2437     assert(!iInterval.isAdjacent(cNegInfInterval));
2438     assert(!iInterval.isAdjacent(iNegInfInterval));
2439 
2440     // Verify Examples.
2441     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
2442                Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
2443     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
2444                Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
2445     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
2446                Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
2447 
2448     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
2449     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
2450 
2451     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
2452     assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)) .isAdjacent(NegInfInterval!Date(Date(2000, 1, 2))));
2453 }
2454 
2455 // Test Interval's merge().
2456 @safe unittest
2457 {
2458     import std.datetime.date;
2459 
2460     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2461 
testInterval(I)2462     static void testInterval(I)(in Interval!Date interval1, in I interval2)
2463     {
2464         interval1.merge(interval2);
2465     }
2466 
2467     assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2468     assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
2469     assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),
2470                                                 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2471 
2472     assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
2473     assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
2474 
2475     assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)), interval));
2476     assertThrown!DateTimeException(testInterval(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)), interval));
2477 
2478     assertThrown!DateTimeException(testInterval(interval, PosInfInterval!Date(Date(2012, 1, 8))));
2479 
2480     assertThrown!DateTimeException(testInterval(interval, NegInfInterval!Date(Date(2010, 7, 3))));
2481 
2482     assert(interval.merge(interval) == interval);
2483     assert(interval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
2484            Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
2485     assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
2486            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2487     assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
2488            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2489     assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
2490            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2491     assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
2492            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
2493     assert(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
2494            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2495     assert(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
2496            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2497     assert(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
2498            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2499     assert(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
2500            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2501     assert(interval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
2502            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2503 
2504     assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).merge(interval) ==
2505            Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
2506     assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).merge(interval) ==
2507            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2508     assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).merge(interval) ==
2509            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2510     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).merge(interval) ==
2511            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2512     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).merge(interval) ==
2513            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
2514     assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).merge(interval) ==
2515            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2516     assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).merge(interval) ==
2517            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2518     assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).merge(interval) ==
2519            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2520     assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).merge(interval) ==
2521            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2522     assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).merge(interval) ==
2523            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2524 
2525     assert(interval.merge(PosInfInterval!Date(Date(2010, 7, 3))) ==
2526            PosInfInterval!Date(Date(2010, 7, 3)));
2527     assert(interval.merge(PosInfInterval!Date(Date(2010, 7, 4))) ==
2528            PosInfInterval!Date(Date(2010, 7, 4)));
2529     assert(interval.merge(PosInfInterval!Date(Date(2010, 7, 5))) ==
2530            PosInfInterval!Date(Date(2010, 7, 4)));
2531     assert(interval.merge(PosInfInterval!Date(Date(2012, 1, 6))) ==
2532            PosInfInterval!Date(Date(2010, 7, 4)));
2533     assert(interval.merge(PosInfInterval!Date(Date(2012, 1, 7))) ==
2534            PosInfInterval!Date(Date(2010, 7, 4)));
2535 
2536     assert(interval.merge(NegInfInterval!Date(Date(2010, 7, 4))) ==
2537            NegInfInterval!Date(Date(2012, 1, 7)));
2538     assert(interval.merge(NegInfInterval!Date(Date(2010, 7, 5))) ==
2539            NegInfInterval!Date(Date(2012, 1, 7)));
2540     assert(interval.merge(NegInfInterval!Date(Date(2012, 1, 6))) ==
2541            NegInfInterval!Date(Date(2012, 1, 7)));
2542     assert(interval.merge(NegInfInterval!Date(Date(2012, 1, 7))) ==
2543            NegInfInterval!Date(Date(2012, 1, 7)));
2544     assert(interval.merge(NegInfInterval!Date(Date(2012, 1, 8))) ==
2545            NegInfInterval!Date(Date(2012, 1, 8)));
2546 
2547     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2548     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2549     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2550     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2551     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2552     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2553     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2554     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2555     assert(!interval.merge(interval).empty);
2556     assert(!interval.merge(cInterval).empty);
2557     assert(!interval.merge(iInterval).empty);
2558     assert(!interval.merge(posInfInterval).empty);
2559     assert(!interval.merge(cPosInfInterval).empty);
2560     assert(!interval.merge(iPosInfInterval).empty);
2561     assert(!interval.merge(negInfInterval).empty);
2562     assert(!interval.merge(cNegInfInterval).empty);
2563     assert(!interval.merge(iNegInfInterval).empty);
2564     assert(!cInterval.merge(interval).empty);
2565     assert(!cInterval.merge(cInterval).empty);
2566     assert(!cInterval.merge(iInterval).empty);
2567     assert(!cInterval.merge(posInfInterval).empty);
2568     assert(!cInterval.merge(cPosInfInterval).empty);
2569     assert(!cInterval.merge(iPosInfInterval).empty);
2570     assert(!cInterval.merge(negInfInterval).empty);
2571     assert(!cInterval.merge(cNegInfInterval).empty);
2572     assert(!cInterval.merge(iNegInfInterval).empty);
2573     assert(!iInterval.merge(interval).empty);
2574     assert(!iInterval.merge(cInterval).empty);
2575     assert(!iInterval.merge(iInterval).empty);
2576     assert(!iInterval.merge(posInfInterval).empty);
2577     assert(!iInterval.merge(cPosInfInterval).empty);
2578     assert(!iInterval.merge(iPosInfInterval).empty);
2579     assert(!iInterval.merge(negInfInterval).empty);
2580     assert(!iInterval.merge(cNegInfInterval).empty);
2581     assert(!iInterval.merge(iNegInfInterval).empty);
2582 
2583     // Verify Examples.
2584     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
2585            Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
2586     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
2587            Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
2588 
2589     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(1990, 7, 6))) ==
2590            PosInfInterval!Date(Date(1990, 7 , 6)));
2591     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(2012, 3, 1))) ==
2592            PosInfInterval!Date(Date(1996, 1 , 2)));
2593 
2594     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1996, 1, 2))) ==
2595            NegInfInterval!Date(Date(2012, 3 , 1)));
2596     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) ==
2597            NegInfInterval!Date(Date(2013, 1 , 12)));
2598 }
2599 
2600 // Test Interval's span().
2601 @safe unittest
2602 {
2603     import std.datetime.date;
2604 
2605     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2606 
2607     static void testInterval(in Interval!Date interval1, in Interval!Date interval2)
2608     {
2609         interval1.span(interval2);
2610     }
2611 
2612     assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2613     assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),interval));
2614     assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),
2615                                                 Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2616 
2617     assert(interval.span(interval) == interval);
2618     assert(interval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
2619            Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
2620     assert(interval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
2621            Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
2622     assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
2623            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2624     assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
2625            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2626     assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
2627            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2628     assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
2629            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
2630     assert(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
2631            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2632     assert(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
2633            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2634     assert(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
2635            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2636     assert(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
2637            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2638     assert(interval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
2639            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2640     assert(interval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
2641            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
2642 
2643     assert(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).span(interval) ==
2644            Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
2645     assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).span(interval) ==
2646            Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
2647     assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).span(interval) ==
2648            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2649     assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).span(interval) ==
2650            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2651     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).span(interval) ==
2652            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
2653     assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).span(interval) ==
2654            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
2655     assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).span(interval) ==
2656            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2657     assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).span(interval) ==
2658            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2659     assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).span(interval) ==
2660            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
2661     assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).span(interval) ==
2662            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2663     assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).span(interval) ==
2664            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
2665     assert(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).span(interval) ==
2666            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
2667 
2668     assert(interval.span(PosInfInterval!Date(Date(2010, 7, 3))) == PosInfInterval!Date(Date(2010, 7, 3)));
2669     assert(interval.span(PosInfInterval!Date(Date(2010, 7, 4))) == PosInfInterval!Date(Date(2010, 7, 4)));
2670     assert(interval.span(PosInfInterval!Date(Date(2010, 7, 5))) == PosInfInterval!Date(Date(2010, 7, 4)));
2671     assert(interval.span(PosInfInterval!Date(Date(2012, 1, 6))) == PosInfInterval!Date(Date(2010, 7, 4)));
2672     assert(interval.span(PosInfInterval!Date(Date(2012, 1, 7))) == PosInfInterval!Date(Date(2010, 7, 4)));
2673     assert(interval.span(PosInfInterval!Date(Date(2012, 1, 8))) == PosInfInterval!Date(Date(2010, 7, 4)));
2674 
2675     assert(interval.span(NegInfInterval!Date(Date(2010, 7, 3))) == NegInfInterval!Date(Date(2012, 1, 7)));
2676     assert(interval.span(NegInfInterval!Date(Date(2010, 7, 4))) == NegInfInterval!Date(Date(2012, 1, 7)));
2677     assert(interval.span(NegInfInterval!Date(Date(2010, 7, 5))) == NegInfInterval!Date(Date(2012, 1, 7)));
2678     assert(interval.span(NegInfInterval!Date(Date(2012, 1, 6))) == NegInfInterval!Date(Date(2012, 1, 7)));
2679     assert(interval.span(NegInfInterval!Date(Date(2012, 1, 7))) == NegInfInterval!Date(Date(2012, 1, 7)));
2680     assert(interval.span(NegInfInterval!Date(Date(2012, 1, 8))) == NegInfInterval!Date(Date(2012, 1, 8)));
2681 
2682     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2683     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2684     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2685     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2686     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
2687     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2688     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2689     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
2690     assert(!interval.span(interval).empty);
2691     assert(!interval.span(cInterval).empty);
2692     assert(!interval.span(iInterval).empty);
2693     assert(!interval.span(posInfInterval).empty);
2694     assert(!interval.span(cPosInfInterval).empty);
2695     assert(!interval.span(iPosInfInterval).empty);
2696     assert(!interval.span(negInfInterval).empty);
2697     assert(!interval.span(cNegInfInterval).empty);
2698     assert(!interval.span(iNegInfInterval).empty);
2699     assert(!cInterval.span(interval).empty);
2700     assert(!cInterval.span(cInterval).empty);
2701     assert(!cInterval.span(iInterval).empty);
2702     assert(!cInterval.span(posInfInterval).empty);
2703     assert(!cInterval.span(cPosInfInterval).empty);
2704     assert(!cInterval.span(iPosInfInterval).empty);
2705     assert(!cInterval.span(negInfInterval).empty);
2706     assert(!cInterval.span(cNegInfInterval).empty);
2707     assert(!cInterval.span(iNegInfInterval).empty);
2708     assert(!iInterval.span(interval).empty);
2709     assert(!iInterval.span(cInterval).empty);
2710     assert(!iInterval.span(iInterval).empty);
2711     assert(!iInterval.span(posInfInterval).empty);
2712     assert(!iInterval.span(cPosInfInterval).empty);
2713     assert(!iInterval.span(iPosInfInterval).empty);
2714     assert(!iInterval.span(negInfInterval).empty);
2715     assert(!iInterval.span(cNegInfInterval).empty);
2716     assert(!iInterval.span(iNegInfInterval).empty);
2717 
2718     // Verify Examples.
2719     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) ==
2720            Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
2721     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
2722            Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
2723 
2724     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(1990, 7, 6))) ==
2725            PosInfInterval!Date(Date(1990, 7 , 6)));
2726     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(2050, 1, 1))) ==
2727            PosInfInterval!Date(Date(1996, 1 , 2)));
2728 
2729     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1602, 5, 21))) ==
2730            NegInfInterval!Date(Date(2012, 3 , 1)));
2731     assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) ==
2732            NegInfInterval!Date(Date(2013, 1 , 12)));
2733 }
2734 
2735 // Test Interval's shift(duration).
2736 @safe unittest
2737 {
2738     import std.datetime.date;
2739 
2740     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2741 
2742     static void testIntervalFail(Interval!Date interval, in Duration duration)
2743     {
2744         interval.shift(duration);
2745     }
2746 
2747     assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
2748 
testInterval(I)2749     static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
2750     {
2751         interval.shift(duration);
2752         assert(interval == expected);
2753     }
2754 
2755     testInterval(interval, dur!"days"(22), Interval!Date(Date(2010, 7, 26), Date(2012, 1, 29)));
2756     testInterval(interval, dur!"days"(-22), Interval!Date(Date(2010, 6, 12), Date(2011, 12, 16)));
2757 
2758     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2759     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2760     static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
2761     static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
2762 
2763     // Verify Examples.
2764     auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
2765     auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
2766 
2767     interval1.shift(dur!"days"(50));
2768     assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
2769 
2770     interval2.shift(dur!"days"(-50));
2771     assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
2772 }
2773 
2774 // Test Interval's shift(int, int, AllowDayOverflow).
2775 @safe unittest
2776 {
2777     import std.datetime.date;
2778 
2779     {
2780         auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2781 
2782         static void testIntervalFail(Interval!Date interval, int years, int months)
2783         {
2784             interval.shift(years, months);
2785         }
2786 
2787         assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
2788 
testInterval(I)2789         static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
2790                                     in I expected, size_t line = __LINE__)
2791         {
2792             interval.shift(years, months, allow);
2793             assert(interval == expected);
2794         }
2795 
2796         testInterval(interval, 5, 0, AllowDayOverflow.yes, Interval!Date(Date(2015, 7, 4), Date(2017, 1, 7)));
2797         testInterval(interval, -5, 0, AllowDayOverflow.yes, Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
2798 
2799         auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
2800 
2801         testInterval(interval2, 1, 1, AllowDayOverflow.yes, Interval!Date(Date(2001, 3, 1), Date(2011, 7, 1)));
2802         testInterval(interval2, 1, -1, AllowDayOverflow.yes, Interval!Date(Date(2000, 12, 29), Date(2011, 5, 1)));
2803         testInterval(interval2, -1, -1, AllowDayOverflow.yes, Interval!Date(Date(1998, 12, 29), Date(2009, 5, 1)));
2804         testInterval(interval2, -1, 1, AllowDayOverflow.yes, Interval!Date(Date(1999, 3, 1), Date(2009, 7, 1)));
2805 
2806         testInterval(interval2, 1, 1, AllowDayOverflow.no, Interval!Date(Date(2001, 2, 28), Date(2011, 6, 30)));
2807         testInterval(interval2, 1, -1, AllowDayOverflow.no, Interval!Date(Date(2000, 12, 29), Date(2011, 4, 30)));
2808         testInterval(interval2, -1, -1, AllowDayOverflow.no, Interval!Date(Date(1998, 12, 29), Date(2009, 4, 30)));
2809         testInterval(interval2, -1, 1, AllowDayOverflow.no, Interval!Date(Date(1999, 2, 28), Date(2009, 6, 30)));
2810     }
2811 
2812     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2813     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2814     static assert(!__traits(compiles, cInterval.shift(5)));
2815     static assert(!__traits(compiles, iInterval.shift(5)));
2816 
2817     // Verify Examples.
2818     auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2819     auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2820 
2821     interval1.shift(2);
2822     assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
2823 
2824     interval2.shift(-2);
2825     assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
2826 }
2827 
2828 // Test Interval's expand(Duration).
2829 @safe unittest
2830 {
2831     import std.datetime.date;
2832 
2833     auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
2834 
testIntervalFail(I)2835     static void testIntervalFail(I)(I interval, in Duration duration)
2836     {
2837         interval.expand(duration);
2838     }
2839 
2840     assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
2841     assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)), dur!"days"(-5)));
2842 
testInterval(I)2843     static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
2844     {
2845         interval.expand(duration);
2846         assert(interval == expected);
2847     }
2848 
2849     testInterval(interval, dur!"days"(22), Interval!Date(Date(2000, 6, 12), Date(2012, 1, 29)));
2850     testInterval(interval, dur!"days"(-22), Interval!Date(Date(2000, 7, 26), Date(2011, 12, 16)));
2851 
2852     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2853     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2854     static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
2855     static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
2856 
2857     // Verify Examples.
2858     auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2859     auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2860 
2861     interval1.expand(dur!"days"(2));
2862     assert(interval1 == Interval!Date(Date(1995, 12, 31), Date(2012, 3, 3)));
2863 
2864     interval2.expand(dur!"days"(-2));
2865     assert(interval2 == Interval!Date(Date(1996, 1, 4), Date(2012, 2, 28)));
2866 }
2867 
2868 // Test Interval's expand(int, int, AllowDayOverflow, Direction)
2869 @safe unittest
2870 {
2871     import std.datetime.date;
2872 
2873     {
2874         auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
2875 
2876         static void testIntervalFail(Interval!Date interval, int years, int months)
2877         {
2878             interval.expand(years, months);
2879         }
2880 
2881         assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
2882         assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)), -5, 0));
2883 
testInterval(I)2884         static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, Direction dir,
2885                                     in I expected, size_t line = __LINE__)
2886         {
2887             interval.expand(years, months, allow, dir);
2888             assert(interval == expected);
2889         }
2890 
2891         testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.both,
2892                      Interval!Date(Date(1995, 7, 4), Date(2017, 1, 7)));
2893         testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.both,
2894                      Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
2895 
2896         testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.fwd,
2897                      Interval!Date(Date(2000, 7, 4), Date(2017, 1, 7)));
2898         testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.fwd,
2899                      Interval!Date(Date(2000, 7, 4), Date(2007, 1, 7)));
2900 
2901         testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.bwd,
2902                      Interval!Date(Date(1995, 7, 4), Date(2012, 1, 7)));
2903         testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.bwd,
2904                      Interval!Date(Date(2005, 7, 4), Date(2012, 1, 7)));
2905 
2906         auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
2907 
2908         testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.both,
2909                      Interval!Date(Date(1998, 12, 29), Date(2011, 7, 1)));
2910         testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.both,
2911                      Interval!Date(Date(1999, 3, 1), Date(2011, 5, 1)));
2912         testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.both,
2913                      Interval!Date(Date(2001, 3, 1), Date(2009, 5, 1)));
2914         testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.both,
2915                      Interval!Date(Date(2000, 12, 29), Date(2009, 7, 1)));
2916 
2917         testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.both,
2918                      Interval!Date(Date(1998, 12, 29), Date(2011, 6, 30)));
2919         testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.both,
2920                      Interval!Date(Date(1999, 2, 28), Date(2011, 4, 30)));
2921         testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.both,
2922                      Interval!Date(Date(2001, 2, 28), Date(2009, 4, 30)));
2923         testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.both,
2924                      Interval!Date(Date(2000, 12, 29), Date(2009, 6, 30)));
2925 
2926         testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.fwd,
2927                      Interval!Date(Date(2000, 1, 29), Date(2011, 7, 1)));
2928         testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.fwd,
2929                      Interval!Date(Date(2000, 1, 29), Date(2011, 5, 1)));
2930         testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.fwd,
2931                      Interval!Date(Date(2000, 1, 29), Date(2009, 5, 1)));
2932         testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.fwd,
2933                      Interval!Date(Date(2000, 1, 29), Date(2009, 7, 1)));
2934 
2935         testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.fwd,
2936                      Interval!Date(Date(2000, 1, 29), Date(2011, 6, 30)));
2937         testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.fwd,
2938                      Interval!Date(Date(2000, 1, 29), Date(2011, 4, 30)));
2939         testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.fwd,
2940                      Interval!Date(Date(2000, 1, 29), Date(2009, 4, 30)));
2941         testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.fwd,
2942                      Interval!Date(Date(2000, 1, 29), Date(2009, 6, 30)));
2943 
2944         testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.bwd,
2945                      Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
2946         testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.bwd,
2947                      Interval!Date(Date(1999, 3, 1), Date(2010, 5, 31)));
2948         testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.bwd,
2949                      Interval!Date(Date(2001, 3, 1), Date(2010, 5, 31)));
2950         testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.bwd,
2951                      Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
2952 
2953         testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.bwd,
2954                      Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
2955         testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.bwd,
2956                      Interval!Date(Date(1999, 2, 28), Date(2010, 5, 31)));
2957         testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.bwd,
2958                      Interval!Date(Date(2001, 2, 28), Date(2010, 5, 31)));
2959         testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.bwd,
2960                      Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
2961     }
2962 
2963     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2964     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
2965     static assert(!__traits(compiles, cInterval.expand(5)));
2966     static assert(!__traits(compiles, iInterval.expand(5)));
2967 
2968     // Verify Examples.
2969     auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2970     auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
2971 
2972     interval1.expand(2);
2973     assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
2974 
2975     interval2.expand(-2);
2976     assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
2977 }
2978 
2979 // Test Interval's fwdRange.
2980 @system unittest
2981 {
2982     import std.datetime.date;
2983 
2984     {
2985         auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
2986 
2987         static void testInterval1(Interval!Date interval)
2988         {
2989             interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
2990         }
2991 
2992         assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
2993 
2994         static void testInterval2(Interval!Date interval)
2995         {
2996             interval.fwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).popFront();
2997         }
2998 
2999         assertThrown!DateTimeException(testInterval2(interval));
3000 
3001         assert(!interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3002         assert(interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).empty);
3003 
3004         assert(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).front ==
3005                Date(2010, 9, 12));
3006 
3007         assert(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(
3008                    everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).front == Date(2010, 9, 17));
3009     }
3010 
3011     // Verify Examples.
3012     {
3013         auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
delegate(in Date date)3014         auto func = delegate (in Date date)
3015                     {
3016                         if ((date.day & 1) == 0)
3017                             return date + dur!"days"(2);
3018                         return date + dur!"days"(1);
3019                     };
3020         auto range = interval.fwdRange(func);
3021 
3022         // An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
3023         assert(range.front == Date(2010, 9, 1));
3024 
3025         range.popFront();
3026         assert(range.front == Date(2010, 9, 2));
3027 
3028         range.popFront();
3029         assert(range.front == Date(2010, 9, 4));
3030 
3031         range.popFront();
3032         assert(range.front == Date(2010, 9, 6));
3033 
3034         range.popFront();
3035         assert(range.front == Date(2010, 9, 8));
3036 
3037         range.popFront();
3038         assert(range.empty);
3039     }
3040 
3041     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3042     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3043     assert(!cInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3044     assert(!iInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3045 }
3046 
3047 // Test Interval's bwdRange.
3048 @system unittest
3049 {
3050     import std.datetime.date;
3051 
3052     {
3053         auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
3054 
3055         static void testInterval1(Interval!Date interval)
3056         {
3057             interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
3058         }
3059 
3060         assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
3061 
3062         static void testInterval2(Interval!Date interval)
3063         {
3064             interval.bwdRange(everyDayOfWeek!(Date, Direction.fwd)(DayOfWeek.fri)).popFront();
3065         }
3066 
3067         assertThrown!DateTimeException(testInterval2(interval));
3068 
3069         assert(!interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).empty);
3070         assert(interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).empty);
3071 
3072         assert(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(
3073                    everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).front == Date(2010, 10, 1));
3074 
3075         assert(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(
3076                    everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).front == Date(2010, 9, 24));
3077     }
3078 
3079     // Verify Examples.
3080     {
3081         auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
delegate(in Date date)3082         auto func = delegate (in Date date)
3083                     {
3084                         if ((date.day & 1) == 0)
3085                             return date - dur!"days"(2);
3086                         return date - dur!"days"(1);
3087                     };
3088         auto range = interval.bwdRange(func);
3089 
3090         // An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
3091         assert(range.front == Date(2010, 9, 9));
3092 
3093         range.popFront();
3094         assert(range.front == Date(2010, 9, 8));
3095 
3096         range.popFront();
3097         assert(range.front == Date(2010, 9, 6));
3098 
3099         range.popFront();
3100         assert(range.front == Date(2010, 9, 4));
3101 
3102         range.popFront();
3103         assert(range.front == Date(2010, 9, 2));
3104 
3105         range.popFront();
3106         assert(range.empty);
3107     }
3108 
3109     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3110     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3111     assert(!cInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3112     assert(!iInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
3113 }
3114 
3115 // Test Interval's toString().
3116 @safe unittest
3117 {
3118     import std.datetime.date;
3119 
3120     assert(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).toString() == "[2010-Jul-04 - 2012-Jan-07)");
3121 
3122     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3123     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
3124     assert(cInterval.toString());
3125     assert(iInterval.toString());
3126 }
3127 
3128 
3129 /++
3130     Represents an interval of time which has positive infinity as its end point.
3131 
3132     Any ranges which iterate over a $(D PosInfInterval) are infinite. So, the
3133     main purpose of using $(D PosInfInterval) is to create an infinite range
3134     which starts at a fixed point in time and goes to positive infinity.
3135   +/
PosInfInterval(TP)3136 struct PosInfInterval(TP)
3137 {
3138 public:
3139 
3140     /++
3141         Params:
3142             begin = The time point which begins the interval.
3143 
3144         Example:
3145 --------------------
3146 auto interval = PosInfInterval!Date(Date(1996, 1, 2));
3147 --------------------
3148       +/
3149     this(in TP begin) pure nothrow
3150     {
3151         _begin = cast(TP) begin;
3152     }
3153 
3154 
3155     /++
3156         Params:
3157             rhs = The $(D PosInfInterval) to assign to this one.
3158       +/
3159     ref PosInfInterval opAssign(const ref PosInfInterval rhs) pure nothrow
3160     {
3161         _begin = cast(TP) rhs._begin;
3162         return this;
3163     }
3164 
3165 
3166     /++
3167         Params:
3168             rhs = The $(D PosInfInterval) to assign to this one.
3169       +/
3170     ref PosInfInterval opAssign(PosInfInterval rhs) pure nothrow
3171     {
3172         _begin = cast(TP) rhs._begin;
3173         return this;
3174     }
3175 
3176 
3177     /++
3178         The starting point of the interval. It is included in the interval.
3179 
3180         Example:
3181 --------------------
3182 assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
3183 --------------------
3184       +/
3185     @property TP begin() const pure nothrow
3186     {
3187         return cast(TP)_begin;
3188     }
3189 
3190 
3191     /++
3192         The starting point of the interval. It is included in the interval.
3193 
3194         Params:
3195             timePoint = The time point to set $(D begin) to.
3196       +/
3197     @property void begin(TP timePoint) pure nothrow
3198     {
3199         _begin = timePoint;
3200     }
3201 
3202 
3203     /++
3204         Whether the interval's length is 0. Always returns false.
3205 
3206         Example:
3207 --------------------
3208 assert(!PosInfInterval!Date(Date(1996, 1, 2)).empty);
3209 --------------------
3210       +/
3211     enum bool empty = false;
3212 
3213 
3214     /++
3215         Whether the given time point is within this interval.
3216 
3217         Params:
3218             timePoint = The time point to check for inclusion in this interval.
3219 
3220         Example:
3221 --------------------
3222 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(1994, 12, 24)));
3223 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(2000, 1, 5)));
3224 --------------------
3225       +/
3226     bool contains(TP timePoint) const pure nothrow
3227     {
3228         return timePoint >= _begin;
3229     }
3230 
3231 
3232     /++
3233         Whether the given interval is completely within this interval.
3234 
3235         Params:
3236             interval = The interval to check for inclusion in this interval.
3237 
3238         Throws:
3239             $(REF DateTimeException,std,datetime,date) if the given interval
3240             is empty.
3241 
3242         Example:
3243 --------------------
3244 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
3245             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
3246 
3247 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
3248             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3249 
3250 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
3251             Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
3252 --------------------
3253       +/
3254     bool contains(in Interval!TP interval) const pure
3255     {
3256         interval._enforceNotEmpty();
3257         return interval._begin >= _begin;
3258     }
3259 
3260 
3261     /++
3262         Whether the given interval is completely within this interval.
3263 
3264         Params:
3265             interval = The interval to check for inclusion in this interval.
3266 
3267         Example:
3268 --------------------
3269 assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
3270             PosInfInterval!Date(Date(1999, 5, 4))));
3271 
3272 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
3273             PosInfInterval!Date(Date(1995, 7, 2))));
3274 --------------------
3275       +/
3276     bool contains(in PosInfInterval interval) const pure nothrow
3277     {
3278         return interval._begin >= _begin;
3279     }
3280 
3281 
3282     /++
3283         Whether the given interval is completely within this interval.
3284 
3285         Always returns false because an interval going to positive infinity
3286         can never contain an interval beginning at negative infinity.
3287 
3288         Params:
3289             interval = The interval to check for inclusion in this interval.
3290 
3291         Example:
3292 --------------------
3293 assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
3294             NegInfInterval!Date(Date(1996, 5, 4))));
3295 --------------------
3296       +/
3297     bool contains(in NegInfInterval!TP interval) const pure nothrow
3298     {
3299         return false;
3300     }
3301 
3302 
3303     /++
3304         Whether this interval is before the given time point.
3305 
3306         Always returns false because an interval going to positive infinity
3307         can never be before any time point.
3308 
3309         Params:
3310             timePoint = The time point to check whether this interval is before
3311                         it.
3312 
3313         Example:
3314 --------------------
3315 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(1994, 12, 24)));
3316 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(2000, 1, 5)));
3317 --------------------
3318       +/
3319     bool isBefore(in TP timePoint) const pure nothrow
3320     {
3321         return false;
3322     }
3323 
3324 
3325     /++
3326         Whether this interval is before the given interval and does not
3327         intersect it.
3328 
3329         Always returns false (unless the given interval is empty) because an
3330         interval going to positive infinity can never be before any other
3331         interval.
3332 
3333         Params:
3334             interval = The interval to check for against this interval.
3335 
3336         Throws:
3337             $(REF DateTimeException,std,datetime,date) if the given interval
3338             is empty.
3339 
3340         Example:
3341 --------------------
3342 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3343             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
3344 
3345 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3346             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3347 --------------------
3348       +/
3349     bool isBefore(in Interval!TP interval) const pure
3350     {
3351         interval._enforceNotEmpty();
3352         return false;
3353     }
3354 
3355 
3356     /++
3357         Whether this interval is before the given interval and does not
3358         intersect it.
3359 
3360         Always returns false because an interval going to positive infinity can
3361         never be before any other interval.
3362 
3363         Params:
3364             interval = The interval to check for against this interval.
3365 
3366         Example:
3367 --------------------
3368 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3369             PosInfInterval!Date(Date(1992, 5, 4))));
3370 
3371 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3372             PosInfInterval!Date(Date(2013, 3, 7))));
3373 --------------------
3374       +/
3375     bool isBefore(in PosInfInterval interval) const pure nothrow
3376     {
3377         return false;
3378     }
3379 
3380 
3381     /++
3382         Whether this interval is before the given interval and does not
3383         intersect it.
3384 
3385         Always returns false because an interval going to positive infinity can
3386         never be before any other interval.
3387 
3388         Params:
3389             interval = The interval to check for against this interval.
3390 
3391         Example:
3392 --------------------
3393 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
3394             NegInfInterval!Date(Date(1996, 5, 4))));
3395 --------------------
3396       +/
3397     bool isBefore(in NegInfInterval!TP interval) const pure nothrow
3398     {
3399         return false;
3400     }
3401 
3402 
3403     /++
3404         Whether this interval is after the given time point.
3405 
3406         Params:
3407             timePoint = The time point to check whether this interval is after
3408                         it.
3409 
3410         Example:
3411 --------------------
3412 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(1994, 12, 24)));
3413 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(2000, 1, 5)));
3414 --------------------
3415       +/
3416     bool isAfter(in TP timePoint) const pure nothrow
3417     {
3418         return timePoint < _begin;
3419     }
3420 
3421 
3422     /++
3423         Whether this interval is after the given interval and does not intersect
3424         it.
3425 
3426         Params:
3427             interval = The interval to check against this interval.
3428 
3429         Throws:
3430             $(REF DateTimeException,std,datetime,date) if the given interval
3431             is empty.
3432 
3433         Example:
3434 --------------------
3435 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3436             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
3437 
3438 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3439             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3440 
3441 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3442             Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
3443 --------------------
3444       +/
3445     bool isAfter(in Interval!TP interval) const pure
3446     {
3447         interval._enforceNotEmpty();
3448         return _begin >= interval._end;
3449     }
3450 
3451 
3452     /++
3453         Whether this interval is after the given interval and does not intersect
3454         it.
3455 
3456         Always returns false because an interval going to positive infinity can
3457         never be after another interval going to positive infinity.
3458 
3459         Params:
3460             interval = The interval to check against this interval.
3461 
3462         Example:
3463 --------------------
3464 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3465             PosInfInterval!Date(Date(1990, 1, 7))));
3466 
3467 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3468             PosInfInterval!Date(Date(1999, 5, 4))));
3469 --------------------
3470       +/
3471     bool isAfter(in PosInfInterval interval) const pure nothrow
3472     {
3473         return false;
3474     }
3475 
3476 
3477     /++
3478         Whether this interval is after the given interval and does not intersect
3479         it.
3480 
3481         Params:
3482             interval = The interval to check against this interval.
3483 
3484         Example:
3485 --------------------
3486 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3487             NegInfInterval!Date(Date(1996, 1, 2))));
3488 
3489 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
3490             NegInfInterval!Date(Date(2000, 7, 1))));
3491 --------------------
3492       +/
3493     bool isAfter(in NegInfInterval!TP interval) const pure nothrow
3494     {
3495         return _begin >= interval._end;
3496     }
3497 
3498 
3499     /++
3500         Whether the given interval overlaps this interval.
3501 
3502         Params:
3503             interval = The interval to check for intersection with this interval.
3504 
3505         Throws:
3506             $(REF DateTimeException,std,datetime,date) if the given interval
3507             is empty.
3508 
3509         Example:
3510 --------------------
3511 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3512             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
3513 
3514 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3515             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3516 
3517 assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3518             Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
3519 --------------------
3520       +/
3521     bool intersects(in Interval!TP interval) const pure
3522     {
3523         interval._enforceNotEmpty();
3524         return interval._end > _begin;
3525     }
3526 
3527 
3528     /++
3529         Whether the given interval overlaps this interval.
3530 
3531         Always returns true because two intervals going to positive infinity
3532         always overlap.
3533 
3534         Params:
3535             interval = The interval to check for intersection with this
3536                        interval.
3537 
3538         Example:
3539 --------------------
3540 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3541             PosInfInterval!Date(Date(1990, 1, 7))));
3542 
3543 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3544             PosInfInterval!Date(Date(1999, 5, 4))));
3545 --------------------
3546       +/
3547     bool intersects(in PosInfInterval interval) const pure nothrow
3548     {
3549         return true;
3550     }
3551 
3552 
3553     /++
3554         Whether the given interval overlaps this interval.
3555 
3556         Params:
3557             interval = The interval to check for intersection with this
3558                        interval.
3559 
3560         Example:
3561 --------------------
3562 assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3563             NegInfInterval!Date(Date(1996, 1, 2))));
3564 
3565 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
3566             NegInfInterval!Date(Date(2000, 7, 1))));
3567 --------------------
3568       +/
3569     bool intersects(in NegInfInterval!TP interval) const pure nothrow
3570     {
3571         return _begin < interval._end;
3572     }
3573 
3574 
3575     /++
3576         Returns the intersection of two intervals
3577 
3578         Params:
3579             interval = The interval to intersect with this interval.
3580 
3581         Throws:
3582             $(REF DateTimeException,std,datetime,date) if the two intervals do
3583             not intersect or if the given interval is empty.
3584 
3585         Example:
3586 --------------------
3587 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3588             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
3589        Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
3590 
3591 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3592             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
3593        Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
3594 --------------------
3595       +/
3596     Interval!TP intersection(in Interval!TP interval) const
3597     {
3598         import std.format : format;
3599 
3600         enforce(this.intersects(interval),
3601                 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
3602 
3603         auto begin = _begin > interval._begin ? _begin : interval._begin;
3604 
3605         return Interval!TP(begin, interval._end);
3606     }
3607 
3608 
3609     /++
3610         Returns the intersection of two intervals
3611 
3612         Params:
3613             interval = The interval to intersect with this interval.
3614 
3615         Example:
3616 --------------------
3617 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3618             PosInfInterval!Date(Date(1990, 7, 6))) ==
3619        PosInfInterval!Date(Date(1996, 1 , 2)));
3620 
3621 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3622             PosInfInterval!Date(Date(1999, 1, 12))) ==
3623        PosInfInterval!Date(Date(1999, 1 , 12)));
3624 --------------------
3625       +/
3626     PosInfInterval intersection(in PosInfInterval interval) const pure nothrow
3627     {
3628         return PosInfInterval(_begin < interval._begin ? interval._begin : _begin);
3629     }
3630 
3631 
3632     /++
3633         Returns the intersection of two intervals
3634 
3635         Params:
3636             interval = The interval to intersect with this interval.
3637 
3638         Throws:
3639             $(REF DateTimeException,std,datetime,date) if the two intervals do
3640             not intersect.
3641 
3642         Example:
3643 --------------------
3644 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3645             NegInfInterval!Date(Date(1999, 7, 6))) ==
3646        Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
3647 
3648 assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
3649             NegInfInterval!Date(Date(2013, 1, 12))) ==
3650        Interval!Date(Date(1996, 1 , 2), Date(2013, 1, 12)));
3651 --------------------
3652       +/
3653     Interval!TP intersection(in NegInfInterval!TP interval) const
3654     {
3655         import std.format : format;
3656 
3657         enforce(this.intersects(interval),
3658                 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
3659 
3660         return Interval!TP(_begin, interval._end);
3661     }
3662 
3663 
3664     /++
3665         Whether the given interval is adjacent to this interval.
3666 
3667         Params:
3668             interval = The interval to check whether its adjecent to this
3669                        interval.
3670 
3671         Throws:
3672             $(REF DateTimeException,std,datetime,date) if the given interval
3673             is empty.
3674 
3675         Example:
3676 --------------------
3677 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3678             Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
3679 
3680 assert(!PosInfInterval!Date(Date(1999, 1, 12)).isAdjacent(
3681             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
3682 --------------------
3683       +/
3684     bool isAdjacent(in Interval!TP interval) const pure
3685     {
3686         interval._enforceNotEmpty();
3687         return _begin == interval._end;
3688     }
3689 
3690 
3691     /++
3692         Whether the given interval is adjacent to this interval.
3693 
3694         Always returns false because two intervals going to positive infinity
3695         can never be adjacent to one another.
3696 
3697         Params:
3698             interval = The interval to check whether its adjecent to this
3699                        interval.
3700 
3701         Example:
3702 --------------------
3703 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3704             PosInfInterval!Date(Date(1990, 1, 7))));
3705 
3706 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3707             PosInfInterval!Date(Date(1996, 1, 2))));
3708 --------------------
3709       +/
3710     bool isAdjacent(in PosInfInterval interval) const pure nothrow
3711     {
3712         return false;
3713     }
3714 
3715 
3716     /++
3717         Whether the given interval is adjacent to this interval.
3718 
3719         Params:
3720             interval = The interval to check whether its adjecent to this
3721                        interval.
3722 
3723         Example:
3724 --------------------
3725 assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3726             NegInfInterval!Date(Date(1996, 1, 2))));
3727 
3728 assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
3729             NegInfInterval!Date(Date(2000, 7, 1))));
3730 --------------------
3731       +/
3732     bool isAdjacent(in NegInfInterval!TP interval) const pure nothrow
3733     {
3734         return _begin == interval._end;
3735     }
3736 
3737 
3738     /++
3739         Returns the union of two intervals
3740 
3741         Params:
3742             interval = The interval to merge with this interval.
3743 
3744         Throws:
3745             $(REF DateTimeException,std,datetime,date) if the two intervals do
3746             not intersect and are not adjacent or if the given interval is
3747             empty.
3748 
3749         Note:
3750             There is no overload for $(D merge) which takes a
3751             $(D NegInfInterval), because an interval
3752             going from negative infinity to positive infinity
3753             is not possible.
3754 
3755         Example:
3756 --------------------
3757 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
3758             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
3759        PosInfInterval!Date(Date(1990, 7 , 6)));
3760 
3761 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
3762             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
3763        PosInfInterval!Date(Date(1996, 1 , 2)));
3764 --------------------
3765       +/
3766     PosInfInterval merge(in Interval!TP interval) const
3767     {
3768         import std.format : format;
3769 
3770         enforce(this.isAdjacent(interval) || this.intersects(interval),
3771                 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
3772 
3773         return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
3774     }
3775 
3776 
3777     /++
3778         Returns the union of two intervals
3779 
3780         Params:
3781             interval = The interval to merge with this interval.
3782 
3783         Note:
3784             There is no overload for $(D merge) which takes a
3785             $(D NegInfInterval), because an interval
3786             going from negative infinity to positive infinity
3787             is not possible.
3788 
3789         Example:
3790 --------------------
3791 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
3792             PosInfInterval!Date(Date(1990, 7, 6))) ==
3793        PosInfInterval!Date(Date(1990, 7 , 6)));
3794 
3795 assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
3796             PosInfInterval!Date(Date(1999, 1, 12))) ==
3797        PosInfInterval!Date(Date(1996, 1 , 2)));
3798 --------------------
3799       +/
3800     PosInfInterval merge(in PosInfInterval interval) const pure nothrow
3801     {
3802         return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
3803     }
3804 
3805 
3806     /++
3807         Returns an interval that covers from the earliest time point of two
3808         intervals up to (but not including) the latest time point of two
3809         intervals.
3810 
3811         Params:
3812             interval = The interval to create a span together with this
3813                        interval.
3814 
3815         Throws:
3816             $(REF DateTimeException,std,datetime,date) if the given interval
3817             is empty.
3818 
3819         Note:
3820             There is no overload for $(D span) which takes a
3821             $(D NegInfInterval), because an interval
3822             going from negative infinity to positive infinity
3823             is not possible.
3824 
3825         Example:
3826 --------------------
3827 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3828             Interval!Date(Date(500, 8, 9), Date(1602, 1, 31))) ==
3829        PosInfInterval!Date(Date(500, 8, 9)));
3830 
3831 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3832             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
3833        PosInfInterval!Date(Date(1990, 7 , 6)));
3834 
3835 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3836             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
3837        PosInfInterval!Date(Date(1996, 1 , 2)));
3838 --------------------
3839       +/
3840     PosInfInterval span(in Interval!TP interval) const pure
3841     {
3842         interval._enforceNotEmpty();
3843         return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
3844     }
3845 
3846 
3847     /++
3848         Returns an interval that covers from the earliest time point of two
3849         intervals up to (but not including) the latest time point of two
3850         intervals.
3851 
3852         Params:
3853             interval = The interval to create a span together with this
3854                        interval.
3855 
3856         Note:
3857             There is no overload for $(D span) which takes a
3858             $(D NegInfInterval), because an interval
3859             going from negative infinity to positive infinity
3860             is not possible.
3861 
3862         Example:
3863 --------------------
3864 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3865             PosInfInterval!Date(Date(1990, 7, 6))) ==
3866        PosInfInterval!Date(Date(1990, 7 , 6)));
3867 
3868 assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
3869             PosInfInterval!Date(Date(1999, 1, 12))) ==
3870        PosInfInterval!Date(Date(1996, 1 , 2)));
3871 --------------------
3872       +/
3873     PosInfInterval span(in PosInfInterval interval) const pure nothrow
3874     {
3875         return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
3876     }
3877 
3878 
3879     /++
3880         Shifts the $(D begin) of this interval forward or backwards in time by
3881         the given duration (a positive duration shifts the interval forward; a
3882         negative duration shifts it backward). Effectively, it does
3883         $(D begin += duration).
3884 
3885         Params:
3886             duration = The duration to shift the interval by.
3887 
3888         Example:
3889 --------------------
3890 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
3891 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
3892 
3893 interval1.shift(dur!"days"(50));
3894 assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
3895 
3896 interval2.shift(dur!"days"(-50));
3897 assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
3898 --------------------
3899       +/
3900     void shift(D)(D duration) pure nothrow
3901         if (__traits(compiles, begin + duration))
3902     {
3903         _begin += duration;
3904     }
3905 
3906 
3907     static if (__traits(compiles, begin.add!"months"(1)) &&
3908                __traits(compiles, begin.add!"years"(1)))
3909     {
3910         /++
3911             Shifts the $(D begin) of this interval forward or backwards in time
3912             by the given number of years and/or months (a positive number of
3913             years and months shifts the interval forward; a negative number
3914             shifts it backward). It adds the years the given years and months to
3915             $(D begin). It effectively calls $(D add!"years"()) and then
3916             $(D add!"months"()) on $(D begin) with the given number of years and
3917             months.
3918 
3919             Params:
3920                 years         = The number of years to shift the interval by.
3921                 months        = The number of months to shift the interval by.
3922                 allowOverflow = Whether the days should be allowed to overflow
3923                                 on $(D begin), causing its month to increment.
3924 
3925             Throws:
3926                 $(REF DateTimeException,std,datetime,date) if this interval is
3927                 empty or if the resulting interval would be invalid.
3928 
3929             Example:
3930 --------------------
3931 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
3932 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
3933 
3934 interval1.shift(dur!"days"(50));
3935 assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
3936 
3937 interval2.shift(dur!"days"(-50));
3938 assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
3939 --------------------
3940           +/
3941         void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
3942             if (isIntegral!T)
3943         {
3944             auto begin = _begin;
3945 
3946             begin.add!"years"(years, allowOverflow);
3947             begin.add!"months"(months, allowOverflow);
3948 
3949             _begin = begin;
3950         }
3951     }
3952 
3953 
3954     /++
3955         Expands the interval backwards in time. Effectively, it does
3956         $(D begin -= duration).
3957 
3958         Params:
3959             duration = The duration to expand the interval by.
3960 
3961         Example:
3962 --------------------
3963 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
3964 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
3965 
3966 interval1.expand(dur!"days"(2));
3967 assert(interval1 == PosInfInterval!Date(Date(1995, 12, 31)));
3968 
3969 interval2.expand(dur!"days"(-2));
3970 assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
3971 --------------------
3972       +/
3973     void expand(D)(D duration) pure nothrow
3974         if (__traits(compiles, begin + duration))
3975     {
3976         _begin -= duration;
3977     }
3978 
3979 
3980     static if (__traits(compiles, begin.add!"months"(1)) &&
3981                __traits(compiles, begin.add!"years"(1)))
3982     {
3983         /++
3984             Expands the interval forwards and/or backwards in time. Effectively,
3985             it subtracts the given number of months/years from $(D begin).
3986 
3987             Params:
3988                 years         = The number of years to expand the interval by.
3989                 months        = The number of months to expand the interval by.
3990                 allowOverflow = Whether the days should be allowed to overflow
3991                                 on $(D begin), causing its month to increment.
3992 
3993             Throws:
3994                 $(REF DateTimeException,std,datetime,date) if this interval is
3995                 empty or if the resulting interval would be invalid.
3996 
3997             Example:
3998 --------------------
3999 auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
4000 auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
4001 
4002 interval1.expand(2);
4003 assert(interval1 == PosInfInterval!Date(Date(1994, 1, 2)));
4004 
4005 interval2.expand(-2);
4006 assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
4007 --------------------
4008           +/
4009         void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
4010             if (isIntegral!T)
4011         {
4012             auto begin = _begin;
4013 
4014             begin.add!"years"(-years, allowOverflow);
4015             begin.add!"months"(-months, allowOverflow);
4016 
4017             _begin = begin;
4018         }
4019     }
4020 
4021 
4022     /++
4023         Returns a range which iterates forward over the interval, starting
4024         at $(D begin), using $(D_PARAM func) to generate each successive time
4025         point.
4026 
4027         The range's $(D front) is the interval's $(D begin). $(D_PARAM func) is
4028         used to generate the next $(D front) when $(D popFront) is called. If
4029         $(D_PARAM popFirst) is $(D PopFirst.yes), then $(D popFront) is called
4030         before the range is returned (so that $(D front) is a time point which
4031         $(D_PARAM func) would generate).
4032 
4033         If $(D_PARAM func) ever generates a time point less than or equal to the
4034         current $(D front) of the range, then a
4035         $(REF DateTimeException,std,datetime,date) will be thrown.
4036 
4037         There are helper functions in this module which generate common
4038         delegates to pass to $(D fwdRange). Their documentation starts with
4039         "Range-generating function," to make them easily searchable.
4040 
4041         Params:
4042             func     = The function used to generate the time points of the
4043                        range over the interval.
4044             popFirst = Whether $(D popFront) should be called on the range
4045                        before returning it.
4046 
4047         Throws:
4048             $(REF DateTimeException,std,datetime,date) if this interval is
4049             empty.
4050 
4051         Warning:
4052             $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
4053             would be a function pointer to a pure function, but forcing
4054             $(D_PARAM func) to be pure is far too restrictive to be useful, and
4055             in order to have the ease of use of having functions which generate
4056             functions to pass to $(D fwdRange), $(D_PARAM func) must be a
4057             delegate.
4058 
4059             If $(D_PARAM func) retains state which changes as it is called, then
4060             some algorithms will not work correctly, because the range's
4061             $(D save) will have failed to have really saved the range's state.
4062             To avoid such bugs, don't pass a delegate which is
4063             not logically pure to $(D fwdRange). If $(D_PARAM func) is given the
4064             same time point with two different calls, it must return the same
4065             result both times.
4066 
4067             Of course, none of the functions in this module have this problem,
4068             so it's only relevant for custom delegates.
4069 
4070         Example:
4071 --------------------
4072 auto interval = PosInfInterval!Date(Date(2010, 9, 1));
4073 auto func = delegate (in Date date) //For iterating over even-numbered days.
4074             {
4075                 if ((date.day & 1) == 0)
4076                     return date + dur!"days"(2);
4077 
4078                 return date + dur!"days"(1);
4079             };
4080 auto range = interval.fwdRange(func);
4081 
4082 //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
4083 assert(range.front == Date(2010, 9, 1));
4084 
4085 range.popFront();
4086 assert(range.front == Date(2010, 9, 2));
4087 
4088 range.popFront();
4089 assert(range.front == Date(2010, 9, 4));
4090 
4091 range.popFront();
4092 assert(range.front == Date(2010, 9, 6));
4093 
4094 range.popFront();
4095 assert(range.front == Date(2010, 9, 8));
4096 
4097 range.popFront();
4098 assert(!range.empty);
4099 --------------------
4100       +/
4101     PosInfIntervalRange!(TP) fwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
4102     {
4103         auto range = PosInfIntervalRange!(TP)(this, func);
4104 
4105         if (popFirst == PopFirst.yes)
4106             range.popFront();
4107 
4108         return range;
4109     }
4110 
4111 
4112     /+
4113         Converts this interval to a string.
4114       +/
4115     //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
4116     //have versions of toString() with extra modifiers, so we define one version
4117     //with modifiers and one without.
4118     string toString()
4119     {
4120         return _toStringImpl();
4121     }
4122 
4123 
4124     /++
4125         Converts this interval to a string.
4126       +/
4127     //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
4128     //have versions of toString() with extra modifiers, so we define one version
4129     //with modifiers and one without.
4130     string toString() const nothrow
4131     {
4132         return _toStringImpl();
4133     }
4134 
4135 private:
4136 
4137     /+
4138         Since we have two versions of toString(), we have _toStringImpl()
4139         so that they can share implementations.
4140       +/
4141     string _toStringImpl() const nothrow
4142     {
4143         import std.format : format;
4144         try
4145             return format("[%s - ∞)", _begin);
4146         catch (Exception e)
4147             assert(0, "format() threw.");
4148     }
4149 
4150 
4151     TP _begin;
4152 }
4153 
4154 //Test PosInfInterval's constructor.
4155 @safe unittest
4156 {
4157     import std.datetime.date;
4158     import std.datetime.systime;
4159 
4160     PosInfInterval!Date(Date.init);
4161     PosInfInterval!TimeOfDay(TimeOfDay.init);
4162     PosInfInterval!DateTime(DateTime.init);
4163     PosInfInterval!SysTime(SysTime(0));
4164 
4165     //Verify Examples.
4166     auto interval = PosInfInterval!Date(Date(1996, 1, 2));
4167 }
4168 
4169 //Test PosInfInterval's begin.
4170 @safe unittest
4171 {
4172     import std.datetime.date;
4173 
4174     assert(PosInfInterval!Date(Date(1, 1, 1)).begin == Date(1, 1, 1));
4175     assert(PosInfInterval!Date(Date(2010, 1, 1)).begin == Date(2010, 1, 1));
4176     assert(PosInfInterval!Date(Date(1997, 12, 31)).begin == Date(1997, 12, 31));
4177 
4178     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4179     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4180     assert(cPosInfInterval.begin != Date.init);
4181     assert(iPosInfInterval.begin != Date.init);
4182 
4183     //Verify Examples.
4184     assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
4185 }
4186 
4187 //Test PosInfInterval's empty.
4188 @safe unittest
4189 {
4190     import std.datetime.date;
4191     import std.datetime.systime;
4192 
4193     assert(!PosInfInterval!Date(Date(2010, 1, 1)).empty);
4194     assert(!PosInfInterval!TimeOfDay(TimeOfDay(0, 30, 0)).empty);
4195     assert(!PosInfInterval!DateTime(DateTime(2010, 1, 1, 0, 30, 0)).empty);
4196     assert(!PosInfInterval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0))).empty);
4197 
4198     const cPosInfInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4199     immutable iPosInfInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4200     assert(!cPosInfInterval.empty);
4201     assert(!iPosInfInterval.empty);
4202 
4203     //Verify Examples.
4204     assert(!PosInfInterval!Date(Date(1996, 1, 2)).empty);
4205 }
4206 
4207 //Test PosInfInterval's contains(time point).
4208 @safe unittest
4209 {
4210     import std.datetime.date;
4211 
4212     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4213 
4214     assert(!posInfInterval.contains(Date(2009, 7, 4)));
4215     assert(!posInfInterval.contains(Date(2010, 7, 3)));
4216     assert(posInfInterval.contains(Date(2010, 7, 4)));
4217     assert(posInfInterval.contains(Date(2010, 7, 5)));
4218     assert(posInfInterval.contains(Date(2011, 7, 1)));
4219     assert(posInfInterval.contains(Date(2012, 1, 6)));
4220     assert(posInfInterval.contains(Date(2012, 1, 7)));
4221     assert(posInfInterval.contains(Date(2012, 1, 8)));
4222     assert(posInfInterval.contains(Date(2013, 1, 7)));
4223 
4224     const cdate = Date(2010, 7, 6);
4225     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4226     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4227     assert(posInfInterval.contains(cdate));
4228     assert(cPosInfInterval.contains(cdate));
4229     assert(iPosInfInterval.contains(cdate));
4230 
4231     //Verify Examples.
4232     assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(1994, 12, 24)));
4233     assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(2000, 1, 5)));
4234 }
4235 
4236 //Test PosInfInterval's contains(Interval).
4237 @safe unittest
4238 {
4239     import std.datetime.date;
4240 
4241     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4242 
4243     static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
4244     {
4245         posInfInterval.contains(interval);
4246     }
4247 
4248     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4249 
4250     assert(posInfInterval.contains(posInfInterval));
4251     assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4252     assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4253     assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4254     assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4255     assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4256     assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4257     assert(posInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4258     assert(posInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4259     assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4260     assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4261     assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4262     assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4263 
4264     assert(!posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
4265     assert(posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
4266     assert(posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
4267     assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
4268     assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
4269     assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
4270 
4271     assert(PosInfInterval!Date(Date(2010, 7, 3)).contains(posInfInterval));
4272     assert(PosInfInterval!Date(Date(2010, 7, 4)).contains(posInfInterval));
4273     assert(!PosInfInterval!Date(Date(2010, 7, 5)).contains(posInfInterval));
4274     assert(!PosInfInterval!Date(Date(2012, 1, 6)).contains(posInfInterval));
4275     assert(!PosInfInterval!Date(Date(2012, 1, 7)).contains(posInfInterval));
4276     assert(!PosInfInterval!Date(Date(2012, 1, 8)).contains(posInfInterval));
4277 
4278     assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
4279     assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
4280     assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
4281     assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
4282     assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
4283     assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
4284 
4285     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4286     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4287     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4288     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4289     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4290     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4291     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4292     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4293     assert(posInfInterval.contains(interval));
4294     assert(posInfInterval.contains(cInterval));
4295     assert(posInfInterval.contains(iInterval));
4296     assert(posInfInterval.contains(posInfInterval));
4297     assert(posInfInterval.contains(cPosInfInterval));
4298     assert(posInfInterval.contains(iPosInfInterval));
4299     assert(!posInfInterval.contains(negInfInterval));
4300     assert(!posInfInterval.contains(cNegInfInterval));
4301     assert(!posInfInterval.contains(iNegInfInterval));
4302     assert(cPosInfInterval.contains(interval));
4303     assert(cPosInfInterval.contains(cInterval));
4304     assert(cPosInfInterval.contains(iInterval));
4305     assert(cPosInfInterval.contains(posInfInterval));
4306     assert(cPosInfInterval.contains(cPosInfInterval));
4307     assert(cPosInfInterval.contains(iPosInfInterval));
4308     assert(!cPosInfInterval.contains(negInfInterval));
4309     assert(!cPosInfInterval.contains(cNegInfInterval));
4310     assert(!cPosInfInterval.contains(iNegInfInterval));
4311     assert(iPosInfInterval.contains(interval));
4312     assert(iPosInfInterval.contains(cInterval));
4313     assert(iPosInfInterval.contains(iInterval));
4314     assert(iPosInfInterval.contains(posInfInterval));
4315     assert(iPosInfInterval.contains(cPosInfInterval));
4316     assert(iPosInfInterval.contains(iPosInfInterval));
4317     assert(!iPosInfInterval.contains(negInfInterval));
4318     assert(!iPosInfInterval.contains(cNegInfInterval));
4319     assert(!iPosInfInterval.contains(iNegInfInterval));
4320 
4321     //Verify Examples.
4322     assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
4323     assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4324     assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
4325 
4326     assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
4327     assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1995, 7, 2))));
4328 
4329     assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
4330 }
4331 
4332 //Test PosInfInterval's isBefore(time point).
4333 @safe unittest
4334 {
4335     import std.datetime.date;
4336 
4337     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4338 
4339     assert(!posInfInterval.isBefore(Date(2009, 7, 3)));
4340     assert(!posInfInterval.isBefore(Date(2010, 7, 3)));
4341     assert(!posInfInterval.isBefore(Date(2010, 7, 4)));
4342     assert(!posInfInterval.isBefore(Date(2010, 7, 5)));
4343     assert(!posInfInterval.isBefore(Date(2011, 7, 1)));
4344     assert(!posInfInterval.isBefore(Date(2012, 1, 6)));
4345     assert(!posInfInterval.isBefore(Date(2012, 1, 7)));
4346     assert(!posInfInterval.isBefore(Date(2012, 1, 8)));
4347     assert(!posInfInterval.isBefore(Date(2013, 1, 7)));
4348 
4349     const cdate = Date(2010, 7, 6);
4350     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4351     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4352     assert(!posInfInterval.isBefore(cdate));
4353     assert(!cPosInfInterval.isBefore(cdate));
4354     assert(!iPosInfInterval.isBefore(cdate));
4355 
4356     //Verify Examples.
4357     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(1994, 12, 24)));
4358     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(2000, 1, 5)));
4359 }
4360 
4361 //Test PosInfInterval's isBefore(Interval).
4362 @safe unittest
4363 {
4364     import std.datetime.date;
4365 
4366     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4367 
4368     static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
4369     {
4370         posInfInterval.isBefore(interval);
4371     }
4372 
4373     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4374 
4375     assert(!posInfInterval.isBefore(posInfInterval));
4376     assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4377     assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4378     assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4379     assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4380     assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4381     assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4382     assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4383     assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4384     assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4385     assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4386     assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4387     assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4388 
4389     assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
4390     assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
4391     assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
4392     assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
4393     assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
4394     assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
4395 
4396     assert(!PosInfInterval!Date(Date(2010, 7, 3)).isBefore(posInfInterval));
4397     assert(!PosInfInterval!Date(Date(2010, 7, 4)).isBefore(posInfInterval));
4398     assert(!PosInfInterval!Date(Date(2010, 7, 5)).isBefore(posInfInterval));
4399     assert(!PosInfInterval!Date(Date(2012, 1, 6)).isBefore(posInfInterval));
4400     assert(!PosInfInterval!Date(Date(2012, 1, 7)).isBefore(posInfInterval));
4401     assert(!PosInfInterval!Date(Date(2012, 1, 8)).isBefore(posInfInterval));
4402 
4403     assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
4404     assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
4405     assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
4406     assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
4407     assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
4408     assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
4409 
4410     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4411     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4412     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4413     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4414     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4415     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4416     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4417     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4418     assert(!posInfInterval.isBefore(interval));
4419     assert(!posInfInterval.isBefore(cInterval));
4420     assert(!posInfInterval.isBefore(iInterval));
4421     assert(!posInfInterval.isBefore(posInfInterval));
4422     assert(!posInfInterval.isBefore(cPosInfInterval));
4423     assert(!posInfInterval.isBefore(iPosInfInterval));
4424     assert(!posInfInterval.isBefore(negInfInterval));
4425     assert(!posInfInterval.isBefore(cNegInfInterval));
4426     assert(!posInfInterval.isBefore(iNegInfInterval));
4427     assert(!cPosInfInterval.isBefore(interval));
4428     assert(!cPosInfInterval.isBefore(cInterval));
4429     assert(!cPosInfInterval.isBefore(iInterval));
4430     assert(!cPosInfInterval.isBefore(posInfInterval));
4431     assert(!cPosInfInterval.isBefore(cPosInfInterval));
4432     assert(!cPosInfInterval.isBefore(iPosInfInterval));
4433     assert(!cPosInfInterval.isBefore(negInfInterval));
4434     assert(!cPosInfInterval.isBefore(cNegInfInterval));
4435     assert(!cPosInfInterval.isBefore(iNegInfInterval));
4436     assert(!iPosInfInterval.isBefore(interval));
4437     assert(!iPosInfInterval.isBefore(cInterval));
4438     assert(!iPosInfInterval.isBefore(iInterval));
4439     assert(!iPosInfInterval.isBefore(posInfInterval));
4440     assert(!iPosInfInterval.isBefore(cPosInfInterval));
4441     assert(!iPosInfInterval.isBefore(iPosInfInterval));
4442     assert(!iPosInfInterval.isBefore(negInfInterval));
4443     assert(!iPosInfInterval.isBefore(cNegInfInterval));
4444     assert(!iPosInfInterval.isBefore(iNegInfInterval));
4445 
4446     //Verify Examples.
4447     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
4448     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4449 
4450     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(1992, 5, 4))));
4451     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
4452 
4453     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
4454 }
4455 
4456 //Test PosInfInterval's isAfter(time point).
4457 @safe unittest
4458 {
4459     import std.datetime.date;
4460 
4461     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4462 
4463     assert(posInfInterval.isAfter(Date(2009, 7, 3)));
4464     assert(posInfInterval.isAfter(Date(2010, 7, 3)));
4465     assert(!posInfInterval.isAfter(Date(2010, 7, 4)));
4466     assert(!posInfInterval.isAfter(Date(2010, 7, 5)));
4467     assert(!posInfInterval.isAfter(Date(2011, 7, 1)));
4468     assert(!posInfInterval.isAfter(Date(2012, 1, 6)));
4469     assert(!posInfInterval.isAfter(Date(2012, 1, 7)));
4470     assert(!posInfInterval.isAfter(Date(2012, 1, 8)));
4471     assert(!posInfInterval.isAfter(Date(2013, 1, 7)));
4472 
4473     const cdate = Date(2010, 7, 6);
4474     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4475     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4476     assert(!posInfInterval.isAfter(cdate));
4477     assert(!cPosInfInterval.isAfter(cdate));
4478     assert(!iPosInfInterval.isAfter(cdate));
4479 
4480     //Verify Examples.
4481     assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(1994, 12, 24)));
4482     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(2000, 1, 5)));
4483 }
4484 
4485 //Test PosInfInterval's isAfter(Interval).
4486 @safe unittest
4487 {
4488     import std.datetime.date;
4489 
4490     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4491 
4492     static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
4493     {
4494         posInfInterval.isAfter(interval);
4495     }
4496 
4497     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4498 
4499     assert(!posInfInterval.isAfter(posInfInterval));
4500     assert(posInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4501     assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4502     assert(posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4503     assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4504     assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4505     assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4506     assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4507     assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4508     assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4509     assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4510     assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4511     assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4512 
4513     assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
4514     assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
4515     assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
4516     assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
4517     assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
4518     assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
4519 
4520     assert(!PosInfInterval!Date(Date(2010, 7, 3)).isAfter(posInfInterval));
4521     assert(!PosInfInterval!Date(Date(2010, 7, 4)).isAfter(posInfInterval));
4522     assert(!PosInfInterval!Date(Date(2010, 7, 5)).isAfter(posInfInterval));
4523     assert(!PosInfInterval!Date(Date(2012, 1, 6)).isAfter(posInfInterval));
4524     assert(!PosInfInterval!Date(Date(2012, 1, 7)).isAfter(posInfInterval));
4525     assert(!PosInfInterval!Date(Date(2012, 1, 8)).isAfter(posInfInterval));
4526 
4527     assert(posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
4528     assert(posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
4529     assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
4530     assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
4531     assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
4532     assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
4533 
4534     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4535     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4536     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4537     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4538     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4539     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4540     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4541     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4542     assert(!posInfInterval.isAfter(interval));
4543     assert(!posInfInterval.isAfter(cInterval));
4544     assert(!posInfInterval.isAfter(iInterval));
4545     assert(!posInfInterval.isAfter(posInfInterval));
4546     assert(!posInfInterval.isAfter(cPosInfInterval));
4547     assert(!posInfInterval.isAfter(iPosInfInterval));
4548     assert(!posInfInterval.isAfter(negInfInterval));
4549     assert(!posInfInterval.isAfter(cNegInfInterval));
4550     assert(!posInfInterval.isAfter(iNegInfInterval));
4551     assert(!cPosInfInterval.isAfter(interval));
4552     assert(!cPosInfInterval.isAfter(cInterval));
4553     assert(!cPosInfInterval.isAfter(iInterval));
4554     assert(!cPosInfInterval.isAfter(posInfInterval));
4555     assert(!cPosInfInterval.isAfter(cPosInfInterval));
4556     assert(!cPosInfInterval.isAfter(iPosInfInterval));
4557     assert(!cPosInfInterval.isAfter(negInfInterval));
4558     assert(!cPosInfInterval.isAfter(cNegInfInterval));
4559     assert(!cPosInfInterval.isAfter(iNegInfInterval));
4560     assert(!iPosInfInterval.isAfter(interval));
4561     assert(!iPosInfInterval.isAfter(cInterval));
4562     assert(!iPosInfInterval.isAfter(iInterval));
4563     assert(!iPosInfInterval.isAfter(posInfInterval));
4564     assert(!iPosInfInterval.isAfter(cPosInfInterval));
4565     assert(!iPosInfInterval.isAfter(iPosInfInterval));
4566     assert(!iPosInfInterval.isAfter(negInfInterval));
4567     assert(!iPosInfInterval.isAfter(cNegInfInterval));
4568     assert(!iPosInfInterval.isAfter(iNegInfInterval));
4569 
4570     //Verify Examples.
4571     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
4572     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4573     assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
4574 
4575     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1990, 1, 7))));
4576     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
4577 
4578     assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
4579     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(2000, 7, 1))));
4580 }
4581 
4582 //Test PosInfInterval's intersects().
4583 @safe unittest
4584 {
4585     import std.datetime.date;
4586 
4587     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4588 
4589     static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
4590     {
4591         posInfInterval.intersects(interval);
4592     }
4593 
4594     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4595 
4596     assert(posInfInterval.intersects(posInfInterval));
4597     assert(!posInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4598     assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4599     assert(!posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4600     assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4601     assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4602     assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4603     assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4604     assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4605     assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4606     assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4607     assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4608     assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4609 
4610     assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
4611     assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
4612     assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
4613     assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
4614     assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
4615     assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
4616 
4617     assert(PosInfInterval!Date(Date(2010, 7, 3)).intersects(posInfInterval));
4618     assert(PosInfInterval!Date(Date(2010, 7, 4)).intersects(posInfInterval));
4619     assert(PosInfInterval!Date(Date(2010, 7, 5)).intersects(posInfInterval));
4620     assert(PosInfInterval!Date(Date(2012, 1, 6)).intersects(posInfInterval));
4621     assert(PosInfInterval!Date(Date(2012, 1, 7)).intersects(posInfInterval));
4622     assert(PosInfInterval!Date(Date(2012, 1, 8)).intersects(posInfInterval));
4623 
4624     assert(!posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
4625     assert(!posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
4626     assert(posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
4627     assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
4628     assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
4629     assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
4630 
4631     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4632     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4633     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4634     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4635     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4636     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4637     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4638     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4639     assert(posInfInterval.intersects(interval));
4640     assert(posInfInterval.intersects(cInterval));
4641     assert(posInfInterval.intersects(iInterval));
4642     assert(posInfInterval.intersects(posInfInterval));
4643     assert(posInfInterval.intersects(cPosInfInterval));
4644     assert(posInfInterval.intersects(iPosInfInterval));
4645     assert(posInfInterval.intersects(negInfInterval));
4646     assert(posInfInterval.intersects(cNegInfInterval));
4647     assert(posInfInterval.intersects(iNegInfInterval));
4648     assert(cPosInfInterval.intersects(interval));
4649     assert(cPosInfInterval.intersects(cInterval));
4650     assert(cPosInfInterval.intersects(iInterval));
4651     assert(cPosInfInterval.intersects(posInfInterval));
4652     assert(cPosInfInterval.intersects(cPosInfInterval));
4653     assert(cPosInfInterval.intersects(iPosInfInterval));
4654     assert(cPosInfInterval.intersects(negInfInterval));
4655     assert(cPosInfInterval.intersects(cNegInfInterval));
4656     assert(cPosInfInterval.intersects(iNegInfInterval));
4657     assert(iPosInfInterval.intersects(interval));
4658     assert(iPosInfInterval.intersects(cInterval));
4659     assert(iPosInfInterval.intersects(iInterval));
4660     assert(iPosInfInterval.intersects(posInfInterval));
4661     assert(iPosInfInterval.intersects(cPosInfInterval));
4662     assert(iPosInfInterval.intersects(iPosInfInterval));
4663     assert(iPosInfInterval.intersects(negInfInterval));
4664     assert(iPosInfInterval.intersects(cNegInfInterval));
4665     assert(iPosInfInterval.intersects(iNegInfInterval));
4666 
4667     //Verify Examples.
4668     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
4669     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4670     assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
4671 
4672     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1990, 1, 7))));
4673     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
4674 
4675     assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
4676     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(2000, 7, 1))));
4677 }
4678 
4679 //Test PosInfInterval's intersection().
4680 @safe unittest
4681 {
4682     import std.datetime.date;
4683 
4684     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4685 
testInterval(I,J)4686     static void testInterval(I, J)(in I interval1, in J interval2)
4687     {
4688         interval1.intersection(interval2);
4689     }
4690 
4691     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4692 
4693     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4694     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4695 
4696     assertThrown!DateTimeException(testInterval(posInfInterval, NegInfInterval!Date(Date(2010, 7, 3))));
4697     assertThrown!DateTimeException(testInterval(posInfInterval, NegInfInterval!Date(Date(2010, 7, 4))));
4698 
4699     assert(posInfInterval.intersection(posInfInterval) == posInfInterval);
4700     assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
4701            Interval!Date(Date(2010, 7, 4), Date(2013, 7, 3)));
4702     assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
4703            Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
4704     assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
4705            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
4706     assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
4707            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
4708     assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
4709            Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
4710     assert(posInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
4711            Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
4712     assert(posInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
4713            Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
4714     assert(posInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
4715            Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)));
4716     assert(posInfInterval.intersection(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
4717            Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)));
4718     assert(posInfInterval.intersection(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
4719            Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)));
4720 
4721     assert(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 3))) == PosInfInterval!Date(Date(2010, 7, 4)));
4722     assert(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 4))) == PosInfInterval!Date(Date(2010, 7, 4)));
4723     assert(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 5))) == PosInfInterval!Date(Date(2010, 7, 5)));
4724     assert(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 6))) == PosInfInterval!Date(Date(2012, 1, 6)));
4725     assert(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 7))) == PosInfInterval!Date(Date(2012, 1, 7)));
4726     assert(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 8))) == PosInfInterval!Date(Date(2012, 1, 8)));
4727 
4728     assert(PosInfInterval!Date(Date(2010, 7, 3)).intersection(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4729     assert(PosInfInterval!Date(Date(2010, 7, 4)).intersection(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4730     assert(PosInfInterval!Date(Date(2010, 7, 5)).intersection(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 5)));
4731     assert(PosInfInterval!Date(Date(2012, 1, 6)).intersection(posInfInterval) == PosInfInterval!Date(Date(2012, 1, 6)));
4732     assert(PosInfInterval!Date(Date(2012, 1, 7)).intersection(posInfInterval) == PosInfInterval!Date(Date(2012, 1, 7)));
4733     assert(PosInfInterval!Date(Date(2012, 1, 8)).intersection(posInfInterval) == PosInfInterval!Date(Date(2012, 1, 8)));
4734 
4735     assert(posInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 5))) ==
4736            Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
4737     assert(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 6))) ==
4738            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 6)));
4739     assert(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 7))) ==
4740            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
4741     assert(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 8))) ==
4742            Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
4743 
4744     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4745     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4746     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4747     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4748     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4749     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4750     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4751     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4752     assert(!posInfInterval.intersection(interval).empty);
4753     assert(!posInfInterval.intersection(cInterval).empty);
4754     assert(!posInfInterval.intersection(iInterval).empty);
4755     assert(!posInfInterval.intersection(posInfInterval).empty);
4756     assert(!posInfInterval.intersection(cPosInfInterval).empty);
4757     assert(!posInfInterval.intersection(iPosInfInterval).empty);
4758     assert(!posInfInterval.intersection(negInfInterval).empty);
4759     assert(!posInfInterval.intersection(cNegInfInterval).empty);
4760     assert(!posInfInterval.intersection(iNegInfInterval).empty);
4761     assert(!cPosInfInterval.intersection(interval).empty);
4762     assert(!cPosInfInterval.intersection(cInterval).empty);
4763     assert(!cPosInfInterval.intersection(iInterval).empty);
4764     assert(!cPosInfInterval.intersection(posInfInterval).empty);
4765     assert(!cPosInfInterval.intersection(cPosInfInterval).empty);
4766     assert(!cPosInfInterval.intersection(iPosInfInterval).empty);
4767     assert(!cPosInfInterval.intersection(negInfInterval).empty);
4768     assert(!cPosInfInterval.intersection(cNegInfInterval).empty);
4769     assert(!cPosInfInterval.intersection(iNegInfInterval).empty);
4770     assert(!iPosInfInterval.intersection(interval).empty);
4771     assert(!iPosInfInterval.intersection(cInterval).empty);
4772     assert(!iPosInfInterval.intersection(iInterval).empty);
4773     assert(!iPosInfInterval.intersection(posInfInterval).empty);
4774     assert(!iPosInfInterval.intersection(cPosInfInterval).empty);
4775     assert(!iPosInfInterval.intersection(iPosInfInterval).empty);
4776     assert(!iPosInfInterval.intersection(negInfInterval).empty);
4777     assert(!iPosInfInterval.intersection(cNegInfInterval).empty);
4778     assert(!iPosInfInterval.intersection(iNegInfInterval).empty);
4779 
4780     //Verify Examples.
4781     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
4782            Interval!Date(Date(1996, 1, 2), Date(2000, 8, 2)));
4783     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
4784            Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17)));
4785 
4786     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) ==
4787            PosInfInterval!Date(Date(1996, 1, 2)));
4788     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) ==
4789            PosInfInterval!Date(Date(1999, 1, 12)));
4790 
4791     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) ==
4792            Interval!Date(Date(1996, 1, 2), Date(1999, 7, 6)));
4793     assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) ==
4794            Interval!Date(Date(1996, 1, 2), Date(2013, 1, 12)));
4795 }
4796 
4797 //Test PosInfInterval's isAdjacent().
4798 @safe unittest
4799 {
4800     import std.datetime.date;
4801 
4802     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4803 
4804     static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
4805     {
4806         posInfInterval.isAdjacent(interval);
4807     }
4808 
4809     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4810 
4811     assert(!posInfInterval.isAdjacent(posInfInterval));
4812     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4813     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
4814     assert(posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
4815     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
4816     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
4817     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
4818     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
4819     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
4820     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
4821     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
4822     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
4823     assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
4824 
4825     assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
4826     assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
4827     assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
4828     assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
4829     assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
4830     assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
4831 
4832     assert(!PosInfInterval!Date(Date(2010, 7, 3)).isAdjacent(posInfInterval));
4833     assert(!PosInfInterval!Date(Date(2010, 7, 4)).isAdjacent(posInfInterval));
4834     assert(!PosInfInterval!Date(Date(2010, 7, 5)).isAdjacent(posInfInterval));
4835     assert(!PosInfInterval!Date(Date(2012, 1, 6)).isAdjacent(posInfInterval));
4836     assert(!PosInfInterval!Date(Date(2012, 1, 7)).isAdjacent(posInfInterval));
4837     assert(!PosInfInterval!Date(Date(2012, 1, 8)).isAdjacent(posInfInterval));
4838 
4839     assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
4840     assert(posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
4841     assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
4842     assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
4843     assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
4844     assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
4845 
4846     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4847     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4848     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4849     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4850     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4851     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4852     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4853     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4854     assert(!posInfInterval.isAdjacent(interval));
4855     assert(!posInfInterval.isAdjacent(cInterval));
4856     assert(!posInfInterval.isAdjacent(iInterval));
4857     assert(!posInfInterval.isAdjacent(posInfInterval));
4858     assert(!posInfInterval.isAdjacent(cPosInfInterval));
4859     assert(!posInfInterval.isAdjacent(iPosInfInterval));
4860     assert(!posInfInterval.isAdjacent(negInfInterval));
4861     assert(!posInfInterval.isAdjacent(cNegInfInterval));
4862     assert(!posInfInterval.isAdjacent(iNegInfInterval));
4863     assert(!cPosInfInterval.isAdjacent(interval));
4864     assert(!cPosInfInterval.isAdjacent(cInterval));
4865     assert(!cPosInfInterval.isAdjacent(iInterval));
4866     assert(!cPosInfInterval.isAdjacent(posInfInterval));
4867     assert(!cPosInfInterval.isAdjacent(cPosInfInterval));
4868     assert(!cPosInfInterval.isAdjacent(iPosInfInterval));
4869     assert(!cPosInfInterval.isAdjacent(negInfInterval));
4870     assert(!cPosInfInterval.isAdjacent(cNegInfInterval));
4871     assert(!cPosInfInterval.isAdjacent(iNegInfInterval));
4872     assert(!iPosInfInterval.isAdjacent(interval));
4873     assert(!iPosInfInterval.isAdjacent(cInterval));
4874     assert(!iPosInfInterval.isAdjacent(iInterval));
4875     assert(!iPosInfInterval.isAdjacent(posInfInterval));
4876     assert(!iPosInfInterval.isAdjacent(cPosInfInterval));
4877     assert(!iPosInfInterval.isAdjacent(iPosInfInterval));
4878     assert(!iPosInfInterval.isAdjacent(negInfInterval));
4879     assert(!iPosInfInterval.isAdjacent(cNegInfInterval));
4880     assert(!iPosInfInterval.isAdjacent(iNegInfInterval));
4881 
4882     //Verify Examples.
4883     assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
4884     assert(!PosInfInterval!Date(Date(1999, 1, 12)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
4885 
4886     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1990, 1, 7))));
4887     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1996, 1, 2))));
4888 
4889     assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
4890     assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(2000, 7, 1))));
4891 }
4892 
4893 //Test PosInfInterval's merge().
4894 @safe unittest
4895 {
4896     import std.datetime.date;
4897 
4898     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4899 
4900     static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
4901     {
4902         posInfInterval.merge(interval);
4903     }
4904 
4905     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
4906 
4907     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
4908 
4909     assert(posInfInterval.merge(posInfInterval) == posInfInterval);
4910     assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
4911            PosInfInterval!Date(Date(2010, 7, 1)));
4912     assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
4913            PosInfInterval!Date(Date(2010, 7, 3)));
4914     assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
4915            PosInfInterval!Date(Date(2010, 7, 3)));
4916     assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
4917            PosInfInterval!Date(Date(2010, 7, 3)));
4918     assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
4919            PosInfInterval!Date(Date(2010, 7, 3)));
4920     assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
4921            PosInfInterval!Date(Date(2010, 7, 4)));
4922     assert(posInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
4923            PosInfInterval!Date(Date(2010, 7, 4)));
4924     assert(posInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
4925            PosInfInterval!Date(Date(2010, 7, 4)));
4926     assert(posInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
4927            PosInfInterval!Date(Date(2010, 7, 4)));
4928     assert(posInfInterval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
4929            PosInfInterval!Date(Date(2010, 7, 4)));
4930     assert(posInfInterval.merge(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
4931            PosInfInterval!Date(Date(2010, 7, 4)));
4932 
4933     assert(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 3))) == PosInfInterval!Date(Date(2010, 7, 3)));
4934     assert(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 4))) == PosInfInterval!Date(Date(2010, 7, 4)));
4935     assert(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 5))) == PosInfInterval!Date(Date(2010, 7, 4)));
4936     assert(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 6))) == PosInfInterval!Date(Date(2010, 7, 4)));
4937     assert(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 7))) == PosInfInterval!Date(Date(2010, 7, 4)));
4938     assert(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 8))) == PosInfInterval!Date(Date(2010, 7, 4)));
4939 
4940     assert(PosInfInterval!Date(Date(2010, 7, 3)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 3)));
4941     assert(PosInfInterval!Date(Date(2010, 7, 4)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4942     assert(PosInfInterval!Date(Date(2010, 7, 5)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4943     assert(PosInfInterval!Date(Date(2012, 1, 6)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4944     assert(PosInfInterval!Date(Date(2012, 1, 7)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4945     assert(PosInfInterval!Date(Date(2012, 1, 8)).merge(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
4946 
4947     static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 3)))));
4948     static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 4)))));
4949     static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 5)))));
4950     static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 6)))));
4951     static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 7)))));
4952     static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 8)))));
4953 
4954     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4955     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4956     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
4957     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4958     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
4959     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4960     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4961     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
4962     assert(!posInfInterval.merge(interval).empty);
4963     assert(!posInfInterval.merge(cInterval).empty);
4964     assert(!posInfInterval.merge(iInterval).empty);
4965     assert(!posInfInterval.merge(posInfInterval).empty);
4966     assert(!posInfInterval.merge(cPosInfInterval).empty);
4967     assert(!posInfInterval.merge(iPosInfInterval).empty);
4968     static assert(!__traits(compiles, posInfInterval.merge(negInfInterval)));
4969     static assert(!__traits(compiles, posInfInterval.merge(cNegInfInterval)));
4970     static assert(!__traits(compiles, posInfInterval.merge(iNegInfInterval)));
4971     assert(!cPosInfInterval.merge(interval).empty);
4972     assert(!cPosInfInterval.merge(cInterval).empty);
4973     assert(!cPosInfInterval.merge(iInterval).empty);
4974     assert(!cPosInfInterval.merge(posInfInterval).empty);
4975     assert(!cPosInfInterval.merge(cPosInfInterval).empty);
4976     assert(!cPosInfInterval.merge(iPosInfInterval).empty);
4977     static assert(!__traits(compiles, cPosInfInterval.merge(negInfInterval)));
4978     static assert(!__traits(compiles, cPosInfInterval.merge(cNegInfInterval)));
4979     static assert(!__traits(compiles, cPosInfInterval.merge(iNegInfInterval)));
4980     assert(!iPosInfInterval.merge(interval).empty);
4981     assert(!iPosInfInterval.merge(cInterval).empty);
4982     assert(!iPosInfInterval.merge(iInterval).empty);
4983     assert(!iPosInfInterval.merge(posInfInterval).empty);
4984     assert(!iPosInfInterval.merge(cPosInfInterval).empty);
4985     assert(!iPosInfInterval.merge(iPosInfInterval).empty);
4986     static assert(!__traits(compiles, iPosInfInterval.merge(negInfInterval)));
4987     static assert(!__traits(compiles, iPosInfInterval.merge(cNegInfInterval)));
4988     static assert(!__traits(compiles, iPosInfInterval.merge(iNegInfInterval)));
4989 
4990     //Verify Examples.
4991     assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
4992            PosInfInterval!Date(Date(1990, 7, 6)));
4993     assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
4994            PosInfInterval!Date(Date(1996, 1, 2)));
4995 
4996     assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1990, 7, 6))) ==
4997            PosInfInterval!Date(Date(1990, 7, 6)));
4998     assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1999, 1, 12))) ==
4999            PosInfInterval!Date(Date(1996, 1, 2)));
5000 }
5001 
5002 //Test PosInfInterval's span().
5003 @safe unittest
5004 {
5005     import std.datetime.date;
5006 
5007     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5008 
5009     static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
5010     {
5011         posInfInterval.span(interval);
5012     }
5013 
5014     assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
5015 
5016     assert(posInfInterval.span(posInfInterval) == posInfInterval);
5017     assert(posInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
5018            PosInfInterval!Date(Date(2010, 7, 1)));
5019     assert(posInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
5020            PosInfInterval!Date(Date(2010, 7, 1)));
5021     assert(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
5022            PosInfInterval!Date(Date(2010, 7, 3)));
5023     assert(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
5024            PosInfInterval!Date(Date(2010, 7, 3)));
5025     assert(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
5026            PosInfInterval!Date(Date(2010, 7, 3)));
5027     assert(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
5028            PosInfInterval!Date(Date(2010, 7, 3)));
5029     assert(posInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
5030            PosInfInterval!Date(Date(2010, 7, 4)));
5031     assert(posInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
5032            PosInfInterval!Date(Date(2010, 7, 4)));
5033     assert(posInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
5034            PosInfInterval!Date(Date(2010, 7, 4)));
5035     assert(posInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
5036            PosInfInterval!Date(Date(2010, 7, 4)));
5037     assert(posInfInterval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
5038            PosInfInterval!Date(Date(2010, 7, 4)));
5039     assert(posInfInterval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
5040            PosInfInterval!Date(Date(2010, 7, 4)));
5041 
5042     assert(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 3))) == PosInfInterval!Date(Date(2010, 7, 3)));
5043     assert(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 4))) == PosInfInterval!Date(Date(2010, 7, 4)));
5044     assert(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 5))) == PosInfInterval!Date(Date(2010, 7, 4)));
5045     assert(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 6))) == PosInfInterval!Date(Date(2010, 7, 4)));
5046     assert(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 7))) == PosInfInterval!Date(Date(2010, 7, 4)));
5047     assert(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 8))) == PosInfInterval!Date(Date(2010, 7, 4)));
5048 
5049     assert(PosInfInterval!Date(Date(2010, 7, 3)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 3)));
5050     assert(PosInfInterval!Date(Date(2010, 7, 4)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5051     assert(PosInfInterval!Date(Date(2010, 7, 5)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5052     assert(PosInfInterval!Date(Date(2012, 1, 6)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5053     assert(PosInfInterval!Date(Date(2012, 1, 7)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5054     assert(PosInfInterval!Date(Date(2012, 1, 8)).span(posInfInterval) == PosInfInterval!Date(Date(2010, 7, 4)));
5055 
5056     static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 3)))));
5057     static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 4)))));
5058     static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 5)))));
5059     static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 6)))));
5060     static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 7)))));
5061     static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 8)))));
5062 
5063     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
5064     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
5065     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
5066     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5067     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5068     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
5069     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
5070     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
5071     assert(!posInfInterval.span(interval).empty);
5072     assert(!posInfInterval.span(cInterval).empty);
5073     assert(!posInfInterval.span(iInterval).empty);
5074     assert(!posInfInterval.span(posInfInterval).empty);
5075     assert(!posInfInterval.span(cPosInfInterval).empty);
5076     assert(!posInfInterval.span(iPosInfInterval).empty);
5077     static assert(!__traits(compiles, posInfInterval.span(negInfInterval)));
5078     static assert(!__traits(compiles, posInfInterval.span(cNegInfInterval)));
5079     static assert(!__traits(compiles, posInfInterval.span(iNegInfInterval)));
5080     assert(!cPosInfInterval.span(interval).empty);
5081     assert(!cPosInfInterval.span(cInterval).empty);
5082     assert(!cPosInfInterval.span(iInterval).empty);
5083     assert(!cPosInfInterval.span(posInfInterval).empty);
5084     assert(!cPosInfInterval.span(cPosInfInterval).empty);
5085     assert(!cPosInfInterval.span(iPosInfInterval).empty);
5086     static assert(!__traits(compiles, cPosInfInterval.span(negInfInterval)));
5087     static assert(!__traits(compiles, cPosInfInterval.span(cNegInfInterval)));
5088     static assert(!__traits(compiles, cPosInfInterval.span(iNegInfInterval)));
5089     assert(!iPosInfInterval.span(interval).empty);
5090     assert(!iPosInfInterval.span(cInterval).empty);
5091     assert(!iPosInfInterval.span(iInterval).empty);
5092     assert(!iPosInfInterval.span(posInfInterval).empty);
5093     assert(!iPosInfInterval.span(cPosInfInterval).empty);
5094     assert(!iPosInfInterval.span(iPosInfInterval).empty);
5095     static assert(!__traits(compiles, iPosInfInterval.span(negInfInterval)));
5096     static assert(!__traits(compiles, iPosInfInterval.span(cNegInfInterval)));
5097     static assert(!__traits(compiles, iPosInfInterval.span(iNegInfInterval)));
5098 
5099     //Verify Examples.
5100     assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(500, 8, 9), Date(1602, 1, 31))) ==
5101            PosInfInterval!Date(Date(500, 8, 9)));
5102     assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
5103            PosInfInterval!Date(Date(1990, 7, 6)));
5104     assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
5105            PosInfInterval!Date(Date(1996, 1, 2)));
5106 
5107     assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1990, 7, 6))) ==
5108            PosInfInterval!Date(Date(1990, 7, 6)));
5109     assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1999, 1, 12))) ==
5110            PosInfInterval!Date(Date(1996, 1, 2)));
5111 }
5112 
5113 //Test PosInfInterval's shift().
5114 @safe unittest
5115 {
5116     import std.datetime.date;
5117 
5118     auto interval = PosInfInterval!Date(Date(2010, 7, 4));
5119 
testInterval(I)5120     static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
5121     {
5122         interval.shift(duration);
5123         assert(interval == expected);
5124     }
5125 
5126     testInterval(interval, dur!"days"(22), PosInfInterval!Date(Date(2010, 7, 26)));
5127     testInterval(interval, dur!"days"(-22), PosInfInterval!Date(Date(2010, 6, 12)));
5128 
5129     const cInterval = PosInfInterval!Date(Date(2010, 7, 4));
5130     immutable iInterval = PosInfInterval!Date(Date(2010, 7, 4));
5131     static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
5132     static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
5133 
5134     //Verify Examples.
5135     auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
5136     auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
5137 
5138     interval1.shift(dur!"days"(50));
5139     assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
5140 
5141     interval2.shift(dur!"days"(-50));
5142     assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
5143 }
5144 
5145 //Test PosInfInterval's shift(int, int, AllowDayOverflow).
5146 @safe unittest
5147 {
5148     import std.datetime.date;
5149 
5150     {
5151         auto interval = PosInfInterval!Date(Date(2010, 7, 4));
5152 
testInterval(I)5153         static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
5154                                     in I expected, size_t line = __LINE__)
5155         {
5156             interval.shift(years, months, allow);
5157             assert(interval == expected);
5158         }
5159 
5160         testInterval(interval, 5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2015, 7, 4)));
5161         testInterval(interval, -5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2005, 7, 4)));
5162 
5163         auto interval2 = PosInfInterval!Date(Date(2000, 1, 29));
5164 
5165         testInterval(interval2, 1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2001, 3, 1)));
5166         testInterval(interval2, 1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2000, 12, 29)));
5167         testInterval(interval2, -1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1998, 12, 29)));
5168         testInterval(interval2, -1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1999, 3, 1)));
5169 
5170         testInterval(interval2, 1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(2001, 2, 28)));
5171         testInterval(interval2, 1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(2000, 12, 29)));
5172         testInterval(interval2, -1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(1998, 12, 29)));
5173         testInterval(interval2, -1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(1999, 2, 28)));
5174     }
5175 
5176     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5177     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5178     static assert(!__traits(compiles, cPosInfInterval.shift(1)));
5179     static assert(!__traits(compiles, iPosInfInterval.shift(1)));
5180 
5181     //Verify Examples.
5182     auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
5183     auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
5184 
5185     interval1.shift(2);
5186     assert(interval1 == PosInfInterval!Date(Date(1998, 1, 2)));
5187 
5188     interval2.shift(-2);
5189     assert(interval2 == PosInfInterval!Date(Date(1994, 1, 2)));
5190 }
5191 
5192 //Test PosInfInterval's expand().
5193 @safe unittest
5194 {
5195     import std.datetime.date;
5196 
5197     auto interval = PosInfInterval!Date(Date(2000, 7, 4));
5198 
testInterval(I)5199     static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
5200     {
5201         interval.expand(duration);
5202         assert(interval == expected);
5203     }
5204 
5205     testInterval(interval, dur!"days"(22), PosInfInterval!Date(Date(2000, 6, 12)));
5206     testInterval(interval, dur!"days"(-22), PosInfInterval!Date(Date(2000, 7, 26)));
5207 
5208     const cInterval = PosInfInterval!Date(Date(2010, 7, 4));
5209     immutable iInterval = PosInfInterval!Date(Date(2010, 7, 4));
5210     static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
5211     static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
5212 
5213     //Verify Examples.
5214     auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
5215     auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
5216 
5217     interval1.expand(dur!"days"(2));
5218     assert(interval1 == PosInfInterval!Date(Date(1995, 12, 31)));
5219 
5220     interval2.expand(dur!"days"(-2));
5221     assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
5222 }
5223 
5224 //Test PosInfInterval's expand(int, int, AllowDayOverflow).
5225 @safe unittest
5226 {
5227     import std.datetime.date;
5228 
5229     {
5230         auto interval = PosInfInterval!Date(Date(2000, 7, 4));
5231 
testInterval(I)5232         static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
5233                                     in I expected, size_t line = __LINE__)
5234         {
5235             interval.expand(years, months, allow);
5236             assert(interval == expected);
5237         }
5238 
5239         testInterval(interval, 5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(1995, 7, 4)));
5240         testInterval(interval, -5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2005, 7, 4)));
5241 
5242         auto interval2 = PosInfInterval!Date(Date(2000, 1, 29));
5243 
5244         testInterval(interval2, 1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1998, 12, 29)));
5245         testInterval(interval2, 1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1999, 3, 1)));
5246         testInterval(interval2, -1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2001, 3, 1)));
5247         testInterval(interval2, -1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2000, 12, 29)));
5248 
5249         testInterval(interval2, 1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(1998, 12, 29)));
5250         testInterval(interval2, 1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(1999, 2, 28)));
5251         testInterval(interval2, -1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(2001, 2, 28)));
5252         testInterval(interval2, -1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(2000, 12, 29)));
5253     }
5254 
5255     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5256     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5257     static assert(!__traits(compiles, cPosInfInterval.expand(1)));
5258     static assert(!__traits(compiles, iPosInfInterval.expand(1)));
5259 
5260     //Verify Examples.
5261     auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
5262     auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
5263 
5264     interval1.expand(2);
5265     assert(interval1 == PosInfInterval!Date(Date(1994, 1, 2)));
5266 
5267     interval2.expand(-2);
5268     assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
5269 }
5270 
5271 //Test PosInfInterval's fwdRange().
5272 @system unittest
5273 {
5274     import std.datetime.date;
5275 
5276     auto posInfInterval = PosInfInterval!Date(Date(2010, 9, 19));
5277 
5278     static void testInterval(PosInfInterval!Date posInfInterval)
5279     {
5280         posInfInterval.fwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).popFront();
5281     }
5282 
5283     assertThrown!DateTimeException(testInterval(posInfInterval));
5284 
5285     assert(PosInfInterval!Date(Date(2010, 9, 12)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).front ==
5286            Date(2010, 9, 12));
5287 
5288     assert(PosInfInterval!Date(Date(2010, 9, 12)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).front ==
5289            Date(2010, 9, 17));
5290 
5291     //Verify Examples.
5292     auto interval = PosInfInterval!Date(Date(2010, 9, 1));
delegate(in Date date)5293     auto func = delegate (in Date date)
5294                 {
5295                     if ((date.day & 1) == 0)
5296                         return date + dur!"days"(2);
5297                     return date + dur!"days"(1);
5298                 };
5299     auto range = interval.fwdRange(func);
5300 
5301     assert(range.front == Date(2010, 9, 1)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
5302 
5303     range.popFront();
5304     assert(range.front == Date(2010, 9, 2));
5305 
5306     range.popFront();
5307     assert(range.front == Date(2010, 9, 4));
5308 
5309     range.popFront();
5310     assert(range.front == Date(2010, 9, 6));
5311 
5312     range.popFront();
5313     assert(range.front == Date(2010, 9, 8));
5314 
5315     range.popFront();
5316     assert(!range.empty);
5317 
5318     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5319     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5320     assert(!cPosInfInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
5321     assert(!iPosInfInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
5322 }
5323 
5324 //Test PosInfInterval's toString().
5325 @safe unittest
5326 {
5327     import std.datetime.date;
5328     assert(PosInfInterval!Date(Date(2010, 7, 4)).toString() == "[2010-Jul-04 - ∞)");
5329 
5330     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5331     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
5332     assert(cPosInfInterval.toString());
5333     assert(iPosInfInterval.toString());
5334 }
5335 
5336 
5337 /++
5338     Represents an interval of time which has negative infinity as its starting
5339     point.
5340 
5341     Any ranges which iterate over a $(D NegInfInterval) are infinite. So, the
5342     main purpose of using $(D NegInfInterval) is to create an infinite range
5343     which starts at negative infinity and goes to a fixed end point.
5344     Iterate over it in reverse.
5345   +/
NegInfInterval(TP)5346 struct NegInfInterval(TP)
5347 {
5348 public:
5349 
5350     /++
5351         Params:
5352             end = The time point which ends the interval.
5353 
5354         Example:
5355 --------------------
5356 auto interval = PosInfInterval!Date(Date(1996, 1, 2));
5357 --------------------
5358       +/
5359     this(in TP end) pure nothrow
5360     {
5361         _end = cast(TP) end;
5362     }
5363 
5364 
5365     /++
5366         Params:
5367             rhs = The $(D NegInfInterval) to assign to this one.
5368       +/
5369     ref NegInfInterval opAssign(const ref NegInfInterval rhs) pure nothrow
5370     {
5371         _end = cast(TP) rhs._end;
5372         return this;
5373     }
5374 
5375 
5376     /++
5377         Params:
5378             rhs = The $(D NegInfInterval) to assign to this one.
5379       +/
5380     ref NegInfInterval opAssign(NegInfInterval rhs) pure nothrow
5381     {
5382         _end = cast(TP) rhs._end;
5383         return this;
5384     }
5385 
5386 
5387     /++
5388         The end point of the interval. It is excluded from the interval.
5389 
5390         Example:
5391 --------------------
5392 assert(NegInfInterval!Date(Date(2012, 3, 1)).end == Date(2012, 3, 1));
5393 --------------------
5394       +/
5395     @property TP end() const pure nothrow
5396     {
5397         return cast(TP)_end;
5398     }
5399 
5400 
5401     /++
5402         The end point of the interval. It is excluded from the interval.
5403 
5404         Params:
5405             timePoint = The time point to set end to.
5406       +/
5407     @property void end(TP timePoint) pure nothrow
5408     {
5409         _end = timePoint;
5410     }
5411 
5412 
5413     /++
5414         Whether the interval's length is 0. Always returns false.
5415 
5416         Example:
5417 --------------------
5418 assert(!NegInfInterval!Date(Date(1996, 1, 2)).empty);
5419 --------------------
5420       +/
5421     enum bool empty = false;
5422 
5423 
5424     /++
5425         Whether the given time point is within this interval.
5426 
5427         Params:
5428             timePoint = The time point to check for inclusion in this interval.
5429 
5430         Example:
5431 --------------------
5432 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
5433 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
5434 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
5435 --------------------
5436       +/
5437     bool contains(TP timePoint) const pure nothrow
5438     {
5439         return timePoint < _end;
5440     }
5441 
5442 
5443     /++
5444         Whether the given interval is completely within this interval.
5445 
5446         Params:
5447             interval = The interval to check for inclusion in this interval.
5448 
5449         Throws:
5450             $(REF DateTimeException,std,datetime,date) if the given interval
5451             is empty.
5452 
5453         Example:
5454 --------------------
5455 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(
5456             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5457 
5458 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(
5459             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
5460 
5461 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(
5462             Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
5463 --------------------
5464       +/
5465     bool contains(in Interval!TP interval) const pure
5466     {
5467         interval._enforceNotEmpty();
5468         return interval._end <= _end;
5469     }
5470 
5471 
5472     /++
5473         Whether the given interval is completely within this interval.
5474 
5475         Always returns false because an interval beginning at negative
5476         infinity can never contain an interval going to positive infinity.
5477 
5478         Params:
5479             interval = The interval to check for inclusion in this interval.
5480 
5481         Example:
5482 --------------------
5483 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(
5484             PosInfInterval!Date(Date(1999, 5, 4))));
5485 --------------------
5486       +/
5487     bool contains(in PosInfInterval!TP interval) const pure nothrow
5488     {
5489         return false;
5490     }
5491 
5492 
5493     /++
5494         Whether the given interval is completely within this interval.
5495 
5496         Params:
5497             interval = The interval to check for inclusion in this interval.
5498 
5499         Example:
5500 --------------------
5501 assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(
5502             NegInfInterval!Date(Date(1996, 5, 4))));
5503 
5504 assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(
5505             NegInfInterval!Date(Date(2013, 7, 9))));
5506 --------------------
5507       +/
5508     bool contains(in NegInfInterval interval) const pure nothrow
5509     {
5510         return interval._end <= _end;
5511     }
5512 
5513 
5514     /++
5515         Whether this interval is before the given time point.
5516 
5517         Params:
5518             timePoint = The time point to check whether this interval is
5519                         before it.
5520 
5521         Example:
5522 --------------------
5523 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
5524 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
5525 assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
5526 --------------------
5527       +/
5528     bool isBefore(in TP timePoint) const pure nothrow
5529     {
5530         return timePoint >= _end;
5531     }
5532 
5533 
5534     /++
5535         Whether this interval is before the given interval and does not
5536         intersect it.
5537 
5538         Params:
5539             interval = The interval to check for against this interval.
5540 
5541         Throws:
5542             $(REF DateTimeException,std,datetime,date) if the given interval
5543             is empty
5544 
5545         Example:
5546 --------------------
5547 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5548             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5549 
5550 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5551             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
5552 
5553 assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5554             Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
5555 --------------------
5556       +/
5557     bool isBefore(in Interval!TP interval) const pure
5558     {
5559         interval._enforceNotEmpty();
5560         return _end <= interval._begin;
5561     }
5562 
5563 
5564     /++
5565         Whether this interval is before the given interval and does not
5566         intersect it.
5567 
5568         Params:
5569             interval = The interval to check for against this interval.
5570 
5571         Example:
5572 --------------------
5573 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5574             PosInfInterval!Date(Date(1999, 5, 4))));
5575 
5576 assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5577             PosInfInterval!Date(Date(2012, 3, 1))));
5578 --------------------
5579       +/
5580     bool isBefore(in PosInfInterval!TP interval) const pure nothrow
5581     {
5582         return _end <= interval._begin;
5583     }
5584 
5585 
5586     /++
5587         Whether this interval is before the given interval and does not
5588         intersect it.
5589 
5590         Always returns false because an interval beginning at negative
5591         infinity can never be before another interval beginning at negative
5592         infinity.
5593 
5594         Params:
5595             interval = The interval to check for against this interval.
5596 
5597         Example:
5598 --------------------
5599 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5600             NegInfInterval!Date(Date(1996, 5, 4))));
5601 
5602 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
5603             NegInfInterval!Date(Date(2013, 7, 9))));
5604 --------------------
5605       +/
5606     bool isBefore(in NegInfInterval interval) const pure nothrow
5607     {
5608         return false;
5609     }
5610 
5611 
5612     /++
5613         Whether this interval is after the given time point.
5614 
5615         Always returns false because an interval beginning at negative infinity
5616         can never be after any time point.
5617 
5618         Params:
5619             timePoint = The time point to check whether this interval is after
5620                         it.
5621 
5622         Example:
5623 --------------------
5624 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
5625 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
5626 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
5627 --------------------
5628       +/
5629     bool isAfter(in TP timePoint) const pure nothrow
5630     {
5631         return false;
5632     }
5633 
5634 
5635     /++
5636         Whether this interval is after the given interval and does not
5637         intersect it.
5638 
5639         Always returns false (unless the given interval is empty) because an
5640         interval beginning at negative infinity can never be after any other
5641         interval.
5642 
5643         Params:
5644             interval = The interval to check against this interval.
5645 
5646         Throws:
5647             $(REF DateTimeException,std,datetime,date) if the given interval
5648             is empty.
5649 
5650         Example:
5651 --------------------
5652 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5653             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5654 
5655 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5656             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
5657 
5658 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5659             Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
5660 --------------------
5661       +/
5662     bool isAfter(in Interval!TP interval) const pure
5663     {
5664         interval._enforceNotEmpty();
5665         return false;
5666     }
5667 
5668 
5669     /++
5670         Whether this interval is after the given interval and does not intersect
5671         it.
5672 
5673         Always returns false because an interval beginning at negative infinity
5674         can never be after any other interval.
5675 
5676         Params:
5677             interval = The interval to check against this interval.
5678 
5679         Example:
5680 --------------------
5681 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5682             PosInfInterval!Date(Date(1999, 5, 4))));
5683 
5684 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5685             PosInfInterval!Date(Date(2012, 3, 1))));
5686 --------------------
5687       +/
5688     bool isAfter(in PosInfInterval!TP interval) const pure nothrow
5689     {
5690         return false;
5691     }
5692 
5693 
5694     /++
5695         Whether this interval is after the given interval and does not intersect
5696         it.
5697 
5698         Always returns false because an interval beginning at negative infinity
5699         can never be after any other interval.
5700 
5701         Params:
5702             interval = The interval to check against this interval.
5703 
5704         Example:
5705 --------------------
5706 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5707             NegInfInterval!Date(Date(1996, 5, 4))));
5708 
5709 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
5710             NegInfInterval!Date(Date(2013, 7, 9))));
5711 --------------------
5712       +/
5713     bool isAfter(in NegInfInterval interval) const pure nothrow
5714     {
5715         return false;
5716     }
5717 
5718 
5719     /++
5720         Whether the given interval overlaps this interval.
5721 
5722         Params:
5723             interval = The interval to check for intersection with this interval.
5724 
5725         Throws:
5726             $(REF DateTimeException,std,datetime,date) if the given interval
5727             is empty.
5728 
5729         Example:
5730 --------------------
5731 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5732             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5733 
5734 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5735             Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
5736 
5737 assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5738             Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
5739 --------------------
5740       +/
5741     bool intersects(in Interval!TP interval) const pure
5742     {
5743         interval._enforceNotEmpty();
5744         return interval._begin < _end;
5745     }
5746 
5747 
5748     /++
5749         Whether the given interval overlaps this interval.
5750 
5751         Params:
5752             interval = The interval to check for intersection with this
5753                        interval.
5754 
5755         Example:
5756 --------------------
5757 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5758             PosInfInterval!Date(Date(1999, 5, 4))));
5759 
5760 assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5761             PosInfInterval!Date(Date(2012, 3, 1))));
5762 --------------------
5763       +/
5764     bool intersects(in PosInfInterval!TP interval) const pure nothrow
5765     {
5766         return interval._begin < _end;
5767     }
5768 
5769 
5770     /++
5771         Whether the given interval overlaps this interval.
5772 
5773         Always returns true because two intervals beginning at negative infinity
5774         always overlap.
5775 
5776         Params:
5777             interval = The interval to check for intersection with this interval.
5778 
5779         Example:
5780 --------------------
5781 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5782             NegInfInterval!Date(Date(1996, 5, 4))));
5783 
5784 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
5785             NegInfInterval!Date(Date(2013, 7, 9))));
5786 --------------------
5787       +/
5788     bool intersects(in NegInfInterval!TP interval) const pure nothrow
5789     {
5790         return true;
5791     }
5792 
5793 
5794     /++
5795         Returns the intersection of two intervals
5796 
5797         Params:
5798             interval = The interval to intersect with this interval.
5799 
5800         Throws:
5801             $(REF DateTimeException,std,datetime,date) if the two intervals do
5802             not intersect or if the given interval is empty.
5803 
5804         Example:
5805 --------------------
5806 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5807             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
5808        Interval!Date(Date(1990, 7 , 6), Date(2000, 8, 2)));
5809 
5810 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5811             Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
5812        Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
5813 --------------------
5814       +/
5815     Interval!TP intersection(in Interval!TP interval) const
5816     {
5817         import std.format : format;
5818 
5819         enforce(this.intersects(interval),
5820                 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
5821 
5822         auto end = _end < interval._end ? _end : interval._end;
5823 
5824         return Interval!TP(interval._begin, end);
5825     }
5826 
5827 
5828     /++
5829         Returns the intersection of two intervals
5830 
5831         Params:
5832             interval = The interval to intersect with this interval.
5833 
5834         Throws:
5835             $(REF DateTimeException,std,datetime,date) if the two intervals do
5836             not intersect.
5837 
5838         Example:
5839 --------------------
5840 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5841             PosInfInterval!Date(Date(1990, 7, 6))) ==
5842        Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
5843 
5844 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5845             PosInfInterval!Date(Date(1999, 1, 12))) ==
5846        Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
5847 --------------------
5848       +/
5849     Interval!TP intersection(in PosInfInterval!TP interval) const
5850     {
5851         import std.format : format;
5852 
5853         enforce(this.intersects(interval),
5854                 new DateTimeException(format("%s and %s do not intersect.", this, interval)));
5855 
5856         return Interval!TP(interval._begin, _end);
5857     }
5858 
5859 
5860     /++
5861         Returns the intersection of two intervals
5862 
5863         Params:
5864             interval = The interval to intersect with this interval.
5865 
5866         Example:
5867 --------------------
5868 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5869             NegInfInterval!Date(Date(1999, 7, 6))) ==
5870        NegInfInterval!Date(Date(1999, 7 , 6)));
5871 
5872 assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
5873             NegInfInterval!Date(Date(2013, 1, 12))) ==
5874        NegInfInterval!Date(Date(2012, 3 , 1)));
5875 --------------------
5876       +/
5877     NegInfInterval intersection(in NegInfInterval interval) const nothrow
5878     {
5879         return NegInfInterval(_end < interval._end ? _end : interval._end);
5880     }
5881 
5882 
5883     /++
5884         Whether the given interval is adjacent to this interval.
5885 
5886         Params:
5887             interval = The interval to check whether its adjecent to this
5888                        interval.
5889 
5890         Throws:
5891             $(REF DateTimeException,std,datetime,date) if the given interval
5892             is empty.
5893 
5894         Example:
5895 --------------------
5896 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5897             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
5898 
5899 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5900             Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1))));
5901 
5902 assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5903             Interval!Date(Date(2012, 3, 1), Date(2019, 2, 2))));
5904 
5905 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5906             Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
5907 --------------------
5908       +/
5909     bool isAdjacent(in Interval!TP interval) const pure
5910     {
5911         interval._enforceNotEmpty();
5912         return interval._begin == _end;
5913     }
5914 
5915 
5916     /++
5917         Whether the given interval is adjacent to this interval.
5918 
5919         Params:
5920             interval = The interval to check whether its adjecent to this
5921                        interval.
5922 
5923         Example:
5924 --------------------
5925 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5926             PosInfInterval!Date(Date(1999, 5, 4))));
5927 
5928 assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5929             PosInfInterval!Date(Date(2012, 3, 1))));
5930 --------------------
5931       +/
5932     bool isAdjacent(in PosInfInterval!TP interval) const pure nothrow
5933     {
5934         return interval._begin == _end;
5935     }
5936 
5937 
5938     /++
5939         Whether the given interval is adjacent to this interval.
5940 
5941         Always returns false because two intervals beginning at negative
5942         infinity can never be adjacent to one another.
5943 
5944         Params:
5945             interval = The interval to check whether its adjecent to this
5946                        interval.
5947 
5948         Example:
5949 --------------------
5950 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5951             NegInfInterval!Date(Date(1996, 5, 4))));
5952 
5953 assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
5954             NegInfInterval!Date(Date(2012, 3, 1))));
5955 --------------------
5956       +/
5957     bool isAdjacent(in NegInfInterval interval) const pure nothrow
5958     {
5959         return false;
5960     }
5961 
5962 
5963     /++
5964         Returns the union of two intervals
5965 
5966         Params:
5967             interval = The interval to merge with this interval.
5968 
5969         Throws:
5970             $(REF DateTimeException,std,datetime,date) if the two intervals do
5971             not intersect and are not adjacent or if the given interval is empty.
5972 
5973         Note:
5974             There is no overload for $(D merge) which takes a
5975             $(D PosInfInterval), because an interval
5976             going from negative infinity to positive infinity
5977             is not possible.
5978 
5979         Example:
5980 --------------------
5981 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
5982             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
5983        NegInfInterval!Date(Date(2012, 3 , 1)));
5984 
5985 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
5986             Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
5987        NegInfInterval!Date(Date(2015, 9 , 2)));
5988 --------------------
5989       +/
5990     NegInfInterval merge(in Interval!TP interval) const
5991     {
5992         import std.format : format;
5993 
5994         enforce(this.isAdjacent(interval) || this.intersects(interval),
5995                 new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
5996 
5997         return NegInfInterval(_end > interval._end ? _end : interval._end);
5998     }
5999 
6000 
6001     /++
6002         Returns the union of two intervals
6003 
6004         Params:
6005             interval = The interval to merge with this interval.
6006 
6007         Note:
6008             There is no overload for $(D merge) which takes a
6009             $(D PosInfInterval), because an interval
6010             going from negative infinity to positive infinity
6011             is not possible.
6012 
6013         Example:
6014 --------------------
6015 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
6016             NegInfInterval!Date(Date(1999, 7, 6))) ==
6017        NegInfInterval!Date(Date(2012, 3 , 1)));
6018 
6019 assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
6020             NegInfInterval!Date(Date(2013, 1, 12))) ==
6021        NegInfInterval!Date(Date(2013, 1 , 12)));
6022 --------------------
6023       +/
6024     NegInfInterval merge(in NegInfInterval interval) const pure nothrow
6025     {
6026         return NegInfInterval(_end > interval._end ? _end : interval._end);
6027     }
6028 
6029 
6030     /++
6031         Returns an interval that covers from the earliest time point of two
6032         intervals up to (but not including) the latest time point of two
6033         intervals.
6034 
6035         Params:
6036             interval = The interval to create a span together with this
6037                        interval.
6038 
6039         Throws:
6040             $(REF DateTimeException,std,datetime,date) if the given interval
6041             is empty.
6042 
6043         Note:
6044             There is no overload for $(D span) which takes a
6045             $(D PosInfInterval), because an interval
6046             going from negative infinity to positive infinity
6047             is not possible.
6048 
6049         Example:
6050 --------------------
6051 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
6052             Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
6053        NegInfInterval!Date(Date(2012, 3 , 1)));
6054 
6055 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
6056             Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
6057        NegInfInterval!Date(Date(2015, 9 , 2)));
6058 
6059 assert(NegInfInterval!Date(Date(1600, 1, 7)).span(
6060             Interval!Date(Date(2012, 3, 11), Date(2017, 7, 1))) ==
6061        NegInfInterval!Date(Date(2017, 7 , 1)));
6062 --------------------
6063       +/
6064     NegInfInterval span(in Interval!TP interval) const pure
6065     {
6066         interval._enforceNotEmpty();
6067         return NegInfInterval(_end > interval._end ? _end : interval._end);
6068     }
6069 
6070 
6071     /++
6072         Returns an interval that covers from the earliest time point of two
6073         intervals up to (but not including) the latest time point of two
6074         intervals.
6075 
6076         Params:
6077             interval = The interval to create a span together with this
6078                        interval.
6079 
6080         Note:
6081             There is no overload for $(D span) which takes a
6082             $(D PosInfInterval), because an interval
6083             going from negative infinity to positive infinity
6084             is not possible.
6085 
6086         Example:
6087 --------------------
6088 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
6089             NegInfInterval!Date(Date(1999, 7, 6))) ==
6090        NegInfInterval!Date(Date(2012, 3 , 1)));
6091 
6092 assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
6093             NegInfInterval!Date(Date(2013, 1, 12))) ==
6094        NegInfInterval!Date(Date(2013, 1 , 12)));
6095 --------------------
6096       +/
6097     NegInfInterval span(in NegInfInterval interval) const pure nothrow
6098     {
6099         return NegInfInterval(_end > interval._end ? _end : interval._end);
6100     }
6101 
6102 
6103     /++
6104         Shifts the $(D end) of this interval forward or backwards in time by the
6105         given duration (a positive duration shifts the interval forward; a
6106         negative duration shifts it backward). Effectively, it does
6107         $(D end += duration).
6108 
6109         Params:
6110             duration = The duration to shift the interval by.
6111 
6112         Example:
6113 --------------------
6114 auto interval1 = NegInfInterval!Date(Date(2012, 4, 5));
6115 auto interval2 = NegInfInterval!Date(Date(2012, 4, 5));
6116 
6117 interval1.shift(dur!"days"(50));
6118 assert(interval1 == NegInfInterval!Date(Date(2012, 5, 25)));
6119 
6120 interval2.shift(dur!"days"(-50));
6121 assert(interval2 == NegInfInterval!Date( Date(2012, 2, 15)));
6122 --------------------
6123       +/
6124     void shift(D)(D duration) pure nothrow
6125         if (__traits(compiles, end + duration))
6126     {
6127         _end += duration;
6128     }
6129 
6130 
6131     static if (__traits(compiles, end.add!"months"(1)) &&
6132                __traits(compiles, end.add!"years"(1)))
6133     {
6134         /++
6135             Shifts the $(D end) of this interval forward or backwards in time by
6136             the given number of years and/or months (a positive number of years
6137             and months shifts the interval forward; a negative number shifts it
6138             backward). It adds the years the given years and months to end. It
6139             effectively calls $(D add!"years"()) and then $(D add!"months"())
6140             on end with the given number of years and months.
6141 
6142             Params:
6143                 years         = The number of years to shift the interval by.
6144                 months        = The number of months to shift the interval by.
6145                 allowOverflow = Whether the days should be allowed to overflow
6146                                 on $(D end), causing its month to increment.
6147 
6148             Throws:
6149                 $(REF DateTimeException,std,datetime,date) if empty is true or
6150                 if the resulting interval would be invalid.
6151 
6152             Example:
6153 --------------------
6154 auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
6155 auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
6156 
6157 interval1.shift(2);
6158 assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
6159 
6160 interval2.shift(-2);
6161 assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
6162 --------------------
6163           +/
6164         void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
6165             if (isIntegral!T)
6166         {
6167             auto end = _end;
6168 
6169             end.add!"years"(years, allowOverflow);
6170             end.add!"months"(months, allowOverflow);
6171 
6172             _end = end;
6173         }
6174     }
6175 
6176 
6177     /++
6178         Expands the interval forwards in time. Effectively, it does
6179         $(D end += duration).
6180 
6181         Params:
6182             duration = The duration to expand the interval by.
6183 
6184         Example:
6185 --------------------
6186 auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
6187 auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
6188 
6189 interval1.expand(dur!"days"(2));
6190 assert(interval1 == NegInfInterval!Date(Date(2012, 3, 3)));
6191 
6192 interval2.expand(dur!"days"(-2));
6193 assert(interval2 == NegInfInterval!Date(Date(2012, 2, 28)));
6194 --------------------
6195       +/
6196     void expand(D)(D duration) pure nothrow
6197         if (__traits(compiles, end + duration))
6198     {
6199         _end += duration;
6200     }
6201 
6202 
6203     static if (__traits(compiles, end.add!"months"(1)) &&
6204                __traits(compiles, end.add!"years"(1)))
6205     {
6206         /++
6207             Expands the interval forwards and/or backwards in time. Effectively,
6208             it adds the given number of months/years to end.
6209 
6210             Params:
6211                 years         = The number of years to expand the interval by.
6212                 months        = The number of months to expand the interval by.
6213                 allowOverflow = Whether the days should be allowed to overflow
6214                                 on $(D end), causing their month to increment.
6215 
6216             Throws:
6217                 $(REF DateTimeException,std,datetime,date) if empty is true or
6218                 if the resulting interval would be invalid.
6219 
6220             Example:
6221 --------------------
6222 auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
6223 auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
6224 
6225 interval1.expand(2);
6226 assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
6227 
6228 interval2.expand(-2);
6229 assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
6230 --------------------
6231           +/
6232         void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
6233             if (isIntegral!T)
6234         {
6235             auto end = _end;
6236 
6237             end.add!"years"(years, allowOverflow);
6238             end.add!"months"(months, allowOverflow);
6239 
6240             _end = end;
6241         }
6242     }
6243 
6244 
6245     /++
6246         Returns a range which iterates backwards over the interval, starting
6247         at $(D end), using $(D_PARAM func) to generate each successive time
6248         point.
6249 
6250         The range's $(D front) is the interval's $(D end). $(D_PARAM func) is
6251         used to generate the next $(D front) when $(D popFront) is called. If
6252         $(D_PARAM popFirst) is $(D PopFirst.yes), then $(D popFront) is called
6253         before the range is returned (so that $(D front) is a time point which
6254         $(D_PARAM func) would generate).
6255 
6256         If $(D_PARAM func) ever generates a time point greater than or equal to
6257         the current $(D front) of the range, then a
6258         $(REF DateTimeException,std,datetime,date) will be thrown.
6259 
6260         There are helper functions in this module which generate common
6261         delegates to pass to $(D bwdRange). Their documentation starts with
6262         "Range-generating function," to make them easily searchable.
6263 
6264         Params:
6265             func     = The function used to generate the time points of the
6266                        range over the interval.
6267             popFirst = Whether $(D popFront) should be called on the range
6268                        before returning it.
6269 
6270         Throws:
6271             $(REF DateTimeException,std,datetime,date) if this interval is
6272             empty.
6273 
6274         Warning:
6275             $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
6276             would be a function pointer to a pure function, but forcing
6277             $(D_PARAM func) to be pure is far too restrictive to be useful, and
6278             in order to have the ease of use of having functions which generate
6279             functions to pass to $(D fwdRange), $(D_PARAM func) must be a
6280             delegate.
6281 
6282             If $(D_PARAM func) retains state which changes as it is called, then
6283             some algorithms will not work correctly, because the range's
6284             $(D save) will have failed to have really saved the range's state.
6285             To avoid such bugs, don't pass a delegate which is
6286             not logically pure to $(D fwdRange). If $(D_PARAM func) is given the
6287             same time point with two different calls, it must return the same
6288             result both times.
6289 
6290             Of course, none of the functions in this module have this problem,
6291             so it's only relevant for custom delegates.
6292 
6293         Example:
6294 --------------------
6295 auto interval = NegInfInterval!Date(Date(2010, 9, 9));
6296 auto func = delegate (in Date date) //For iterating over even-numbered days.
6297             {
6298                 if ((date.day & 1) == 0)
6299                     return date - dur!"days"(2);
6300 
6301                 return date - dur!"days"(1);
6302             };
6303 auto range = interval.bwdRange(func);
6304 
6305 assert(range.front == Date(2010, 9, 9)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
6306 
6307 range.popFront();
6308 assert(range.front == Date(2010, 9, 8));
6309 
6310 range.popFront();
6311 assert(range.front == Date(2010, 9, 6));
6312 
6313 range.popFront();
6314 assert(range.front == Date(2010, 9, 4));
6315 
6316 range.popFront();
6317 assert(range.front == Date(2010, 9, 2));
6318 
6319 range.popFront();
6320 assert(!range.empty);
6321 --------------------
6322       +/
6323     NegInfIntervalRange!(TP) bwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
6324     {
6325         auto range = NegInfIntervalRange!(TP)(this, func);
6326 
6327         if (popFirst == PopFirst.yes)
6328             range.popFront();
6329 
6330         return range;
6331     }
6332 
6333 
6334     /+
6335         Converts this interval to a string.
6336       +/
6337     //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
6338     //have versions of toString() with extra modifiers, so we define one version
6339     //with modifiers and one without.
6340     string toString()
6341     {
6342         return _toStringImpl();
6343     }
6344 
6345 
6346     /++
6347         Converts this interval to a string.
6348       +/
6349     //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
6350     //have versions of toString() with extra modifiers, so we define one version
6351     //with modifiers and one without.
6352     string toString() const nothrow
6353     {
6354         return _toStringImpl();
6355     }
6356 
6357 private:
6358 
6359     /+
6360         Since we have two versions of toString(), we have _toStringImpl()
6361         so that they can share implementations.
6362       +/
6363     string _toStringImpl() const nothrow
6364     {
6365         import std.format : format;
6366         try
6367             return format("[-∞ - %s)", _end);
6368         catch (Exception e)
6369             assert(0, "format() threw.");
6370     }
6371 
6372 
6373     TP _end;
6374 }
6375 
6376 //Test NegInfInterval's constructor.
6377 @safe unittest
6378 {
6379     import std.datetime.date;
6380     import std.datetime.systime;
6381 
6382     NegInfInterval!Date(Date.init);
6383     NegInfInterval!TimeOfDay(TimeOfDay.init);
6384     NegInfInterval!DateTime(DateTime.init);
6385     NegInfInterval!SysTime(SysTime(0));
6386 }
6387 
6388 //Test NegInfInterval's end.
6389 @safe unittest
6390 {
6391     import std.datetime.date;
6392 
6393     assert(NegInfInterval!Date(Date(2010, 1, 1)).end == Date(2010, 1, 1));
6394     assert(NegInfInterval!Date(Date(2010, 1, 1)).end == Date(2010, 1, 1));
6395     assert(NegInfInterval!Date(Date(1998, 1, 1)).end == Date(1998, 1, 1));
6396 
6397     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6398     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6399     assert(cNegInfInterval.end != Date.init);
6400     assert(iNegInfInterval.end != Date.init);
6401 
6402     //Verify Examples.
6403     assert(NegInfInterval!Date(Date(2012, 3, 1)).end == Date(2012, 3, 1));
6404 }
6405 
6406 //Test NegInfInterval's empty.
6407 @safe unittest
6408 {
6409     import std.datetime.date;
6410     import std.datetime.systime;
6411 
6412     assert(!NegInfInterval!Date(Date(2010, 1, 1)).empty);
6413     assert(!NegInfInterval!TimeOfDay(TimeOfDay(0, 30, 0)).empty);
6414     assert(!NegInfInterval!DateTime(DateTime(2010, 1, 1, 0, 30, 0)).empty);
6415     assert(!NegInfInterval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0))).empty);
6416 
6417     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6418     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6419     assert(!cNegInfInterval.empty);
6420     assert(!iNegInfInterval.empty);
6421 
6422     //Verify Examples.
6423     assert(!NegInfInterval!Date(Date(1996, 1, 2)).empty);
6424 }
6425 
6426 //Test NegInfInterval's contains(time point).
6427 @safe unittest
6428 {
6429     import std.datetime.date;
6430 
6431     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6432 
6433     assert(negInfInterval.contains(Date(2009, 7, 4)));
6434     assert(negInfInterval.contains(Date(2010, 7, 3)));
6435     assert(negInfInterval.contains(Date(2010, 7, 4)));
6436     assert(negInfInterval.contains(Date(2010, 7, 5)));
6437     assert(negInfInterval.contains(Date(2011, 7, 1)));
6438     assert(negInfInterval.contains(Date(2012, 1, 6)));
6439     assert(!negInfInterval.contains(Date(2012, 1, 7)));
6440     assert(!negInfInterval.contains(Date(2012, 1, 8)));
6441     assert(!negInfInterval.contains(Date(2013, 1, 7)));
6442 
6443     const cdate = Date(2010, 7, 6);
6444     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6445     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6446     assert(negInfInterval.contains(cdate));
6447     assert(cNegInfInterval.contains(cdate));
6448     assert(iNegInfInterval.contains(cdate));
6449 
6450     //Verify Examples.
6451     assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
6452     assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
6453     assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
6454 }
6455 
6456 //Test NegInfInterval's contains(Interval).
6457 @safe unittest
6458 {
6459     import std.datetime.date;
6460 
6461     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6462 
6463     static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
6464     {
6465         negInfInterval.contains(interval);
6466     }
6467 
6468     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6469 
6470     assert(negInfInterval.contains(negInfInterval));
6471     assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
6472     assert(!negInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
6473     assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
6474     assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
6475     assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
6476     assert(!negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
6477     assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
6478     assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
6479     assert(negInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
6480     assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
6481     assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6482     assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6483 
6484     assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
6485     assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
6486     assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
6487     assert(negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
6488     assert(negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
6489     assert(!negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
6490 
6491     assert(!NegInfInterval!Date(Date(2010, 7, 3)).contains(negInfInterval));
6492     assert(!NegInfInterval!Date(Date(2010, 7, 4)).contains(negInfInterval));
6493     assert(!NegInfInterval!Date(Date(2010, 7, 5)).contains(negInfInterval));
6494     assert(!NegInfInterval!Date(Date(2012, 1, 6)).contains(negInfInterval));
6495     assert(NegInfInterval!Date(Date(2012, 1, 7)).contains(negInfInterval));
6496     assert(NegInfInterval!Date(Date(2012, 1, 8)).contains(negInfInterval));
6497 
6498     assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
6499     assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
6500     assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
6501     assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
6502     assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
6503     assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
6504 
6505     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6506     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6507     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6508     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6509     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6510     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6511     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6512     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6513     assert(negInfInterval.contains(interval));
6514     assert(negInfInterval.contains(cInterval));
6515     assert(negInfInterval.contains(iInterval));
6516     assert(!negInfInterval.contains(posInfInterval));
6517     assert(!negInfInterval.contains(cPosInfInterval));
6518     assert(!negInfInterval.contains(iPosInfInterval));
6519     assert(negInfInterval.contains(negInfInterval));
6520     assert(negInfInterval.contains(cNegInfInterval));
6521     assert(negInfInterval.contains(iNegInfInterval));
6522     assert(cNegInfInterval.contains(interval));
6523     assert(cNegInfInterval.contains(cInterval));
6524     assert(cNegInfInterval.contains(iInterval));
6525     assert(!cNegInfInterval.contains(posInfInterval));
6526     assert(!cNegInfInterval.contains(cPosInfInterval));
6527     assert(!cNegInfInterval.contains(iPosInfInterval));
6528     assert(cNegInfInterval.contains(negInfInterval));
6529     assert(cNegInfInterval.contains(cNegInfInterval));
6530     assert(cNegInfInterval.contains(iNegInfInterval));
6531     assert(iNegInfInterval.contains(interval));
6532     assert(iNegInfInterval.contains(cInterval));
6533     assert(iNegInfInterval.contains(iInterval));
6534     assert(!iNegInfInterval.contains(posInfInterval));
6535     assert(!iNegInfInterval.contains(cPosInfInterval));
6536     assert(!iNegInfInterval.contains(iPosInfInterval));
6537     assert(iNegInfInterval.contains(negInfInterval));
6538     assert(iNegInfInterval.contains(cNegInfInterval));
6539     assert(iNegInfInterval.contains(iNegInfInterval));
6540 
6541     //Verify Examples.
6542     assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
6543     assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
6544     assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
6545 
6546     assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
6547 
6548     assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
6549     assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(2013, 7, 9))));
6550 }
6551 
6552 //Test NegInfInterval's isBefore(time point).
6553 @safe unittest
6554 {
6555     import std.datetime.date;
6556 
6557     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6558 
6559     assert(!negInfInterval.isBefore(Date(2009, 7, 4)));
6560     assert(!negInfInterval.isBefore(Date(2010, 7, 3)));
6561     assert(!negInfInterval.isBefore(Date(2010, 7, 4)));
6562     assert(!negInfInterval.isBefore(Date(2010, 7, 5)));
6563     assert(!negInfInterval.isBefore(Date(2011, 7, 1)));
6564     assert(!negInfInterval.isBefore(Date(2012, 1, 6)));
6565     assert(negInfInterval.isBefore(Date(2012, 1, 7)));
6566     assert(negInfInterval.isBefore(Date(2012, 1, 8)));
6567     assert(negInfInterval.isBefore(Date(2013, 1, 7)));
6568 
6569     const cdate = Date(2010, 7, 6);
6570     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6571     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6572     assert(!negInfInterval.isBefore(cdate));
6573     assert(!cNegInfInterval.isBefore(cdate));
6574     assert(!iNegInfInterval.isBefore(cdate));
6575 
6576     //Verify Examples.
6577     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
6578     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
6579     assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
6580 }
6581 
6582 //Test NegInfInterval's isBefore(Interval).
6583 @safe unittest
6584 {
6585     import std.datetime.date;
6586 
6587     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6588 
6589     static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
6590     {
6591         negInfInterval.isBefore(interval);
6592     }
6593 
6594     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6595 
6596     assert(!negInfInterval.isBefore(negInfInterval));
6597     assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
6598     assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
6599     assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
6600     assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
6601     assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
6602     assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
6603     assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
6604     assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
6605     assert(!negInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
6606     assert(!negInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
6607     assert(negInfInterval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6608     assert(negInfInterval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6609 
6610     assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
6611     assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
6612     assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
6613     assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
6614     assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
6615     assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
6616 
6617     assert(!NegInfInterval!Date(Date(2010, 7, 3)).isBefore(negInfInterval));
6618     assert(!NegInfInterval!Date(Date(2010, 7, 4)).isBefore(negInfInterval));
6619     assert(!NegInfInterval!Date(Date(2010, 7, 5)).isBefore(negInfInterval));
6620     assert(!NegInfInterval!Date(Date(2012, 1, 6)).isBefore(negInfInterval));
6621     assert(!NegInfInterval!Date(Date(2012, 1, 7)).isBefore(negInfInterval));
6622     assert(!NegInfInterval!Date(Date(2012, 1, 8)).isBefore(negInfInterval));
6623 
6624     assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
6625     assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
6626     assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
6627     assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
6628     assert(negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
6629     assert(negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
6630 
6631     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6632     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6633     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6634     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6635     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6636     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6637     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6638     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6639     assert(!negInfInterval.isBefore(interval));
6640     assert(!negInfInterval.isBefore(cInterval));
6641     assert(!negInfInterval.isBefore(iInterval));
6642     assert(!negInfInterval.isBefore(posInfInterval));
6643     assert(!negInfInterval.isBefore(cPosInfInterval));
6644     assert(!negInfInterval.isBefore(iPosInfInterval));
6645     assert(!negInfInterval.isBefore(negInfInterval));
6646     assert(!negInfInterval.isBefore(cNegInfInterval));
6647     assert(!negInfInterval.isBefore(iNegInfInterval));
6648     assert(!cNegInfInterval.isBefore(interval));
6649     assert(!cNegInfInterval.isBefore(cInterval));
6650     assert(!cNegInfInterval.isBefore(iInterval));
6651     assert(!cNegInfInterval.isBefore(posInfInterval));
6652     assert(!cNegInfInterval.isBefore(cPosInfInterval));
6653     assert(!cNegInfInterval.isBefore(iPosInfInterval));
6654     assert(!cNegInfInterval.isBefore(negInfInterval));
6655     assert(!cNegInfInterval.isBefore(cNegInfInterval));
6656     assert(!cNegInfInterval.isBefore(iNegInfInterval));
6657     assert(!iNegInfInterval.isBefore(interval));
6658     assert(!iNegInfInterval.isBefore(cInterval));
6659     assert(!iNegInfInterval.isBefore(iInterval));
6660     assert(!iNegInfInterval.isBefore(posInfInterval));
6661     assert(!iNegInfInterval.isBefore(cPosInfInterval));
6662     assert(!iNegInfInterval.isBefore(iPosInfInterval));
6663     assert(!iNegInfInterval.isBefore(negInfInterval));
6664     assert(!iNegInfInterval.isBefore(cNegInfInterval));
6665     assert(!iNegInfInterval.isBefore(iNegInfInterval));
6666 
6667     //Verify Examples.
6668     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
6669     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
6670     assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
6671 
6672     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
6673     assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2012, 3, 1))));
6674 
6675     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
6676     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(2013, 7, 9))));
6677 }
6678 
6679 //Test NegInfInterval's isAfter(time point).
6680 @safe unittest
6681 {
6682     import std.datetime.date;
6683 
6684     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6685 
6686     assert(!negInfInterval.isAfter(Date(2009, 7, 4)));
6687     assert(!negInfInterval.isAfter(Date(2010, 7, 3)));
6688     assert(!negInfInterval.isAfter(Date(2010, 7, 4)));
6689     assert(!negInfInterval.isAfter(Date(2010, 7, 5)));
6690     assert(!negInfInterval.isAfter(Date(2011, 7, 1)));
6691     assert(!negInfInterval.isAfter(Date(2012, 1, 6)));
6692     assert(!negInfInterval.isAfter(Date(2012, 1, 7)));
6693     assert(!negInfInterval.isAfter(Date(2012, 1, 8)));
6694     assert(!negInfInterval.isAfter(Date(2013, 1, 7)));
6695 
6696     const cdate = Date(2010, 7, 6);
6697     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6698     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6699     assert(!negInfInterval.isAfter(cdate));
6700     assert(!cNegInfInterval.isAfter(cdate));
6701     assert(!iNegInfInterval.isAfter(cdate));
6702 }
6703 
6704 //Test NegInfInterval's isAfter(Interval).
6705 @safe unittest
6706 {
6707     import std.datetime.date;
6708 
6709     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6710 
6711     static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
6712     {
6713         negInfInterval.isAfter(interval);
6714     }
6715 
6716     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6717 
6718     assert(!negInfInterval.isAfter(negInfInterval));
6719     assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
6720     assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
6721     assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
6722     assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
6723     assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
6724     assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
6725     assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
6726     assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
6727     assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
6728     assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
6729     assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6730     assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6731 
6732     assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
6733     assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
6734     assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
6735     assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
6736     assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
6737     assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
6738 
6739     assert(!NegInfInterval!Date(Date(2010, 7, 3)).isAfter(negInfInterval));
6740     assert(!NegInfInterval!Date(Date(2010, 7, 4)).isAfter(negInfInterval));
6741     assert(!NegInfInterval!Date(Date(2010, 7, 5)).isAfter(negInfInterval));
6742     assert(!NegInfInterval!Date(Date(2012, 1, 6)).isAfter(negInfInterval));
6743     assert(!NegInfInterval!Date(Date(2012, 1, 7)).isAfter(negInfInterval));
6744     assert(!NegInfInterval!Date(Date(2012, 1, 8)).isAfter(negInfInterval));
6745 
6746     assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
6747     assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
6748     assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
6749     assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
6750     assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
6751     assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
6752 
6753     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6754     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6755     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6756     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6757     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6758     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6759     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6760     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6761     assert(!negInfInterval.isAfter(interval));
6762     assert(!negInfInterval.isAfter(cInterval));
6763     assert(!negInfInterval.isAfter(iInterval));
6764     assert(!negInfInterval.isAfter(posInfInterval));
6765     assert(!negInfInterval.isAfter(cPosInfInterval));
6766     assert(!negInfInterval.isAfter(iPosInfInterval));
6767     assert(!negInfInterval.isAfter(negInfInterval));
6768     assert(!negInfInterval.isAfter(cNegInfInterval));
6769     assert(!negInfInterval.isAfter(iNegInfInterval));
6770     assert(!cNegInfInterval.isAfter(interval));
6771     assert(!cNegInfInterval.isAfter(cInterval));
6772     assert(!cNegInfInterval.isAfter(iInterval));
6773     assert(!cNegInfInterval.isAfter(posInfInterval));
6774     assert(!cNegInfInterval.isAfter(cPosInfInterval));
6775     assert(!cNegInfInterval.isAfter(iPosInfInterval));
6776     assert(!cNegInfInterval.isAfter(negInfInterval));
6777     assert(!cNegInfInterval.isAfter(cNegInfInterval));
6778     assert(!cNegInfInterval.isAfter(iNegInfInterval));
6779     assert(!iNegInfInterval.isAfter(interval));
6780     assert(!iNegInfInterval.isAfter(cInterval));
6781     assert(!iNegInfInterval.isAfter(iInterval));
6782     assert(!iNegInfInterval.isAfter(posInfInterval));
6783     assert(!iNegInfInterval.isAfter(cPosInfInterval));
6784     assert(!iNegInfInterval.isAfter(iPosInfInterval));
6785     assert(!iNegInfInterval.isAfter(negInfInterval));
6786     assert(!iNegInfInterval.isAfter(cNegInfInterval));
6787     assert(!iNegInfInterval.isAfter(iNegInfInterval));
6788 
6789     //Verify Examples.
6790     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
6791     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
6792     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
6793 
6794     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
6795     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
6796     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
6797 
6798     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
6799     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(2012, 3, 1))));
6800 
6801     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 5, 4))));
6802     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(2013, 7, 9))));
6803 }
6804 
6805 //Test NegInfInterval's intersects().
6806 @safe unittest
6807 {
6808     import std.datetime.date;
6809 
6810     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6811 
6812     static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
6813     {
6814         negInfInterval.intersects(interval);
6815     }
6816 
6817     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6818 
6819     assert(negInfInterval.intersects(negInfInterval));
6820     assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
6821     assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
6822     assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
6823     assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
6824     assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
6825     assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
6826     assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
6827     assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
6828     assert(negInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
6829     assert(negInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
6830     assert(!negInfInterval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6831     assert(!negInfInterval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6832 
6833     assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
6834     assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
6835     assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
6836     assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
6837     assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
6838     assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
6839 
6840     assert(NegInfInterval!Date(Date(2010, 7, 3)).intersects(negInfInterval));
6841     assert(NegInfInterval!Date(Date(2010, 7, 4)).intersects(negInfInterval));
6842     assert(NegInfInterval!Date(Date(2010, 7, 5)).intersects(negInfInterval));
6843     assert(NegInfInterval!Date(Date(2012, 1, 6)).intersects(negInfInterval));
6844     assert(NegInfInterval!Date(Date(2012, 1, 7)).intersects(negInfInterval));
6845     assert(NegInfInterval!Date(Date(2012, 1, 8)).intersects(negInfInterval));
6846 
6847     assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
6848     assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
6849     assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
6850     assert(negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
6851     assert(!negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
6852     assert(!negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
6853 
6854     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6855     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6856     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6857     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6858     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6859     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6860     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6861     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6862     assert(negInfInterval.intersects(interval));
6863     assert(negInfInterval.intersects(cInterval));
6864     assert(negInfInterval.intersects(iInterval));
6865     assert(negInfInterval.intersects(posInfInterval));
6866     assert(negInfInterval.intersects(cPosInfInterval));
6867     assert(negInfInterval.intersects(iPosInfInterval));
6868     assert(negInfInterval.intersects(negInfInterval));
6869     assert(negInfInterval.intersects(cNegInfInterval));
6870     assert(negInfInterval.intersects(iNegInfInterval));
6871     assert(cNegInfInterval.intersects(interval));
6872     assert(cNegInfInterval.intersects(cInterval));
6873     assert(cNegInfInterval.intersects(iInterval));
6874     assert(cNegInfInterval.intersects(posInfInterval));
6875     assert(cNegInfInterval.intersects(cPosInfInterval));
6876     assert(cNegInfInterval.intersects(iPosInfInterval));
6877     assert(cNegInfInterval.intersects(negInfInterval));
6878     assert(cNegInfInterval.intersects(cNegInfInterval));
6879     assert(cNegInfInterval.intersects(iNegInfInterval));
6880     assert(iNegInfInterval.intersects(interval));
6881     assert(iNegInfInterval.intersects(cInterval));
6882     assert(iNegInfInterval.intersects(iInterval));
6883     assert(iNegInfInterval.intersects(posInfInterval));
6884     assert(iNegInfInterval.intersects(cPosInfInterval));
6885     assert(iNegInfInterval.intersects(iPosInfInterval));
6886     assert(iNegInfInterval.intersects(negInfInterval));
6887     assert(iNegInfInterval.intersects(cNegInfInterval));
6888     assert(iNegInfInterval.intersects(iNegInfInterval));
6889 
6890     //Verify Examples.
6891     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
6892     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
6893     assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
6894 
6895     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
6896     assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
6897 
6898     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 5, 4))));
6899     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2013, 7, 9))));
6900 }
6901 
6902 //Test NegInfInterval's intersection().
6903 @safe unittest
6904 {
6905     import std.datetime.date;
6906 
6907     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6908 
testInterval(I,J)6909     static void testInterval(I, J)(in I interval1, in J interval2)
6910     {
6911         interval1.intersection(interval2);
6912     }
6913 
6914     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
6915 
6916     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
6917     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
6918 
6919     assertThrown!DateTimeException(testInterval(negInfInterval, PosInfInterval!Date(Date(2012, 1, 7))));
6920     assertThrown!DateTimeException(testInterval(negInfInterval, PosInfInterval!Date(Date(2012, 1, 8))));
6921 
6922     assert(negInfInterval.intersection(negInfInterval) == negInfInterval);
6923     assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
6924            Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)));
6925     assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
6926            Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
6927     assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
6928            Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)));
6929     assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
6930            Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)));
6931     assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
6932            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
6933     assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
6934            Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
6935     assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
6936            Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
6937     assert(negInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
6938            Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
6939     assert(negInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
6940            Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
6941     assert(negInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
6942            Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
6943 
6944     assert(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 3))) == NegInfInterval!Date(Date(2010, 7, 3)));
6945     assert(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 4))) == NegInfInterval!Date(Date(2010, 7, 4)));
6946     assert(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 5))) == NegInfInterval!Date(Date(2010, 7, 5)));
6947     assert(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 6))) == NegInfInterval!Date(Date(2012, 1, 6)));
6948     assert(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 7))) == NegInfInterval!Date(Date(2012, 1, 7)));
6949     assert(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 8))) == NegInfInterval!Date(Date(2012, 1, 7)));
6950 
6951     assert(NegInfInterval!Date(Date(2010, 7, 3)).intersection(negInfInterval) == NegInfInterval!Date(Date(2010, 7, 3)));
6952     assert(NegInfInterval!Date(Date(2010, 7, 4)).intersection(negInfInterval) == NegInfInterval!Date(Date(2010, 7, 4)));
6953     assert(NegInfInterval!Date(Date(2010, 7, 5)).intersection(negInfInterval) == NegInfInterval!Date(Date(2010, 7, 5)));
6954     assert(NegInfInterval!Date(Date(2012, 1, 6)).intersection(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 6)));
6955     assert(NegInfInterval!Date(Date(2012, 1, 7)).intersection(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
6956     assert(NegInfInterval!Date(Date(2012, 1, 8)).intersection(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
6957 
6958     assert(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 3))) ==
6959            Interval!Date(Date(2010, 7, 3), Date(2012, 1 ,7)));
6960     assert(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 4))) ==
6961            Interval!Date(Date(2010, 7, 4), Date(2012, 1 ,7)));
6962     assert(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 5))) ==
6963            Interval!Date(Date(2010, 7, 5), Date(2012, 1 ,7)));
6964     assert(negInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 6))) ==
6965            Interval!Date(Date(2012, 1, 6), Date(2012, 1 ,7)));
6966 
6967     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6968     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6969     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
6970     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6971     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6972     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
6973     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6974     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
6975     assert(!negInfInterval.intersection(interval).empty);
6976     assert(!negInfInterval.intersection(cInterval).empty);
6977     assert(!negInfInterval.intersection(iInterval).empty);
6978     assert(!negInfInterval.intersection(posInfInterval).empty);
6979     assert(!negInfInterval.intersection(cPosInfInterval).empty);
6980     assert(!negInfInterval.intersection(iPosInfInterval).empty);
6981     assert(!negInfInterval.intersection(negInfInterval).empty);
6982     assert(!negInfInterval.intersection(cNegInfInterval).empty);
6983     assert(!negInfInterval.intersection(iNegInfInterval).empty);
6984     assert(!cNegInfInterval.intersection(interval).empty);
6985     assert(!cNegInfInterval.intersection(cInterval).empty);
6986     assert(!cNegInfInterval.intersection(iInterval).empty);
6987     assert(!cNegInfInterval.intersection(posInfInterval).empty);
6988     assert(!cNegInfInterval.intersection(cPosInfInterval).empty);
6989     assert(!cNegInfInterval.intersection(iPosInfInterval).empty);
6990     assert(!cNegInfInterval.intersection(negInfInterval).empty);
6991     assert(!cNegInfInterval.intersection(cNegInfInterval).empty);
6992     assert(!cNegInfInterval.intersection(iNegInfInterval).empty);
6993     assert(!iNegInfInterval.intersection(interval).empty);
6994     assert(!iNegInfInterval.intersection(cInterval).empty);
6995     assert(!iNegInfInterval.intersection(iInterval).empty);
6996     assert(!iNegInfInterval.intersection(posInfInterval).empty);
6997     assert(!iNegInfInterval.intersection(cPosInfInterval).empty);
6998     assert(!iNegInfInterval.intersection(iPosInfInterval).empty);
6999     assert(!iNegInfInterval.intersection(negInfInterval).empty);
7000     assert(!iNegInfInterval.intersection(cNegInfInterval).empty);
7001     assert(!iNegInfInterval.intersection(iNegInfInterval).empty);
7002 
7003     //Verify Examples.
7004     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
7005            Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2)));
7006     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
7007            Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1)));
7008 
7009     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) ==
7010            Interval!Date(Date(1990, 7, 6), Date(2012, 3, 1)));
7011     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) ==
7012            Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1)));
7013 
7014     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) ==
7015            NegInfInterval!Date(Date(1999, 7, 6)));
7016     assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) ==
7017            NegInfInterval!Date(Date(2012, 3, 1)));
7018 }
7019 
7020 //Test NegInfInterval's isAdjacent().
7021 @safe unittest
7022 {
7023     import std.datetime.date;
7024 
7025     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7026 
7027     static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
7028     {
7029         negInfInterval.isAdjacent(interval);
7030     }
7031 
7032     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
7033 
7034     assert(!negInfInterval.isAdjacent(negInfInterval));
7035     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
7036     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
7037     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
7038     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
7039     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
7040     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
7041     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
7042     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
7043     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
7044     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
7045     assert(negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
7046     assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
7047 
7048     assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
7049     assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
7050     assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
7051     assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
7052     assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
7053     assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
7054 
7055     assert(!NegInfInterval!Date(Date(2010, 7, 3)).isAdjacent(negInfInterval));
7056     assert(!NegInfInterval!Date(Date(2010, 7, 4)).isAdjacent(negInfInterval));
7057     assert(!NegInfInterval!Date(Date(2010, 7, 5)).isAdjacent(negInfInterval));
7058     assert(!NegInfInterval!Date(Date(2012, 1, 6)).isAdjacent(negInfInterval));
7059     assert(!NegInfInterval!Date(Date(2012, 1, 7)).isAdjacent(negInfInterval));
7060     assert(!NegInfInterval!Date(Date(2012, 1, 8)).isAdjacent(negInfInterval));
7061 
7062     assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
7063     assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
7064     assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
7065     assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
7066     assert(negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
7067     assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
7068 
7069     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7070     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7071     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7072     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7073     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7074     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7075     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7076     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7077     assert(!negInfInterval.isAdjacent(interval));
7078     assert(!negInfInterval.isAdjacent(cInterval));
7079     assert(!negInfInterval.isAdjacent(iInterval));
7080     assert(!negInfInterval.isAdjacent(posInfInterval));
7081     assert(!negInfInterval.isAdjacent(cPosInfInterval));
7082     assert(!negInfInterval.isAdjacent(iPosInfInterval));
7083     assert(!negInfInterval.isAdjacent(negInfInterval));
7084     assert(!negInfInterval.isAdjacent(cNegInfInterval));
7085     assert(!negInfInterval.isAdjacent(iNegInfInterval));
7086     assert(!cNegInfInterval.isAdjacent(interval));
7087     assert(!cNegInfInterval.isAdjacent(cInterval));
7088     assert(!cNegInfInterval.isAdjacent(iInterval));
7089     assert(!cNegInfInterval.isAdjacent(posInfInterval));
7090     assert(!cNegInfInterval.isAdjacent(cPosInfInterval));
7091     assert(!cNegInfInterval.isAdjacent(iPosInfInterval));
7092     assert(!cNegInfInterval.isAdjacent(negInfInterval));
7093     assert(!cNegInfInterval.isAdjacent(cNegInfInterval));
7094     assert(!cNegInfInterval.isAdjacent(iNegInfInterval));
7095     assert(!iNegInfInterval.isAdjacent(interval));
7096     assert(!iNegInfInterval.isAdjacent(cInterval));
7097     assert(!iNegInfInterval.isAdjacent(iInterval));
7098     assert(!iNegInfInterval.isAdjacent(posInfInterval));
7099     assert(!iNegInfInterval.isAdjacent(cPosInfInterval));
7100     assert(!iNegInfInterval.isAdjacent(iPosInfInterval));
7101     assert(!iNegInfInterval.isAdjacent(negInfInterval));
7102     assert(!iNegInfInterval.isAdjacent(cNegInfInterval));
7103     assert(!iNegInfInterval.isAdjacent(iNegInfInterval));
7104 
7105     //Verify Examples.
7106     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
7107     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1))));
7108     assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2012, 3, 1), Date(2019, 2, 2))));
7109     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
7110 
7111     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
7112     assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
7113 
7114     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 5, 4))));
7115     assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(2012, 3, 1))));
7116 }
7117 
7118 //Test NegInfInterval's merge().
7119 @safe unittest
7120 {
7121     import std.datetime.date;
7122 
7123     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7124 
testInterval(I,J)7125     static void testInterval(I, J)(in I interval1, in J interval2)
7126     {
7127         interval1.merge(interval2);
7128     }
7129 
7130     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
7131 
7132     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
7133 
7134     assert(negInfInterval.merge(negInfInterval) == negInfInterval);
7135     assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
7136            NegInfInterval!Date(Date(2012, 1, 7)));
7137     assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
7138            NegInfInterval!Date(Date(2013, 7, 3)));
7139     assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
7140            NegInfInterval!Date(Date(2012, 1, 7)));
7141     assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
7142            NegInfInterval!Date(Date(2012, 1, 7)));
7143     assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
7144            NegInfInterval!Date(Date(2012, 1, 7)));
7145     assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
7146            NegInfInterval!Date(Date(2012, 1, 8)));
7147     assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
7148            NegInfInterval!Date(Date(2012, 1, 7)));
7149     assert(negInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
7150            NegInfInterval!Date(Date(2012, 1, 7)));
7151     assert(negInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
7152            NegInfInterval!Date(Date(2012, 1, 7)));
7153     assert(negInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
7154            NegInfInterval!Date(Date(2012, 1, 8)));
7155     assert(negInfInterval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
7156            NegInfInterval!Date(Date(2012, 1, 8)));
7157 
7158     assert(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 3))) == NegInfInterval!Date(Date(2012, 1, 7)));
7159     assert(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 4))) == NegInfInterval!Date(Date(2012, 1, 7)));
7160     assert(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 5))) == NegInfInterval!Date(Date(2012, 1, 7)));
7161     assert(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 6))) == NegInfInterval!Date(Date(2012, 1, 7)));
7162     assert(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 7))) == NegInfInterval!Date(Date(2012, 1, 7)));
7163     assert(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 8))) == NegInfInterval!Date(Date(2012, 1, 8)));
7164 
7165     assert(NegInfInterval!Date(Date(2010, 7, 3)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7166     assert(NegInfInterval!Date(Date(2010, 7, 4)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7167     assert(NegInfInterval!Date(Date(2010, 7, 5)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7168     assert(NegInfInterval!Date(Date(2012, 1, 6)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7169     assert(NegInfInterval!Date(Date(2012, 1, 7)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7170     assert(NegInfInterval!Date(Date(2012, 1, 8)).merge(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 8)));
7171 
7172     static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 3)))));
7173     static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 4)))));
7174     static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 5)))));
7175     static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 6)))));
7176     static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 7)))));
7177     static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 8)))));
7178 
7179     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7180     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7181     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7182     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7183     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7184     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7185     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7186     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7187     assert(!negInfInterval.merge(interval).empty);
7188     assert(!negInfInterval.merge(cInterval).empty);
7189     assert(!negInfInterval.merge(iInterval).empty);
7190     static assert(!__traits(compiles, negInfInterval.merge(posInfInterval)));
7191     static assert(!__traits(compiles, negInfInterval.merge(cPosInfInterval)));
7192     static assert(!__traits(compiles, negInfInterval.merge(iPosInfInterval)));
7193     assert(!negInfInterval.merge(negInfInterval).empty);
7194     assert(!negInfInterval.merge(cNegInfInterval).empty);
7195     assert(!negInfInterval.merge(iNegInfInterval).empty);
7196     assert(!cNegInfInterval.merge(interval).empty);
7197     assert(!cNegInfInterval.merge(cInterval).empty);
7198     assert(!cNegInfInterval.merge(iInterval).empty);
7199     static assert(!__traits(compiles, cNegInfInterval.merge(posInfInterval)));
7200     static assert(!__traits(compiles, cNegInfInterval.merge(cPosInfInterval)));
7201     static assert(!__traits(compiles, cNegInfInterval.merge(iPosInfInterval)));
7202     assert(!cNegInfInterval.merge(negInfInterval).empty);
7203     assert(!cNegInfInterval.merge(cNegInfInterval).empty);
7204     assert(!cNegInfInterval.merge(iNegInfInterval).empty);
7205     assert(!iNegInfInterval.merge(interval).empty);
7206     assert(!iNegInfInterval.merge(cInterval).empty);
7207     assert(!iNegInfInterval.merge(iInterval).empty);
7208     static assert(!__traits(compiles, iNegInfInterval.merge(posInfInterval)));
7209     static assert(!__traits(compiles, iNegInfInterval.merge(cPosInfInterval)));
7210     static assert(!__traits(compiles, iNegInfInterval.merge(iPosInfInterval)));
7211     assert(!iNegInfInterval.merge(negInfInterval).empty);
7212     assert(!iNegInfInterval.merge(cNegInfInterval).empty);
7213     assert(!iNegInfInterval.merge(iNegInfInterval).empty);
7214 
7215     //Verify Examples.
7216     assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
7217            NegInfInterval!Date(Date(2012, 3, 1)));
7218     assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
7219            NegInfInterval!Date(Date(2015, 9, 2)));
7220 
7221     assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1999, 7, 6))) ==
7222            NegInfInterval!Date(Date(2012, 3, 1)));
7223     assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) ==
7224            NegInfInterval!Date(Date(2013, 1, 12)));
7225 }
7226 
7227 //Test NegInfInterval's span().
7228 @safe unittest
7229 {
7230     import std.datetime.date;
7231 
7232     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7233 
testInterval(I,J)7234     static void testInterval(I, J)(in I interval1, in J interval2)
7235     {
7236         interval1.span(interval2);
7237     }
7238 
7239     assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
7240 
7241     assert(negInfInterval.span(negInfInterval) == negInfInterval);
7242     assert(negInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
7243            NegInfInterval!Date(Date(2012, 1, 7)));
7244     assert(negInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
7245            NegInfInterval!Date(Date(2013, 7, 3)));
7246     assert(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
7247            NegInfInterval!Date(Date(2012, 1, 7)));
7248     assert(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
7249            NegInfInterval!Date(Date(2012, 1, 7)));
7250     assert(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
7251            NegInfInterval!Date(Date(2012, 1, 7)));
7252     assert(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
7253            NegInfInterval!Date(Date(2012, 1, 8)));
7254     assert(negInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
7255            NegInfInterval!Date(Date(2012, 1, 7)));
7256     assert(negInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
7257            NegInfInterval!Date(Date(2012, 1, 7)));
7258     assert(negInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
7259            NegInfInterval!Date(Date(2012, 1, 7)));
7260     assert(negInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
7261            NegInfInterval!Date(Date(2012, 1, 8)));
7262     assert(negInfInterval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
7263            NegInfInterval!Date(Date(2012, 1, 8)));
7264     assert(negInfInterval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
7265            NegInfInterval!Date(Date(2012, 1, 9)));
7266 
7267     assert(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 3))) == NegInfInterval!Date(Date(2012, 1, 7)));
7268     assert(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 4))) == NegInfInterval!Date(Date(2012, 1, 7)));
7269     assert(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 5))) == NegInfInterval!Date(Date(2012, 1, 7)));
7270     assert(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 6))) == NegInfInterval!Date(Date(2012, 1, 7)));
7271     assert(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 7))) == NegInfInterval!Date(Date(2012, 1, 7)));
7272     assert(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 8))) == NegInfInterval!Date(Date(2012, 1, 8)));
7273 
7274     assert(NegInfInterval!Date(Date(2010, 7, 3)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7275     assert(NegInfInterval!Date(Date(2010, 7, 4)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7276     assert(NegInfInterval!Date(Date(2010, 7, 5)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7277     assert(NegInfInterval!Date(Date(2012, 1, 6)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7278     assert(NegInfInterval!Date(Date(2012, 1, 7)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 7)));
7279     assert(NegInfInterval!Date(Date(2012, 1, 8)).span(negInfInterval) == NegInfInterval!Date(Date(2012, 1, 8)));
7280 
7281     static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 3)))));
7282     static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 4)))));
7283     static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 5)))));
7284     static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 6)))));
7285     static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 7)))));
7286     static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 8)))));
7287 
7288     auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7289     const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7290     immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
7291     auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7292     const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7293     immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
7294     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7295     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7296     assert(!negInfInterval.span(interval).empty);
7297     assert(!negInfInterval.span(cInterval).empty);
7298     assert(!negInfInterval.span(iInterval).empty);
7299     static assert(!__traits(compiles, negInfInterval.span(posInfInterval)));
7300     static assert(!__traits(compiles, negInfInterval.span(cPosInfInterval)));
7301     static assert(!__traits(compiles, negInfInterval.span(iPosInfInterval)));
7302     assert(!negInfInterval.span(negInfInterval).empty);
7303     assert(!negInfInterval.span(cNegInfInterval).empty);
7304     assert(!negInfInterval.span(iNegInfInterval).empty);
7305     assert(!cNegInfInterval.span(interval).empty);
7306     assert(!cNegInfInterval.span(cInterval).empty);
7307     assert(!cNegInfInterval.span(iInterval).empty);
7308     static assert(!__traits(compiles, cNegInfInterval.span(posInfInterval)));
7309     static assert(!__traits(compiles, cNegInfInterval.span(cPosInfInterval)));
7310     static assert(!__traits(compiles, cNegInfInterval.span(iPosInfInterval)));
7311     assert(!cNegInfInterval.span(negInfInterval).empty);
7312     assert(!cNegInfInterval.span(cNegInfInterval).empty);
7313     assert(!cNegInfInterval.span(iNegInfInterval).empty);
7314     assert(!iNegInfInterval.span(interval).empty);
7315     assert(!iNegInfInterval.span(cInterval).empty);
7316     assert(!iNegInfInterval.span(iInterval).empty);
7317     static assert(!__traits(compiles, iNegInfInterval.span(posInfInterval)));
7318     static assert(!__traits(compiles, iNegInfInterval.span(cPosInfInterval)));
7319     static assert(!__traits(compiles, iNegInfInterval.span(iPosInfInterval)));
7320     assert(!iNegInfInterval.span(negInfInterval).empty);
7321     assert(!iNegInfInterval.span(cNegInfInterval).empty);
7322     assert(!iNegInfInterval.span(iNegInfInterval).empty);
7323 
7324     //Verify Examples.
7325     assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
7326            NegInfInterval!Date(Date(2012, 3, 1)));
7327     assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
7328            NegInfInterval!Date(Date(2015, 9, 2)));
7329     assert(NegInfInterval!Date(Date(1600, 1, 7)).span(Interval!Date(Date(2012, 3, 11), Date(2017, 7, 1))) ==
7330            NegInfInterval!Date(Date(2017, 7, 1)));
7331 
7332     assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1999, 7, 6))) ==
7333            NegInfInterval!Date(Date(2012, 3, 1)));
7334     assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) ==
7335            NegInfInterval!Date(Date(2013, 1, 12)));
7336 }
7337 
7338 //Test NegInfInterval's shift().
7339 @safe unittest
7340 {
7341     import std.datetime.date;
7342 
7343     auto interval = NegInfInterval!Date(Date(2012, 1, 7));
7344 
testInterval(I)7345     static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
7346     {
7347         interval.shift(duration);
7348         assert(interval == expected);
7349     }
7350 
7351     testInterval(interval, dur!"days"(22), NegInfInterval!Date(Date(2012, 1, 29)));
7352     testInterval(interval, dur!"days"(-22), NegInfInterval!Date(Date(2011, 12, 16)));
7353 
7354     const cInterval = NegInfInterval!Date(Date(2012, 1, 7));
7355     immutable iInterval = NegInfInterval!Date(Date(2012, 1, 7));
7356     static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
7357     static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
7358 
7359     //Verify Examples.
7360     auto interval1 = NegInfInterval!Date(Date(2012, 4, 5));
7361     auto interval2 = NegInfInterval!Date(Date(2012, 4, 5));
7362 
7363     interval1.shift(dur!"days"(50));
7364     assert(interval1 == NegInfInterval!Date(Date(2012, 5, 25)));
7365 
7366     interval2.shift(dur!"days"(-50));
7367     assert(interval2 == NegInfInterval!Date( Date(2012, 2, 15)));
7368 }
7369 
7370 //Test NegInfInterval's shift(int, int, AllowDayOverflow).
7371 @safe unittest
7372 {
7373     import std.datetime.date;
7374 
7375     {
7376         auto interval = NegInfInterval!Date(Date(2012, 1, 7));
7377 
testIntervalFail(I)7378         static void testIntervalFail(I)(I interval, int years, int months)
7379         {
7380             interval.shift(years, months);
7381         }
7382 
testInterval(I)7383         static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
7384                                     in I expected, size_t line = __LINE__)
7385         {
7386             interval.shift(years, months, allow);
7387             assert(interval == expected);
7388         }
7389 
7390         testInterval(interval, 5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2017, 1, 7)));
7391         testInterval(interval, -5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2007, 1, 7)));
7392 
7393         auto interval2 = NegInfInterval!Date(Date(2010, 5, 31));
7394 
7395         testInterval(interval2, 1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 7, 1)));
7396         testInterval(interval2, 1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 5, 1)));
7397         testInterval(interval2, -1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 5, 1)));
7398         testInterval(interval2, -1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 7, 1)));
7399 
7400         testInterval(interval2, 1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 6, 30)));
7401         testInterval(interval2, 1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 4, 30)));
7402         testInterval(interval2, -1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 4, 30)));
7403         testInterval(interval2, -1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 6, 30)));
7404     }
7405 
7406     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7407     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7408     static assert(!__traits(compiles, cNegInfInterval.shift(1)));
7409     static assert(!__traits(compiles, iNegInfInterval.shift(1)));
7410 
7411     //Verify Examples.
7412     auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
7413     auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
7414 
7415     interval1.shift(2);
7416     assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
7417 
7418     interval2.shift(-2);
7419     assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
7420 }
7421 
7422 //Test NegInfInterval's expand().
7423 @safe unittest
7424 {
7425     import std.datetime.date;
7426 
7427     auto interval = NegInfInterval!Date(Date(2012, 1, 7));
7428 
testInterval(I)7429     static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
7430     {
7431         interval.expand(duration);
7432         assert(interval == expected);
7433     }
7434 
7435     testInterval(interval, dur!"days"(22), NegInfInterval!Date(Date(2012, 1, 29)));
7436     testInterval(interval, dur!"days"(-22), NegInfInterval!Date(Date(2011, 12, 16)));
7437 
7438     const cInterval = NegInfInterval!Date(Date(2012, 1, 7));
7439     immutable iInterval = NegInfInterval!Date(Date(2012, 1, 7));
7440     static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
7441     static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
7442 
7443     //Verify Examples.
7444     auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
7445     auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
7446 
7447     interval1.expand(dur!"days"(2));
7448     assert(interval1 == NegInfInterval!Date(Date(2012, 3, 3)));
7449 
7450     interval2.expand(dur!"days"(-2));
7451     assert(interval2 == NegInfInterval!Date(Date(2012, 2, 28)));
7452 }
7453 
7454 //Test NegInfInterval's expand(int, int, AllowDayOverflow).
7455 @safe unittest
7456 {
7457     import std.datetime.date;
7458 
7459     {
7460         auto interval = NegInfInterval!Date(Date(2012, 1, 7));
7461 
testInterval(I)7462         static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
7463                                     in I expected, size_t line = __LINE__)
7464         {
7465             interval.expand(years, months, allow);
7466             assert(interval == expected);
7467         }
7468 
7469         testInterval(interval, 5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2017, 1, 7)));
7470         testInterval(interval, -5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2007, 1, 7)));
7471 
7472         auto interval2 = NegInfInterval!Date(Date(2010, 5, 31));
7473 
7474         testInterval(interval2, 1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 7, 1)));
7475         testInterval(interval2, 1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 5, 1)));
7476         testInterval(interval2, -1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 5, 1)));
7477         testInterval(interval2, -1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 7, 1)));
7478 
7479         testInterval(interval2, 1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 6, 30)));
7480         testInterval(interval2, 1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 4, 30)));
7481         testInterval(interval2, -1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 4, 30)));
7482         testInterval(interval2, -1, 1, AllowDayOverflow.no, NegInfInterval!Date( Date(2009, 6, 30)));
7483     }
7484 
7485     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7486     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7487     static assert(!__traits(compiles, cNegInfInterval.expand(1)));
7488     static assert(!__traits(compiles, iNegInfInterval.expand(1)));
7489 
7490     //Verify Examples.
7491     auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
7492     auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
7493 
7494     interval1.expand(2);
7495     assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
7496 
7497     interval2.expand(-2);
7498     assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
7499 }
7500 
7501 //Test NegInfInterval's bwdRange().
7502 @system unittest
7503 {
7504     import std.datetime.date;
7505 
7506     auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7507 
7508     static void testInterval(NegInfInterval!Date negInfInterval)
7509     {
7510         negInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.fwd)(DayOfWeek.fri)).popFront();
7511     }
7512 
7513     assertThrown!DateTimeException(testInterval(negInfInterval));
7514 
7515     assert(NegInfInterval!Date(Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).front ==
7516            Date(2010, 10, 1));
7517 
7518     assert(NegInfInterval!Date(Date(2010, 10, 1)).bwdRange(
7519                everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).front == Date(2010, 9, 24));
7520 
7521     //Verify Examples.
7522     auto interval = NegInfInterval!Date(Date(2010, 9, 9));
delegate(in Date date)7523     auto func = delegate (in Date date)
7524                 {
7525                     if ((date.day & 1) == 0)
7526                         return date - dur!"days"(2);
7527                     return date - dur!"days"(1);
7528                 };
7529     auto range = interval.bwdRange(func);
7530 
7531     //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
7532     assert(range.front == Date(2010, 9, 9));
7533 
7534     range.popFront();
7535     assert(range.front == Date(2010, 9, 8));
7536 
7537     range.popFront();
7538     assert(range.front == Date(2010, 9, 6));
7539 
7540     range.popFront();
7541     assert(range.front == Date(2010, 9, 4));
7542 
7543     range.popFront();
7544     assert(range.front == Date(2010, 9, 2));
7545 
7546     range.popFront();
7547     assert(!range.empty);
7548 
7549     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7550     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7551     assert(!cNegInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).empty);
7552     assert(!iNegInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).empty);
7553 }
7554 
7555 //Test NegInfInterval's toString().
7556 @safe unittest
7557 {
7558     import std.datetime.date;
7559 
7560     assert(NegInfInterval!Date(Date(2012, 1, 7)).toString() == "[-∞ - 2012-Jan-07)");
7561 
7562     const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7563     immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
7564     assert(cNegInfInterval.toString());
7565     assert(iNegInfInterval.toString());
7566 }
7567 
7568 
7569 /++
7570     Range-generating function.
7571 
7572     Returns a delegate which returns the next time point with the given
7573     $(D DayOfWeek) in a range.
7574 
7575     Using this delegate allows iteration over successive time points which
7576     are all the same day of the week. e.g. passing $(D DayOfWeek.mon) to
7577     $(D everyDayOfWeek) would result in a delegate which could be used to
7578     iterate over all of the Mondays in a range.
7579 
7580     Params:
7581         dir       = The direction to iterate in. If passing the return value to
7582                     $(D fwdRange), use $(D Direction.fwd). If passing it to
7583                     $(D bwdRange), use $(D Direction.bwd).
7584         dayOfWeek = The week that each time point in the range will be.
7585   +/
7586 TP delegate(in TP) everyDayOfWeek(TP, Direction dir = Direction.fwd)(DayOfWeek dayOfWeek) nothrow
7587 if (isTimePoint!TP &&
7588     (dir == Direction.fwd || dir == Direction.bwd) &&
7589     __traits(hasMember, TP, "dayOfWeek") &&
7590     !__traits(isStaticFunction, TP.dayOfWeek) &&
7591     is(typeof(TP.dayOfWeek) == DayOfWeek))
7592 {
func(in TP tp)7593     TP func(in TP tp)
7594     {
7595         TP retval = cast(TP) tp;
7596         immutable days = daysToDayOfWeek(retval.dayOfWeek, dayOfWeek);
7597 
7598         static if (dir == Direction.fwd)
7599             immutable adjustedDays = days == 0 ? 7 : days;
7600         else
7601             immutable adjustedDays = days == 0 ? -7 : days - 7;
7602 
7603         return retval += dur!"days"(adjustedDays);
7604     }
7605 
7606     return &func;
7607 }
7608 
7609 ///
7610 @system unittest
7611 {
7612     import std.datetime.date : Date, DayOfWeek;
7613 
7614     auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
7615     auto func = everyDayOfWeek!Date(DayOfWeek.mon);
7616     auto range = interval.fwdRange(func);
7617 
7618     // A Thursday. Using PopFirst.yes would have made this Date(2010, 9, 6).
7619     assert(range.front == Date(2010, 9, 2));
7620 
7621     range.popFront();
7622     assert(range.front == Date(2010, 9, 6));
7623 
7624     range.popFront();
7625     assert(range.front == Date(2010, 9, 13));
7626 
7627     range.popFront();
7628     assert(range.front == Date(2010, 9, 20));
7629 
7630     range.popFront();
7631     assert(range.empty);
7632 }
7633 
7634 @system unittest
7635 {
7636     import std.datetime.date;
7637     import std.datetime.systime;
7638 
7639     auto funcFwd = everyDayOfWeek!Date(DayOfWeek.mon);
7640     auto funcBwd = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.mon);
7641 
7642     assert(funcFwd(Date(2010, 8, 28)) == Date(2010, 8, 30));
7643     assert(funcFwd(Date(2010, 8, 29)) == Date(2010, 8, 30));
7644     assert(funcFwd(Date(2010, 8, 30)) == Date(2010, 9, 6));
7645     assert(funcFwd(Date(2010, 8, 31)) == Date(2010, 9, 6));
7646     assert(funcFwd(Date(2010, 9, 1)) == Date(2010, 9, 6));
7647     assert(funcFwd(Date(2010, 9, 2)) == Date(2010, 9, 6));
7648     assert(funcFwd(Date(2010, 9, 3)) == Date(2010, 9, 6));
7649     assert(funcFwd(Date(2010, 9, 4)) == Date(2010, 9, 6));
7650     assert(funcFwd(Date(2010, 9, 5)) == Date(2010, 9, 6));
7651     assert(funcFwd(Date(2010, 9, 6)) == Date(2010, 9, 13));
7652     assert(funcFwd(Date(2010, 9, 7)) == Date(2010, 9, 13));
7653 
7654     assert(funcBwd(Date(2010, 8, 28)) == Date(2010, 8, 23));
7655     assert(funcBwd(Date(2010, 8, 29)) == Date(2010, 8, 23));
7656     assert(funcBwd(Date(2010, 8, 30)) == Date(2010, 8, 23));
7657     assert(funcBwd(Date(2010, 8, 31)) == Date(2010, 8, 30));
7658     assert(funcBwd(Date(2010, 9, 1)) == Date(2010, 8, 30));
7659     assert(funcBwd(Date(2010, 9, 2)) == Date(2010, 8, 30));
7660     assert(funcBwd(Date(2010, 9, 3)) == Date(2010, 8, 30));
7661     assert(funcBwd(Date(2010, 9, 4)) == Date(2010, 8, 30));
7662     assert(funcBwd(Date(2010, 9, 5)) == Date(2010, 8, 30));
7663     assert(funcBwd(Date(2010, 9, 6)) == Date(2010, 8, 30));
7664     assert(funcBwd(Date(2010, 9, 7)) == Date(2010, 9, 6));
7665 
7666     static assert(!__traits(compiles, everyDayOfWeek!TimeOfDay(DayOfWeek.mon)));
7667     assert(everyDayOfWeek!DateTime(DayOfWeek.mon) !is null);
7668     assert(everyDayOfWeek!SysTime(DayOfWeek.mon) !is null);
7669 }
7670 
7671 
7672 /++
7673     Range-generating function.
7674 
7675     Returns a delegate which returns the next time point with the given month
7676     which would be reached by adding months to the given time point.
7677 
7678     So, using this delegate allows iteration over successive time points
7679     which are in the same month but different years. For example,
7680     iterate over each successive December 25th in an interval by starting with a
7681     date which had the 25th as its day and passed $(D Month.dec) to
7682     $(D everyMonth) to create the delegate.
7683 
7684     Since it wouldn't really make sense to be iterating over a specific month
7685     and end up with some of the time points in the succeeding month or two years
7686     after the previous time point, $(D AllowDayOverflow.no) is always used when
7687     calculating the next time point.
7688 
7689     Params:
7690         dir   = The direction to iterate in. If passing the return value to
7691                 $(D fwdRange), use $(D Direction.fwd). If passing it to
7692                 $(D bwdRange), use $(D Direction.bwd).
7693         month = The month that each time point in the range will be in
7694                 (January is 1).
7695   +/
7696 TP delegate(in TP) everyMonth(TP, Direction dir = Direction.fwd)(int month)
7697 if (isTimePoint!TP &&
7698     (dir == Direction.fwd || dir == Direction.bwd) &&
7699     __traits(hasMember, TP, "month") &&
7700     !__traits(isStaticFunction, TP.month) &&
7701     is(typeof(TP.month) == Month))
7702 {
7703     import std.datetime.date : enforceValid, monthsToMonth;
7704 
7705     enforceValid!"months"(month);
7706 
func(in TP tp)7707     TP func(in TP tp)
7708     {
7709         TP retval = cast(TP) tp;
7710         immutable months = monthsToMonth(retval.month, month);
7711 
7712         static if (dir == Direction.fwd)
7713             immutable adjustedMonths = months == 0 ? 12 : months;
7714         else
7715             immutable adjustedMonths = months == 0 ? -12 : months - 12;
7716 
7717         retval.add!"months"(adjustedMonths, AllowDayOverflow.no);
7718 
7719         if (retval.month != month)
7720         {
7721             retval.add!"months"(-1);
7722             assert(retval.month == month);
7723         }
7724 
7725         return retval;
7726     }
7727 
7728     return &func;
7729 }
7730 
7731 ///
7732 @system unittest
7733 {
7734     import std.datetime.date : Date, Month;
7735 
7736     auto interval = Interval!Date(Date(2000, 1, 30), Date(2004, 8, 5));
7737     auto func = everyMonth!Date(Month.feb);
7738     auto range = interval.fwdRange(func);
7739 
7740     // Using PopFirst.yes would have made this Date(2010, 2, 29).
7741     assert(range.front == Date(2000, 1, 30));
7742 
7743     range.popFront();
7744     assert(range.front == Date(2000, 2, 29));
7745 
7746     range.popFront();
7747     assert(range.front == Date(2001, 2, 28));
7748 
7749     range.popFront();
7750     assert(range.front == Date(2002, 2, 28));
7751 
7752     range.popFront();
7753     assert(range.front == Date(2003, 2, 28));
7754 
7755     range.popFront();
7756     assert(range.front == Date(2004, 2, 28));
7757 
7758     range.popFront();
7759     assert(range.empty);
7760 }
7761 
7762 @system unittest
7763 {
7764     import std.datetime.date;
7765     import std.datetime.systime;
7766 
7767     auto funcFwd = everyMonth!Date(Month.jun);
7768     auto funcBwd = everyMonth!(Date, Direction.bwd)(Month.jun);
7769 
7770     assert(funcFwd(Date(2010, 5, 31)) == Date(2010, 6, 30));
7771     assert(funcFwd(Date(2010, 6, 30)) == Date(2011, 6, 30));
7772     assert(funcFwd(Date(2010, 7, 31)) == Date(2011, 6, 30));
7773     assert(funcFwd(Date(2010, 8, 31)) == Date(2011, 6, 30));
7774     assert(funcFwd(Date(2010, 9, 30)) == Date(2011, 6, 30));
7775     assert(funcFwd(Date(2010, 10, 31)) == Date(2011, 6, 30));
7776     assert(funcFwd(Date(2010, 11, 30)) == Date(2011, 6, 30));
7777     assert(funcFwd(Date(2010, 12, 31)) == Date(2011, 6, 30));
7778     assert(funcFwd(Date(2011, 1, 31)) == Date(2011, 6, 30));
7779     assert(funcFwd(Date(2011, 2, 28)) == Date(2011, 6, 28));
7780     assert(funcFwd(Date(2011, 3, 31)) == Date(2011, 6, 30));
7781     assert(funcFwd(Date(2011, 4, 30)) == Date(2011, 6, 30));
7782     assert(funcFwd(Date(2011, 5, 31)) == Date(2011, 6, 30));
7783     assert(funcFwd(Date(2011, 6, 30)) == Date(2012, 6, 30));
7784     assert(funcFwd(Date(2011, 7, 31)) == Date(2012, 6, 30));
7785 
7786     assert(funcBwd(Date(2010, 5, 31)) == Date(2009, 6, 30));
7787     assert(funcBwd(Date(2010, 6, 30)) == Date(2009, 6, 30));
7788     assert(funcBwd(Date(2010, 7, 31)) == Date(2010, 6, 30));
7789     assert(funcBwd(Date(2010, 8, 31)) == Date(2010, 6, 30));
7790     assert(funcBwd(Date(2010, 9, 30)) == Date(2010, 6, 30));
7791     assert(funcBwd(Date(2010, 10, 31)) == Date(2010, 6, 30));
7792     assert(funcBwd(Date(2010, 11, 30)) == Date(2010, 6, 30));
7793     assert(funcBwd(Date(2010, 12, 31)) == Date(2010, 6, 30));
7794     assert(funcBwd(Date(2011, 1, 31)) == Date(2010, 6, 30));
7795     assert(funcBwd(Date(2011, 2, 28)) == Date(2010, 6, 28));
7796     assert(funcBwd(Date(2011, 3, 31)) == Date(2010, 6, 30));
7797     assert(funcBwd(Date(2011, 4, 30)) == Date(2010, 6, 30));
7798     assert(funcBwd(Date(2011, 5, 31)) == Date(2010, 6, 30));
7799     assert(funcBwd(Date(2011, 6, 30)) == Date(2010, 6, 30));
7800     assert(funcBwd(Date(2011, 7, 30)) == Date(2011, 6, 30));
7801 
7802     static assert(!__traits(compiles, everyMonth!TimeOfDay(Month.jan)));
7803     assert(everyMonth!DateTime(Month.jan) !is null);
7804     assert(everyMonth!SysTime(Month.jan) !is null);
7805 }
7806 
7807 
7808 /++
7809     Range-generating function.
7810 
7811     Returns a delegate which returns the next time point which is the given
7812     duration later.
7813 
7814     Using this delegate allows iteration over successive time points which
7815     are apart by the given duration e.g. passing $(D dur!"days"(3)) to
7816     $(D everyDuration) would result in a delegate which could be used to iterate
7817     over a range of days which are each 3 days apart.
7818 
7819     Params:
7820         dir      = The direction to iterate in. If passing the return value to
7821                    $(D fwdRange), use $(D Direction.fwd). If passing it to
7822                    $(D bwdRange), use $(D Direction.bwd).
7823         duration = The duration which separates each successive time point in
7824                    the range.
7825   +/
7826 TP delegate(in TP) everyDuration(TP, Direction dir = Direction.fwd, D)(D duration) nothrow
7827 if (isTimePoint!TP &&
7828     __traits(compiles, TP.init + duration) &&
7829     (dir == Direction.fwd || dir == Direction.bwd))
7830 {
7831     TP func(in TP tp)
7832     {
7833         static if (dir == Direction.fwd)
7834             return tp + duration;
7835         else
7836             return tp - duration;
7837     }
7838 
7839     return &func;
7840 }
7841 
7842 ///
7843 @system unittest
7844 {
7845     import core.time : dur;
7846     import std.datetime.date : Date;
7847 
7848     auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
7849     auto func = everyDuration!Date(dur!"days"(8));
7850     auto range = interval.fwdRange(func);
7851 
7852     // Using PopFirst.yes would have made this Date(2010, 9, 10).
7853     assert(range.front == Date(2010, 9, 2));
7854 
7855     range.popFront();
7856     assert(range.front == Date(2010, 9, 10));
7857 
7858     range.popFront();
7859     assert(range.front == Date(2010, 9, 18));
7860 
7861     range.popFront();
7862     assert(range.front == Date(2010, 9, 26));
7863 
7864     range.popFront();
7865     assert(range.empty);
7866 }
7867 
7868 @system unittest
7869 {
7870     import std.datetime.date;
7871     import std.datetime.systime;
7872 
7873     auto funcFwd = everyDuration!Date(dur!"days"(27));
7874     auto funcBwd = everyDuration!(Date, Direction.bwd)(dur!"days"(27));
7875 
7876     assert(funcFwd(Date(2009, 12, 25)) == Date(2010, 1, 21));
7877     assert(funcFwd(Date(2009, 12, 26)) == Date(2010, 1, 22));
7878     assert(funcFwd(Date(2009, 12, 27)) == Date(2010, 1, 23));
7879     assert(funcFwd(Date(2009, 12, 28)) == Date(2010, 1, 24));
7880 
7881     assert(funcBwd(Date(2010, 1, 21)) == Date(2009, 12, 25));
7882     assert(funcBwd(Date(2010, 1, 22)) == Date(2009, 12, 26));
7883     assert(funcBwd(Date(2010, 1, 23)) == Date(2009, 12, 27));
7884     assert(funcBwd(Date(2010, 1, 24)) == Date(2009, 12, 28));
7885 
7886     assert(everyDuration!Date(dur!"hnsecs"(1)) !is null);
7887     assert(everyDuration!TimeOfDay(dur!"hnsecs"(1)) !is null);
7888     assert(everyDuration!DateTime(dur!"hnsecs"(1)) !is null);
7889     assert(everyDuration!SysTime(dur!"hnsecs"(1)) !is null);
7890 }
7891 
7892 
7893 /++
7894     Range-generating function.
7895 
7896     Returns a delegate which returns the next time point which is the given
7897     number of years, month, and duration later.
7898 
7899     The difference between this version of $(D everyDuration) and the version
7900     which just takes a $(REF Duration, core,time) is that this one also takes
7901     the number of years and months (along with an $(D AllowDayOverflow) to
7902     indicate whether adding years and months should allow the days to overflow).
7903 
7904     Note that if iterating forward, $(D add!"years"()) is called on the given
7905     time point, then $(D add!"months"()), and finally the duration is added
7906     to it. However, if iterating backwards, the duration is added first, then
7907     $(D add!"months"()) is called, and finally $(D add!"years"()) is called.
7908     That way, going backwards generates close to the same time points that
7909     iterating forward does, but since adding years and months is not entirely
7910     reversible (due to possible day overflow, regardless of whether
7911     $(D AllowDayOverflow.yes) or $(D AllowDayOverflow.no) is used), it can't be
7912     guaranteed that iterating backwards will give the same time points as
7913     iterating forward would have (even assuming that the end of the range is a
7914     time point which would be returned by the delegate when iterating forward
7915     from $(D begin)).
7916 
7917     Params:
7918         dir           = The direction to iterate in. If passing the return
7919                         value to $(D fwdRange), use $(D Direction.fwd). If
7920                         passing it to $(D bwdRange), use $(D Direction.bwd).
7921         years         = The number of years to add to the time point passed to
7922                         the delegate.
7923         months        = The number of months to add to the time point passed to
7924                         the delegate.
7925         allowOverflow = Whether the days should be allowed to overflow on
7926                         $(D begin) and $(D end), causing their month to
7927                         increment.
7928         duration      = The duration to add to the time point passed to the
7929                         delegate.
7930   +/
7931 TP delegate(in TP) everyDuration(TP, Direction dir = Direction.fwd, D)
7932                                  (int years,
7933                                  int months = 0,
7934                                  AllowDayOverflow allowOverflow = AllowDayOverflow.yes,
7935                                  D duration = dur!"days"(0)) nothrow
7936 if (isTimePoint!TP &&
7937     __traits(compiles, TP.init + duration) &&
7938     __traits(compiles, TP.init.add!"years"(years)) &&
7939     __traits(compiles, TP.init.add!"months"(months)) &&
7940     (dir == Direction.fwd || dir == Direction.bwd))
7941 {
7942     TP func(in TP tp)
7943     {
7944         static if (dir == Direction.fwd)
7945         {
7946             TP retval = cast(TP) tp;
7947 
7948             retval.add!"years"(years, allowOverflow);
7949             retval.add!"months"(months, allowOverflow);
7950 
7951             return retval + duration;
7952         }
7953         else
7954         {
7955             TP retval = tp - duration;
7956 
7957             retval.add!"months"(-months, allowOverflow);
7958             retval.add!"years"(-years, allowOverflow);
7959 
7960             return retval;
7961         }
7962     }
7963 
7964     return &func;
7965 }
7966 
7967 ///
7968 @system unittest
7969 {
7970     import core.time : dur;
7971     import std.datetime.date : AllowDayOverflow, Date;
7972 
7973     auto interval = Interval!Date(Date(2010, 9, 2), Date(2025, 9, 27));
7974     auto func = everyDuration!Date(4, 1, AllowDayOverflow.yes, dur!"days"(2));
7975     auto range = interval.fwdRange(func);
7976 
7977     // Using PopFirst.yes would have made this Date(2014, 10, 12).
7978     assert(range.front == Date(2010, 9, 2));
7979 
7980     range.popFront();
7981     assert(range.front == Date(2014, 10, 4));
7982 
7983     range.popFront();
7984     assert(range.front == Date(2018, 11, 6));
7985 
7986     range.popFront();
7987     assert(range.front == Date(2022, 12, 8));
7988 
7989     range.popFront();
7990     assert(range.empty);
7991 }
7992 
7993 @system unittest
7994 {
7995     import std.datetime.date;
7996     import std.datetime.systime;
7997 
7998     {
7999         auto funcFwd = everyDuration!Date(1, 2, AllowDayOverflow.yes, dur!"days"(3));
8000         auto funcBwd = everyDuration!(Date, Direction.bwd)(1, 2, AllowDayOverflow.yes, dur!"days"(3));
8001 
8002         assert(funcFwd(Date(2009, 12, 25)) == Date(2011, 2, 28));
8003         assert(funcFwd(Date(2009, 12, 26)) == Date(2011, 3, 1));
8004         assert(funcFwd(Date(2009, 12, 27)) == Date(2011, 3, 2));
8005         assert(funcFwd(Date(2009, 12, 28)) == Date(2011, 3, 3));
8006         assert(funcFwd(Date(2009, 12, 29)) == Date(2011, 3, 4));
8007 
8008         assert(funcBwd(Date(2011, 2, 28)) == Date(2009, 12, 25));
8009         assert(funcBwd(Date(2011, 3, 1)) == Date(2009, 12, 26));
8010         assert(funcBwd(Date(2011, 3, 2)) == Date(2009, 12, 27));
8011         assert(funcBwd(Date(2011, 3, 3)) == Date(2009, 12, 28));
8012         assert(funcBwd(Date(2011, 3, 4)) == Date(2010, 1, 1));
8013     }
8014 
8015     {
8016         auto funcFwd = everyDuration!Date(1, 2, AllowDayOverflow.no, dur!"days"(3));
8017         auto funcBwd = everyDuration!(Date, Direction.bwd)(1, 2, AllowDayOverflow.yes, dur!"days"(3));
8018 
8019         assert(funcFwd(Date(2009, 12, 25)) == Date(2011, 2, 28));
8020         assert(funcFwd(Date(2009, 12, 26)) == Date(2011, 3, 1));
8021         assert(funcFwd(Date(2009, 12, 27)) == Date(2011, 3, 2));
8022         assert(funcFwd(Date(2009, 12, 28)) == Date(2011, 3, 3));
8023         assert(funcFwd(Date(2009, 12, 29)) == Date(2011, 3, 3));
8024 
8025         assert(funcBwd(Date(2011, 2, 28)) == Date(2009, 12, 25));
8026         assert(funcBwd(Date(2011, 3, 1)) == Date(2009, 12, 26));
8027         assert(funcBwd(Date(2011, 3, 2)) == Date(2009, 12, 27));
8028         assert(funcBwd(Date(2011, 3, 3)) == Date(2009, 12, 28));
8029         assert(funcBwd(Date(2011, 3, 4)) == Date(2010, 1, 1));
8030     }
8031 
8032     assert(everyDuration!Date(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1)) !is null);
8033     static assert(!__traits(compiles, everyDuration!TimeOfDay(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
8034     assert(everyDuration!DateTime(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1)) !is null);
8035     assert(everyDuration!SysTime(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1)) !is null);
8036 }
8037 
8038 
8039 /++
8040     A range over an $(LREF Interval).
8041 
8042     $(D IntervalRange) is only ever constructed by $(LREF Interval). However, when
8043     it is constructed, it is given a function, $(D func), which is used to
8044     generate the time points which are iterated over. $(D func) takes a time
8045     point and returns a time point of the same type. For instance,
8046     to iterate over all of the days in
8047     the interval $(D Interval!Date), pass a function to $(LREF Interval)'s
8048     $(D fwdRange) where that function took a $(REF Date,std,datetime,date) and
8049     returned a $(REF Date,std,datetime,date) which was one day later. That
8050     function would then be used by $(D IntervalRange)'s $(D popFront) to iterate
8051     over the $(REF Date,std,datetime,date)s in the interval.
8052 
8053     If $(D dir == Direction.fwd), then a range iterates forward in time, whereas
8054     if $(D dir == Direction.bwd), then it iterates backwards in time. So, if
8055     $(D dir == Direction.fwd) then $(D front == interval.begin), whereas if
8056     $(D dir == Direction.bwd) then $(D front == interval.end). $(D func) must
8057     generate a time point going in the proper direction of iteration, or a
8058     $(REF DateTimeException,std,datetime,date) will be thrown. So, to iterate
8059     forward in time, the time point that $(D func) generates must be later in
8060     time than the one passed to it. If it's either identical or earlier in time,
8061     then a $(REF DateTimeException,std,datetime,date) will be thrown. To
8062     iterate backwards, then the generated time point must be before the time
8063     point which was passed in.
8064 
8065     If the generated time point is ever passed the edge of the range in the
8066     proper direction, then the edge of that range will be used instead. So, if
8067     iterating forward, and the generated time point is past the interval's
8068     $(D end), then $(D front) becomes $(D end). If iterating backwards, and the
8069     generated time point is before $(D begin), then $(D front) becomes
8070     $(D begin). In either case, the range would then be empty.
8071 
8072     Also note that while normally the $(D begin) of an interval is included in
8073     it and its $(D end) is excluded from it, if $(D dir == Direction.bwd), then
8074     $(D begin) is treated as excluded and $(D end) is treated as included. This
8075     allows for the same behavior in both directions. This works because none of
8076     $(LREF Interval)'s functions which care about whether $(D begin) or $(D end)
8077     is included or excluded are ever called by $(D IntervalRange). $(D interval)
8078     returns a normal interval, regardless of whether $(D dir == Direction.fwd)
8079     or if $(D dir == Direction.bwd), so any $(LREF Interval) functions which are
8080     called on it which care about whether $(D begin) or $(D end) are included or
8081     excluded will treat $(D begin) as included and $(D end) as excluded.
8082   +/
8083 struct IntervalRange(TP, Direction dir)
8084 if (isTimePoint!TP && dir != Direction.both)
8085 {
8086 public:
8087 
8088     /++
8089         Params:
8090             rhs = The $(D IntervalRange) to assign to this one.
8091       +/
opAssign(ref IntervalRange rhs)8092     ref IntervalRange opAssign(ref IntervalRange rhs) pure nothrow
8093     {
8094         _interval = rhs._interval;
8095         _func = rhs._func;
8096         return this;
8097     }
8098 
8099 
8100     /++ Ditto +/
8101     ref IntervalRange opAssign(IntervalRange rhs) pure nothrow
8102     {
8103         return this = rhs;
8104     }
8105 
8106 
8107     /++
8108         Whether this $(D IntervalRange) is empty.
8109       +/
8110     @property bool empty() const pure nothrow
8111     {
8112         return _interval.empty;
8113     }
8114 
8115 
8116     /++
8117         The first time point in the range.
8118 
8119         Throws:
8120             $(REF DateTimeException,std,datetime,date) if the range is empty.
8121       +/
8122     @property TP front() const pure
8123     {
8124         _enforceNotEmpty();
8125 
8126         static if (dir == Direction.fwd)
8127             return _interval.begin;
8128         else
8129             return _interval.end;
8130     }
8131 
8132 
8133     /++
8134         Pops $(D front) from the range, using $(D func) to generate the next
8135         time point in the range. If the generated time point is beyond the edge
8136         of the range, then $(D front) is set to that edge, and the range is then
8137         empty. So, if iterating forwards, and the generated time point is
8138         greater than the interval's $(D end), then $(D front) is set to
8139         $(D end). If iterating backwards, and the generated time point is less
8140         than the interval's $(D begin), then $(D front) is set to $(D begin).
8141 
8142         Throws:
8143             $(REF DateTimeException,std,datetime,date) if the range is empty
8144             or if the generated time point is in the wrong direction (i.e. if
8145             iterating forward and the generated time point is before $(D front),
8146             or if iterating backwards and the generated time point is after
8147             $(D front)).
8148       +/
8149     void popFront()
8150     {
8151         _enforceNotEmpty();
8152 
8153         static if (dir == Direction.fwd)
8154         {
8155             auto begin = _func(_interval.begin);
8156 
8157             if (begin > _interval.end)
8158                 begin = _interval.end;
8159 
8160             _enforceCorrectDirection(begin);
8161 
8162             _interval.begin = begin;
8163         }
8164         else
8165         {
8166             auto end = _func(_interval.end);
8167 
8168             if (end < _interval.begin)
8169                 end = _interval.begin;
8170 
8171             _enforceCorrectDirection(end);
8172 
8173             _interval.end = end;
8174         }
8175     }
8176 
8177 
8178     /++
8179         Returns a copy of $(D this).
8180       +/
8181     @property IntervalRange save() pure nothrow
8182     {
8183         return this;
8184     }
8185 
8186 
8187     /++
8188         The interval that this $(D IntervalRange) currently covers.
8189       +/
8190     @property Interval!TP interval() const pure nothrow
8191     {
8192         return cast(Interval!TP)_interval;
8193     }
8194 
8195 
8196     /++
8197         The function used to generate the next time point in the range.
8198       +/
8199     TP delegate(in TP) func() pure nothrow @property
8200     {
8201         return _func;
8202     }
8203 
8204 
8205     /++
8206         The $(D Direction) that this range iterates in.
8207       +/
8208     @property Direction direction() const pure nothrow
8209     {
8210         return dir;
8211     }
8212 
8213 
8214 private:
8215 
8216     /+
8217         Params:
8218             interval = The interval that this range covers.
8219             func     = The function used to generate the time points which are
8220                        iterated over.
8221       +/
8222     this(in Interval!TP interval, TP delegate(in TP) func) pure nothrow
8223     {
8224         _func = func;
8225         _interval = interval;
8226     }
8227 
8228 
8229     /+
8230         Throws:
8231             $(REF DateTimeException,std,datetime,date) if this interval is
8232             empty.
8233       +/
8234     void _enforceNotEmpty(size_t line = __LINE__) const pure
8235     {
8236         if (empty)
8237             throw new DateTimeException("Invalid operation for an empty IntervalRange.", __FILE__, line);
8238     }
8239 
8240 
8241     /+
8242         Throws:
8243             $(REF DateTimeException,std,datetime,date) if $(D_PARAM newTP) is
8244             in the wrong direction.
8245       +/
8246     void _enforceCorrectDirection(in TP newTP, size_t line = __LINE__) const
8247     {
8248         import std.format : format;
8249 
8250         static if (dir == Direction.fwd)
8251         {
8252             enforce(newTP > _interval._begin,
8253                     new DateTimeException(format("Generated time point is before previous begin: prev [%s] new [%s]",
8254                                                  interval._begin,
8255                                                  newTP),
8256                                                  __FILE__,
8257                                                  line));
8258         }
8259         else
8260         {
8261             enforce(newTP < _interval._end,
8262                     new DateTimeException(format("Generated time point is after previous end: prev [%s] new [%s]",
8263                                                  interval._end,
8264                                                  newTP),
8265                                                  __FILE__,
8266                                                  line));
8267         }
8268     }
8269 
8270 
8271     Interval!TP        _interval;
8272     TP delegate(in TP) _func;
8273 }
8274 
8275 //Test that IntervalRange satisfies the range predicates that it's supposed to satisfy.
8276 @safe unittest
8277 {
8278     import std.datetime.date;
8279     import std.datetime.systime;
8280     import std.range.primitives;
8281 
8282     static assert(isInputRange!(IntervalRange!(Date, Direction.fwd)));
8283     static assert(isForwardRange!(IntervalRange!(Date, Direction.fwd)));
8284 
8285     //Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=4895
8286     //static assert(!isOutputRange!(IntervalRange!(Date, Direction.fwd), Date));
8287 
8288     static assert(!isBidirectionalRange!(IntervalRange!(Date, Direction.fwd)));
8289     static assert(!isRandomAccessRange!(IntervalRange!(Date, Direction.fwd)));
8290     static assert(!hasSwappableElements!(IntervalRange!(Date, Direction.fwd)));
8291     static assert(!hasAssignableElements!(IntervalRange!(Date, Direction.fwd)));
8292     static assert(!hasLength!(IntervalRange!(Date, Direction.fwd)));
8293     static assert(!isInfinite!(IntervalRange!(Date, Direction.fwd)));
8294     static assert(!hasSlicing!(IntervalRange!(Date, Direction.fwd)));
8295 
8296     static assert(is(ElementType!(IntervalRange!(Date, Direction.fwd)) == Date));
8297     static assert(is(ElementType!(IntervalRange!(TimeOfDay, Direction.fwd)) == TimeOfDay));
8298     static assert(is(ElementType!(IntervalRange!(DateTime, Direction.fwd)) == DateTime));
8299     static assert(is(ElementType!(IntervalRange!(SysTime, Direction.fwd)) == SysTime));
8300 }
8301 
8302 //Test construction of IntervalRange.
8303 @safe unittest
8304 {
8305     import std.datetime.date;
8306     import std.datetime.systime;
8307 
8308     {
dateFunc(in Date date)8309         Date dateFunc(in Date date) { return date; }
8310         auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8311         auto ir = IntervalRange!(Date, Direction.fwd)(interval, &dateFunc);
8312     }
8313 
8314     {
todFunc(in TimeOfDay tod)8315         TimeOfDay todFunc(in TimeOfDay tod) { return tod; }
8316         auto interval = Interval!TimeOfDay(TimeOfDay(12, 1, 7), TimeOfDay(14, 0, 0));
8317         auto ir = IntervalRange!(TimeOfDay, Direction.fwd)(interval, &todFunc);
8318     }
8319 
8320     {
dtFunc(in DateTime dt)8321         DateTime dtFunc(in DateTime dt) { return dt; }
8322         auto interval = Interval!DateTime(DateTime(2010, 7, 4, 12, 1, 7), DateTime(2012, 1, 7, 14, 0, 0));
8323         auto ir = IntervalRange!(DateTime, Direction.fwd)(interval, &dtFunc);
8324     }
8325 
8326     {
stFunc(in SysTime st)8327         SysTime stFunc(in SysTime st) { return cast(SysTime) st; }
8328         auto interval = Interval!SysTime(SysTime(DateTime(2010, 7, 4, 12, 1, 7)),
8329                                          SysTime(DateTime(2012, 1, 7, 14, 0, 0)));
8330         auto ir = IntervalRange!(SysTime, Direction.fwd)(interval, &stFunc);
8331     }
8332 }
8333 
8334 //Test IntervalRange's empty().
8335 @system unittest
8336 {
8337     import std.datetime.date;
8338 
8339     //fwd
8340     {
8341         auto range = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8342 
8343         assert(!range.empty);
8344         range.popFront();
8345         assert(range.empty);
8346 
8347         const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8348         assert(!cRange.empty);
8349 
8350         //Apparently, creating an immutable IntervalRange!Date doesn't work, so we can't test if
8351         //empty works with it. However, since an immutable range is pretty useless, it's no great loss.
8352     }
8353 
8354     //bwd
8355     {
8356         auto range = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21)).bwdRange(
8357             everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
8358 
8359         assert(!range.empty);
8360         range.popFront();
8361         assert(range.empty);
8362 
8363         const cRange = Interval!Date( Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8364             everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
8365         assert(!cRange.empty);
8366 
8367         //Apparently, creating an immutable IntervalRange!Date doesn't work, so we can't test if
8368         //empty works with it. However, since an immutable range is pretty useless, it's no great loss.
8369     }
8370 }
8371 
8372 //Test IntervalRange's front.
8373 @system unittest
8374 {
8375     import std.datetime.date;
8376 
8377     //fwd
8378     {
8379         auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).fwdRange(
8380             everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8381         assertThrown!DateTimeException((in IntervalRange!(Date, Direction.fwd) range){range.front;}(emptyRange));
8382 
8383         auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed));
8384         assert(range.front == Date(2010, 7, 4));
8385 
8386         auto poppedRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(
8387             everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8388         assert(poppedRange.front == Date(2010, 7, 7));
8389 
8390         const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8391         assert(cRange.front != Date.init);
8392     }
8393 
8394     //bwd
8395     {
8396         auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).bwdRange(
8397             everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
8398         assertThrown!DateTimeException((in IntervalRange!(Date, Direction.bwd) range){range.front;}(emptyRange));
8399 
8400         auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8401             everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed));
8402         assert(range.front == Date(2012, 1, 7));
8403 
8404         auto poppedRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8405             everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
8406         assert(poppedRange.front == Date(2012, 1, 4));
8407 
8408         const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8409             everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
8410         assert(cRange.front != Date.init);
8411     }
8412 }
8413 
8414 //Test IntervalRange's popFront().
8415 @system unittest
8416 {
8417     import std.datetime.date;
8418     import std.range.primitives : walkLength;
8419 
8420     //fwd
8421     {
8422         auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).fwdRange(
8423             everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8424         assertThrown!DateTimeException((IntervalRange!(Date, Direction.fwd) range){range.popFront();}(emptyRange));
8425 
8426         auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(
8427             everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8428         auto expected = range.front;
8429 
foreach(date;range)8430         foreach (date; range)
8431         {
8432             assert(date == expected);
8433             expected += dur!"days"(7);
8434         }
8435 
8436         assert(walkLength(range) == 79);
8437 
8438         const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8439         assert(cRange.front != Date.init);
8440     }
8441 
8442     //bwd
8443     {
8444         auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).bwdRange(
8445             everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
8446         assertThrown!DateTimeException((IntervalRange!(Date, Direction.bwd) range){range.popFront();}(emptyRange));
8447 
8448         auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8449             everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
8450         auto expected = range.front;
8451 
foreach(date;range)8452         foreach (date; range)
8453         {
8454             assert(date == expected);
8455             expected += dur!"days"(-7);
8456         }
8457 
8458         assert(walkLength(range) == 79);
8459 
8460         const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(
8461             everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
8462         static assert(!__traits(compiles, cRange.popFront()));
8463     }
8464 }
8465 
8466 //Test IntervalRange's save.
8467 @system unittest
8468 {
8469     import std.datetime.date;
8470 
8471     //fwd
8472     {
8473         auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8474         auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8475         auto range = interval.fwdRange(func);
8476 
8477         assert(range.save == range);
8478     }
8479 
8480     //bwd
8481     {
8482         auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8483         auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
8484         auto range = interval.bwdRange(func);
8485 
8486         assert(range.save == range);
8487     }
8488 }
8489 
8490 //Test IntervalRange's interval.
8491 @system unittest
8492 {
8493     import std.datetime.date;
8494 
8495     //fwd
8496     {
8497         auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8498         auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8499         auto range = interval.fwdRange(func);
8500 
8501         assert(range.interval == interval);
8502 
8503         const cRange = range;
8504         assert(!cRange.interval.empty);
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.interval == interval);
8514 
8515         const cRange = range;
8516         assert(!cRange.interval.empty);
8517     }
8518 }
8519 
8520 //Test IntervalRange's func.
8521 @system unittest
8522 {
8523     import std.datetime.date;
8524 
8525     //fwd
8526     {
8527         auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8528         auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8529         auto range = interval.fwdRange(func);
8530 
8531         assert(range.func == func);
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.func == func);
8541     }
8542 }
8543 
8544 //Test IntervalRange's direction.
8545 @system unittest
8546 {
8547     import std.datetime.date;
8548 
8549     //fwd
8550     {
8551         auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
8552         auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8553         auto range = interval.fwdRange(func);
8554 
8555         assert(range.direction == Direction.fwd);
8556 
8557         const cRange = range;
8558         assert(cRange.direction == Direction.fwd);
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.direction == Direction.bwd);
8568 
8569         const cRange = range;
8570         assert(cRange.direction == Direction.bwd);
8571     }
8572 }
8573 
8574 
8575 /++
8576     A range over a $(D PosInfInterval). It is an infinite range.
8577 
8578     $(D PosInfIntervalRange) is only ever constructed by $(D PosInfInterval).
8579     However, when it is constructed, it is given a function, $(D func), which
8580     is used to generate the time points which are iterated over. $(D func)
8581     takes a time point and returns a time point of the same type. For
8582     instance, to iterate
8583     over all of the days in the interval $(D PosInfInterval!Date), pass a
8584     function to $(D PosInfInterval)'s $(D fwdRange) where that function took a
8585     $(REF Date,std,datetime,date) and returned a $(REF Date,std,datetime,date)
8586     which was one day later. That function would then be used by
8587     $(D PosInfIntervalRange)'s $(D popFront) to iterate over the
8588     $(REF Date,std,datetime,date)s in the interval - though obviously, since the
8589     range is infinite, use a function such as $(D std.range.take) with it rather
8590     than iterating over $(I all) of the dates.
8591 
8592     As the interval goes to positive infinity, the range is always iterated over
8593     forwards, never backwards. $(D func) must generate a time point going in
8594     the proper direction of iteration, or a
8595     $(REF DateTimeException,std,datetime,date) will be thrown. So, the time
8596     points that $(D func) generates must be later in time than the one passed to
8597     it. If it's either identical or earlier in time, then a
8598     $(REF DateTimeException,std,datetime,date) will be thrown.
8599   +/
8600 struct PosInfIntervalRange(TP)
8601 if (isTimePoint!TP)
8602 {
8603 public:
8604 
8605     /++
8606         Params:
8607             rhs = The $(D PosInfIntervalRange) to assign to this one.
8608       +/
opAssign(ref PosInfIntervalRange rhs)8609     ref PosInfIntervalRange opAssign(ref PosInfIntervalRange rhs) pure nothrow
8610     {
8611         _interval = rhs._interval;
8612         _func = rhs._func;
8613         return this;
8614     }
8615 
8616 
8617     /++ Ditto +/
8618     ref PosInfIntervalRange opAssign(PosInfIntervalRange rhs) pure nothrow
8619     {
8620         return this = rhs;
8621     }
8622 
8623 
8624     /++
8625         This is an infinite range, so it is never empty.
8626       +/
8627     enum bool empty = false;
8628 
8629 
8630     /++
8631         The first time point in the range.
8632       +/
8633     @property TP front() const pure nothrow
8634     {
8635         return _interval.begin;
8636     }
8637 
8638 
8639     /++
8640         Pops $(D front) from the range, using $(D func) to generate the next
8641         time point in the range.
8642 
8643         Throws:
8644             $(REF DateTimeException,std,datetime,date) if the generated time
8645             point is less than $(D front).
8646       +/
8647     void popFront()
8648     {
8649         auto begin = _func(_interval.begin);
8650         _enforceCorrectDirection(begin);
8651         _interval.begin = begin;
8652     }
8653 
8654 
8655     /++
8656         Returns a copy of $(D this).
8657       +/
8658     @property PosInfIntervalRange save() pure nothrow
8659     {
8660         return this;
8661     }
8662 
8663 
8664     /++
8665         The interval that this range currently covers.
8666       +/
8667     @property PosInfInterval!TP interval() const pure nothrow
8668     {
8669         return cast(PosInfInterval!TP)_interval;
8670     }
8671 
8672 
8673     /++
8674         The function used to generate the next time point in the range.
8675       +/
8676     TP delegate(in TP) func() pure nothrow @property
8677     {
8678         return _func;
8679     }
8680 
8681 
8682 private:
8683 
8684     /+
8685         Params:
8686             interval = The interval that this range covers.
8687             func     = The function used to generate the time points which are
8688                        iterated over.
8689       +/
8690     this(in PosInfInterval!TP interval, TP delegate(in TP) func) pure nothrow
8691     {
8692         _func = func;
8693         _interval = interval;
8694     }
8695 
8696 
8697     /+
8698         Throws:
8699             $(REF DateTimeException,std,datetime,date) if $(D_PARAM newTP) is
8700             in the wrong direction.
8701       +/
8702     void _enforceCorrectDirection(in TP newTP, size_t line = __LINE__) const
8703     {
8704         import std.format : format;
8705 
8706         enforce(newTP > _interval._begin,
8707                 new DateTimeException(format("Generated time point is before previous begin: prev [%s] new [%s]",
8708                                              interval._begin,
8709                                              newTP),
8710                                              __FILE__,
8711                                              line));
8712     }
8713 
8714 
8715     PosInfInterval!TP  _interval;
8716     TP delegate(in TP) _func;
8717 }
8718 
8719 //Test that PosInfIntervalRange satisfies the range predicates that it's supposed to satisfy.
8720 @safe unittest
8721 {
8722     import std.datetime.date;
8723     import std.datetime.systime;
8724     import std.range.primitives;
8725 
8726     static assert(isInputRange!(PosInfIntervalRange!Date));
8727     static assert(isForwardRange!(PosInfIntervalRange!Date));
8728     static assert(isInfinite!(PosInfIntervalRange!Date));
8729 
8730     //Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=4895
8731     //static assert(!isOutputRange!(PosInfIntervalRange!Date, Date));
8732     static assert(!isBidirectionalRange!(PosInfIntervalRange!Date));
8733     static assert(!isRandomAccessRange!(PosInfIntervalRange!Date));
8734     static assert(!hasSwappableElements!(PosInfIntervalRange!Date));
8735     static assert(!hasAssignableElements!(PosInfIntervalRange!Date));
8736     static assert(!hasLength!(PosInfIntervalRange!Date));
8737     static assert(!hasSlicing!(PosInfIntervalRange!Date));
8738 
8739     static assert(is(ElementType!(PosInfIntervalRange!Date) == Date));
8740     static assert(is(ElementType!(PosInfIntervalRange!TimeOfDay) == TimeOfDay));
8741     static assert(is(ElementType!(PosInfIntervalRange!DateTime) == DateTime));
8742     static assert(is(ElementType!(PosInfIntervalRange!SysTime) == SysTime));
8743 }
8744 
8745 //Test construction of PosInfIntervalRange.
8746 @safe unittest
8747 {
8748     import std.datetime.date;
8749     import std.datetime.systime;
8750 
8751     {
dateFunc(in Date date)8752         Date dateFunc(in Date date) { return date; }
8753         auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
8754         auto ir = PosInfIntervalRange!Date(posInfInterval, &dateFunc);
8755     }
8756 
8757     {
todFunc(in TimeOfDay tod)8758         TimeOfDay todFunc(in TimeOfDay tod) { return tod; }
8759         auto posInfInterval = PosInfInterval!TimeOfDay(TimeOfDay(12, 1, 7));
8760         auto ir = PosInfIntervalRange!(TimeOfDay)(posInfInterval, &todFunc);
8761     }
8762 
8763     {
dtFunc(in DateTime dt)8764         DateTime dtFunc(in DateTime dt) { return dt; }
8765         auto posInfInterval = PosInfInterval!DateTime(DateTime(2010, 7, 4, 12, 1, 7));
8766         auto ir = PosInfIntervalRange!(DateTime)(posInfInterval, &dtFunc);
8767     }
8768 
8769     {
stFunc(in SysTime st)8770         SysTime stFunc(in SysTime st) { return cast(SysTime) st; }
8771         auto posInfInterval = PosInfInterval!SysTime(SysTime(DateTime(2010, 7, 4, 12, 1, 7)));
8772         auto ir = PosInfIntervalRange!SysTime(posInfInterval, &stFunc);
8773     }
8774 }
8775 
8776 //Test PosInfIntervalRange's front.
8777 @system unittest
8778 {
8779     import std.datetime.date;
8780 
8781     auto range = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed));
8782     assert(range.front == Date(2010, 7, 4));
8783 
8784     auto poppedRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8785     assert(poppedRange.front == Date(2010, 7, 7));
8786 
8787     const cRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8788     assert(cRange.front != Date.init);
8789 }
8790 
8791 //Test PosInfIntervalRange's popFront().
8792 @system unittest
8793 {
8794     import std.datetime.date;
8795     import std.range : take;
8796 
8797     auto range = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
8798     auto expected = range.front;
8799 
8800     foreach (date; take(range, 79))
8801     {
8802         assert(date == expected);
8803         expected += dur!"days"(7);
8804     }
8805 
8806     const cRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
8807     static assert(!__traits(compiles, cRange.popFront()));
8808 }
8809 
8810 //Test PosInfIntervalRange's save.
8811 @system unittest
8812 {
8813     import std.datetime.date;
8814 
8815     auto interval = PosInfInterval!Date(Date(2010, 7, 4));
8816     auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8817     auto range = interval.fwdRange(func);
8818 
8819     assert(range.save == range);
8820 }
8821 
8822 //Test PosInfIntervalRange's interval.
8823 @system unittest
8824 {
8825     import std.datetime.date;
8826 
8827     auto interval = PosInfInterval!Date(Date(2010, 7, 4));
8828     auto func = everyDayOfWeek!Date(DayOfWeek.fri);
8829     auto range = interval.fwdRange(func);
8830 
8831     assert(range.interval == interval);
8832 
8833     const cRange = range;
8834     assert(!cRange.interval.empty);
8835 }
8836 
8837 //Test PosInfIntervalRange's func.
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.func == func);
8847 }
8848 
8849 
8850 /++
8851     A range over a $(D NegInfInterval). It is an infinite range.
8852 
8853     $(D NegInfIntervalRange) is only ever constructed by $(D NegInfInterval).
8854     However, when it is constructed, it is given a function, $(D func), which
8855     is used to generate the time points which are iterated over. $(D func)
8856     takes a time point and returns a time point of the same type. For
8857     instance, to iterate over all of the days in the interval
8858     $(D NegInfInterval!Date), pass a function to $(D NegInfInterval)'s
8859     $(D bwdRange) where that function took a $(REF Date,std,datetime,date) and
8860     returned a $(REF Date,std,datetime,date) which was one day earlier. That
8861     function would then be used by $(D NegInfIntervalRange)'s $(D popFront) to
8862     iterate over the $(REF Date,std,datetime,date)s in the interval - though
8863     obviously, since the range is infinite, use a function such as
8864     $(D std.range.take) with it rather than iterating over $(I all) of the dates.
8865 
8866     As the interval goes to negative infinity, the range is always iterated over
8867     backwards, never forwards. $(D func) must generate a time point going in
8868     the proper direction of iteration, or a
8869     $(REF DateTimeException,std,datetime,date) will be thrown. So, the time
8870     points that $(D func) generates must be earlier in time than the one passed
8871     to it. If it's either identical or later in time, then a
8872     $(REF DateTimeException,std,datetime,date) will be thrown.
8873 
8874     Also note that while normally the $(D end) of an interval is excluded from
8875     it, $(D NegInfIntervalRange) treats it as if it were included. This allows
8876     for the same behavior as with $(D PosInfIntervalRange). This works
8877     because none of $(D NegInfInterval)'s functions which care about whether
8878     $(D end) is included or excluded are ever called by
8879     $(D NegInfIntervalRange). $(D interval) returns a normal interval, so any
8880     $(D NegInfInterval) functions which are called on it which care about
8881     whether $(D end) is included or excluded will treat $(D end) as excluded.
8882   +/
8883 struct NegInfIntervalRange(TP)
8884 if (isTimePoint!TP)
8885 {
8886 public:
8887 
8888     /++
8889         Params:
8890             rhs = The $(D NegInfIntervalRange) to assign to this one.
8891       +/
opAssign(ref NegInfIntervalRange rhs)8892     ref NegInfIntervalRange opAssign(ref NegInfIntervalRange rhs) pure nothrow
8893     {
8894         _interval = rhs._interval;
8895         _func = rhs._func;
8896 
8897         return this;
8898     }
8899 
8900 
8901     /++ Ditto +/
opAssign(NegInfIntervalRange rhs)8902     ref NegInfIntervalRange opAssign(NegInfIntervalRange rhs) pure nothrow
8903     {
8904         return this = rhs;
8905     }
8906 
8907 
8908     /++
8909         This is an infinite range, so it is never empty.
8910       +/
8911     enum bool empty = false;
8912 
8913 
8914     /++
8915         The first time point in the range.
8916       +/
front()8917     @property TP front() const pure nothrow
8918     {
8919         return _interval.end;
8920     }
8921 
8922 
8923     /++
8924         Pops $(D front) from the range, using $(D func) to generate the next
8925         time point in the range.
8926 
8927         Throws:
8928             $(REF DateTimeException,std,datetime,date) if the generated time
8929             point is greater than $(D front).
8930       +/
popFront()8931     void popFront()
8932     {
8933         auto end = _func(_interval.end);
8934         _enforceCorrectDirection(end);
8935         _interval.end = end;
8936     }
8937 
8938 
8939     /++
8940         Returns a copy of $(D this).
8941       +/
save()8942     @property NegInfIntervalRange save() pure nothrow
8943     {
8944         return this;
8945     }
8946 
8947 
8948     /++
8949         The interval that this range currently covers.
8950       +/
8951     @property NegInfInterval!TP interval() const pure nothrow
8952     {
8953         return cast(NegInfInterval!TP)_interval;
8954     }
8955 
8956 
8957     /++
8958         The function used to generate the next time point in the range.
8959       +/
delegate(in TP)8960     TP delegate(in TP) func() pure nothrow @property
8961     {
8962         return _func;
8963     }
8964 
8965 
8966 private:
8967 
8968     /+
8969         Params:
8970             interval = The interval that this range covers.
8971             func     = The function used to generate the time points which are
8972                        iterated over.
8973       +/
8974     this(in NegInfInterval!TP interval, TP delegate(in TP) func) pure nothrow
8975     {
8976         _func = func;
8977         _interval = interval;
8978     }
8979 
8980 
8981     /+
8982         Throws:
8983             $(REF DateTimeException,std,datetime,date) if $(D_PARAM newTP) is
8984             in the wrong direction.
8985       +/
8986     void _enforceCorrectDirection(in TP newTP, size_t line = __LINE__) const
8987     {
8988         import std.format : format;
8989 
8990         enforce(newTP < _interval._end,
8991                 new DateTimeException(format("Generated time point is before previous end: prev [%s] new [%s]",
8992                                              interval._end,
8993                                              newTP),
8994                                              __FILE__,
8995                                              line));
8996     }
8997 
8998 
8999     NegInfInterval!TP  _interval;
9000     TP delegate(in TP) _func;
9001 }
9002 
9003 //Test that NegInfIntervalRange satisfies the range predicates that it's supposed to satisfy.
9004 @safe unittest
9005 {
9006     import std.datetime.date;
9007     import std.range.primitives;
9008 
9009     static assert(isInputRange!(NegInfIntervalRange!Date));
9010     static assert(isForwardRange!(NegInfIntervalRange!Date));
9011     static assert(isInfinite!(NegInfIntervalRange!Date));
9012 
9013     //Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=4895
9014     //static assert(!isOutputRange!(NegInfIntervalRange!Date, Date));
9015     static assert(!isBidirectionalRange!(NegInfIntervalRange!Date));
9016     static assert(!isRandomAccessRange!(NegInfIntervalRange!Date));
9017     static assert(!hasSwappableElements!(NegInfIntervalRange!Date));
9018     static assert(!hasAssignableElements!(NegInfIntervalRange!Date));
9019     static assert(!hasLength!(NegInfIntervalRange!Date));
9020     static assert(!hasSlicing!(NegInfIntervalRange!Date));
9021 
9022     static assert(is(ElementType!(NegInfIntervalRange!Date) == Date));
9023     static assert(is(ElementType!(NegInfIntervalRange!TimeOfDay) == TimeOfDay));
9024     static assert(is(ElementType!(NegInfIntervalRange!DateTime) == DateTime));
9025 }
9026 
9027 //Test construction of NegInfIntervalRange.
9028 @safe unittest
9029 {
9030     import std.datetime.date;
9031     import std.datetime.systime;
9032 
9033     {
dateFunc(in Date date)9034         Date dateFunc(in Date date) { return date; }
9035         auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
9036         auto ir = NegInfIntervalRange!Date(negInfInterval, &dateFunc);
9037     }
9038 
9039     {
todFunc(in TimeOfDay tod)9040         TimeOfDay todFunc(in TimeOfDay tod) { return tod; }
9041         auto negInfInterval = NegInfInterval!TimeOfDay(TimeOfDay(14, 0, 0));
9042         auto ir = NegInfIntervalRange!(TimeOfDay)(negInfInterval, &todFunc);
9043     }
9044 
9045     {
dtFunc(in DateTime dt)9046         DateTime dtFunc(in DateTime dt) { return dt; }
9047         auto negInfInterval = NegInfInterval!DateTime(DateTime(2012, 1, 7, 14, 0, 0));
9048         auto ir = NegInfIntervalRange!(DateTime)(negInfInterval, &dtFunc);
9049     }
9050 
9051     {
stFunc(in SysTime st)9052         SysTime stFunc(in SysTime st) { return cast(SysTime)(st); }
9053         auto negInfInterval = NegInfInterval!SysTime(SysTime(DateTime(2012, 1, 7, 14, 0, 0)));
9054         auto ir = NegInfIntervalRange!(SysTime)(negInfInterval, &stFunc);
9055     }
9056 }
9057 
9058 //Test NegInfIntervalRange's front.
9059 @system unittest
9060 {
9061     import std.datetime.date;
9062 
9063     auto range = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed));
9064     assert(range.front == Date(2012, 1, 7));
9065 
9066     auto poppedRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(
9067         everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
9068     assert(poppedRange.front == Date(2012, 1, 4));
9069 
9070     const cRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
9071     assert(cRange.front != Date.init);
9072 }
9073 
9074 //Test NegInfIntervalRange's popFront().
9075 @system unittest
9076 {
9077     import std.datetime.date;
9078     import std.range : take;
9079 
9080     auto range = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(
9081         everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
9082     auto expected = range.front;
9083 
9084     foreach (date; take(range, 79))
9085     {
9086         assert(date == expected);
9087         expected += dur!"days"(-7);
9088     }
9089 
9090     const cRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
9091     static assert(!__traits(compiles, cRange.popFront()));
9092 }
9093 
9094 //Test NegInfIntervalRange's save.
9095 @system unittest
9096 {
9097     import std.datetime.date;
9098 
9099     auto interval = NegInfInterval!Date(Date(2012, 1, 7));
9100     auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
9101     auto range = interval.bwdRange(func);
9102 
9103     assert(range.save == range);
9104 }
9105 
9106 //Test NegInfIntervalRange's interval.
9107 @system unittest
9108 {
9109     import std.datetime.date;
9110 
9111     auto interval = NegInfInterval!Date(Date(2012, 1, 7));
9112     auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
9113     auto range = interval.bwdRange(func);
9114 
9115     assert(range.interval == interval);
9116 
9117     const cRange = range;
9118     assert(!cRange.interval.empty);
9119 }
9120 
9121 //Test NegInfIntervalRange's func.
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.func == func);
9131 }
9132