blob: d787e3a8080cc5e76c77b6e632b69657aa85cd10 [file] [log] [blame]
// Written in the D programming language
/++
$(SCRIPT inhibitQuickIndex = 1;)
$(DIVC quickindex,
$(BOOKTABLE,
$(TR $(TH Category) $(TH Functions))
$(TR $(TD Main types) $(TD
$(LREF Interval)
$(LREF Direction)
))
$(TR $(TD Special intervals) $(TD
$(LREF everyDayOfWeek)
$(LREF everyMonth)
$(LREF everyDuration)
))
$(TR $(TD Special intervals) $(TD
$(LREF NegInfInterval)
$(LREF PosInfInterval)
))
$(TR $(TD Underlying ranges) $(TD
$(LREF IntervalRange)
$(LREF NegInfIntervalRange)
$(LREF PosInfIntervalRange)
))
$(TR $(TD Flags) $(TD
$(LREF PopFirst)
))
))
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: $(HTTP jmdavisprog.com, Jonathan M Davis)
Source: $(PHOBOSSRC std/datetime/interval.d)
+/
module std.datetime.interval;
import core.time : Duration, dur;
import std.datetime.date : AllowDayOverflow, DateTimeException, daysToDayOfWeek,
DayOfWeek, isTimePoint, Month;
import std.exception : enforce;
import std.range.primitives : isOutputRange;
import std.traits : isIntegral;
import std.typecons : Flag;
version (StdUnittest) import std.exception : assertThrown;
/++
Indicates a direction in time. One example of its use is $(LREF Interval)'s
$(LREF expand) function which uses it to indicate whether the interval
should be expanded backwards (into the past), forwards (into the future), or
both.
+/
enum Direction
{
/// Backward.
bwd,
/// Forward.
fwd,
/// Both backward and forward.
both
}
/++
Used to indicate whether `popFront` should be called immediately upon
creating a range. The idea is that for some functions used to generate a
range for an interval, `front` is not necessarily a time point which
would ever be generated by the range (e.g. if the range were every Sunday
within an interval, but the interval started on a Monday), so there needs
to be a way to deal with that. To get the first time point in the range to
match what the function generates, then use `PopFirst.yes` to indicate
that the range should have `popFront` called on it before the range is
returned so that `front` is a time point which the function would
generate. To let the first time point not match the generator function,
use `PopFront.no`.
For instance, if the function used to generate a range of time points
generated successive Easters (i.e. you're iterating over all of the Easters
within the interval), the initial date probably isn't an Easter. Using
`PopFirst.yes` would tell the function which returned the range that
`popFront` was to be called so that front would then be an Easter - the
next one generated by the function (which when iterating forward would be
the Easter following the original `front`, while when iterating backward,
it would be the Easter prior to the original `front`). If
`PopFirst.no` were used, then `front` would remain the original time
point and it would not necessarily be a time point which would be generated
by the range-generating function (which in many cases is exactly what is
desired - e.g. if iterating over every day starting at the beginning of the
interval).
If set to `PopFirst.no`, then popFront is not called before returning
the range.
Otherwise, if set to `PopFirst.yes`, then popFront is called before
returning the range.
+/
alias PopFirst = Flag!"popFirst";
/++
Represents an interval of time.
An `Interval` has a starting point and an end point. The interval of time
is therefore the time starting at the starting point up to, but not
including, the end point. e.g.
$(BOOKTABLE,
$(TR $(TD [January 5th, 2010 - March 10th, 2010$(RPAREN)))
$(TR $(TD [05:00:30 - 12:00:00$(RPAREN)))
$(TR $(TD [1982-01-04T08:59:00 - 2010-07-04T12:00:00$(RPAREN)))
)
A range can be obtained from an `Interval`, allowing iteration over
that interval, with the exact time points which are iterated over depending
on the function which generates the range.
+/
struct Interval(TP)
{
public:
/++
Params:
begin = The time point which begins the interval.
end = The time point which ends (but is not included in) the
interval.
Throws:
$(REF DateTimeException,std,datetime,date) if $(D_PARAM end) is
before $(D_PARAM begin).
Example:
--------------------
Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
--------------------
+/
this(U)(scope const TP begin, scope const U end) pure
if (is(immutable TP == immutable U))
{
if (!_valid(begin, end))
throw new DateTimeException("Arguments would result in an invalid Interval.");
_begin = cast(TP) begin;
_end = cast(TP) end;
}
/++
Params:
begin = The time point which begins the interval.
duration = The duration from the starting point to the end point.
Throws:
$(REF DateTimeException,std,datetime,date) if the resulting
`end` is before `begin`.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), dur!"days"(3)) ==
Interval!Date(Date(1996, 1, 2), Date(1996, 1, 5)));
--------------------
+/
this(D)(scope const TP begin, scope const D duration) pure
if (__traits(compiles, begin + duration))
{
_begin = cast(TP) begin;
_end = begin + duration;
if (!_valid(_begin, _end))
throw new DateTimeException("Arguments would result in an invalid Interval.");
}
/++
Params:
rhs = The $(LREF Interval) to assign to this one.
+/
ref Interval opAssign(const ref Interval rhs) pure nothrow
{
_begin = cast(TP) rhs._begin;
_end = cast(TP) rhs._end;
return this;
}
/++
Params:
rhs = The $(LREF Interval) to assign to this one.
+/
ref Interval opAssign(Interval rhs) pure nothrow
{
_begin = cast(TP) rhs._begin;
_end = cast(TP) rhs._end;
return this;
}
/++
The starting point of the interval. It is included in the interval.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin ==
Date(1996, 1, 2));
--------------------
+/
@property TP begin() const pure nothrow
{
return cast(TP) _begin;
}
/++
The starting point of the interval. It is included in the interval.
Params:
timePoint = The time point to set `begin` to.
Throws:
$(REF DateTimeException,std,datetime,date) if the resulting
interval would be invalid.
+/
@property void begin(TP timePoint) pure
{
if (!_valid(timePoint, _end))
throw new DateTimeException("Arguments would result in an invalid Interval.");
_begin = timePoint;
}
/++
The end point of the interval. It is excluded from the interval.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end ==
Date(2012, 3, 1));
--------------------
+/
@property TP end() const pure nothrow
{
return cast(TP) _end;
}
/++
The end point of the interval. It is excluded from the interval.
Params:
timePoint = The time point to set end to.
Throws:
$(REF DateTimeException,std,datetime,date) if the resulting
interval would be invalid.
+/
@property void end(TP timePoint) pure
{
if (!_valid(_begin, timePoint))
throw new DateTimeException("Arguments would result in an invalid Interval.");
_end = timePoint;
}
/++
Returns the duration between `begin` and `end`.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length ==
dur!"days"(5903));
--------------------
+/
@property auto length() const pure nothrow
{
return _end - _begin;
}
/++
Whether the interval's length is 0, that is, whether $(D begin == end).
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
--------------------
+/
@property bool empty() const pure nothrow
{
return _begin == _end;
}
/++
Whether the given time point is within this interval.
Params:
timePoint = The time point to check for inclusion in this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
Date(1994, 12, 24)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
Date(2000, 1, 5)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
Date(2012, 3, 1)));
--------------------
+/
bool contains(scope const TP timePoint) const pure
{
_enforceNotEmpty();
return timePoint >= _begin && timePoint < _end;
}
/++
Whether the given interval is completely within this interval.
Params:
interval = The interval to check for inclusion in this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if either interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
--------------------
+/
bool contains(scope const Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return interval._begin >= _begin &&
interval._begin < _end &&
interval._end <= _end;
}
/++
Whether the given interval is completely within this interval.
Always returns false (unless this interval is empty), because an
interval going to positive infinity can never be contained in a finite
interval.
Params:
interval = The interval to check for inclusion in this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
PosInfInterval!Date(Date(1999, 5, 4))));
--------------------
+/
bool contains(scope const PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return false;
}
/++
Whether the given interval is completely within this interval.
Always returns false (unless this interval is empty), because an
interval beginning at negative infinity can never be contained in a
finite interval.
Params:
interval = The interval to check for inclusion in this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
NegInfInterval!Date(Date(1996, 5, 4))));
--------------------
+/
bool contains(scope const NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return false;
}
/++
Whether this interval is before the given time point.
Params:
timePoint = The time point to check whether this interval is before
it.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
Date(1994, 12, 24)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
Date(2000, 1, 5)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
Date(2012, 3, 1)));
--------------------
+/
bool isBefore(scope const TP timePoint) const pure
{
_enforceNotEmpty();
return _end <= timePoint;
}
/++
Whether this interval is before the given interval and does not
intersect with it.
Params:
interval = The interval to check for against this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if either interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
--------------------
+/
bool isBefore(scope const Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return _end <= interval._begin;
}
/++
Whether this interval is before the given interval and does not
intersect with it.
Params:
interval = The interval to check for against this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
PosInfInterval!Date(Date(2013, 3, 7))));
--------------------
+/
bool isBefore(scope const PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _end <= interval._begin;
}
/++
Whether this interval is before the given interval and does not
intersect with it.
Always returns false (unless this interval is empty) because a finite
interval can never be before an interval beginning at negative infinity.
Params:
interval = The interval to check for against this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
NegInfInterval!Date(Date(1996, 5, 4))));
--------------------
+/
bool isBefore(scope const NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return false;
}
/++
Whether this interval is after the given time point.
Params:
timePoint = The time point to check whether this interval is after
it.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
Date(1994, 12, 24)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
Date(2000, 1, 5)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
Date(2012, 3, 1)));
--------------------
+/
bool isAfter(scope const TP timePoint) const pure
{
_enforceNotEmpty();
return timePoint < _begin;
}
/++
Whether this interval is after the given interval and does not intersect
it.
Params:
interval = The interval to check against this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if either interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
--------------------
+/
bool isAfter(scope const Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return _begin >= interval._end;
}
/++
Whether this interval is after the given interval and does not intersect
it.
Always returns false (unless this interval is empty) because a finite
interval can never be after an interval going to positive infinity.
Params:
interval = The interval to check against this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
PosInfInterval!Date(Date(1999, 5, 4))));
--------------------
+/
bool isAfter(scope const PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return false;
}
/++
Whether this interval is after the given interval and does not intersect
it.
Params:
interval = The interval to check against this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
NegInfInterval!Date(Date(1996, 1, 2))));
--------------------
+/
bool isAfter(scope const NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _begin >= interval._end;
}
/++
Whether the given interval overlaps this interval.
Params:
interval = The interval to check for intersection with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if either interval is
empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
--------------------
+/
bool intersects(scope const Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return interval._begin < _end && interval._end > _begin;
}
/++
Whether the given interval overlaps this interval.
Params:
interval = The interval to check for intersection with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
PosInfInterval!Date(Date(1999, 5, 4))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
PosInfInterval!Date(Date(2012, 3, 1))));
--------------------
+/
bool intersects(scope const PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _end > interval._begin;
}
/++
Whether the given interval overlaps this interval.
Params:
interval = The interval to check for intersection with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
NegInfInterval!Date(Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
NegInfInterval!Date(Date(2000, 1, 2))));
--------------------
+/
bool intersects(scope const NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _begin < interval._end;
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the two intervals do
not intersect or if either interval is empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
--------------------
+/
Interval intersection(scope const Interval interval) const
{
import std.format : format;
enforce(this.intersects(interval),
new DateTimeException(format("%s and %s do not intersect.", this, interval)));
auto begin = _begin > interval._begin ? _begin : interval._begin;
auto end = _end < interval._end ? _end : interval._end;
return Interval(begin, end);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the two intervals do
not intersect or if this interval is empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
PosInfInterval!Date(Date(1990, 7, 6))) ==
Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
PosInfInterval!Date(Date(1999, 1, 12))) ==
Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
--------------------
+/
Interval intersection(scope const PosInfInterval!TP interval) const
{
import std.format : format;
enforce(this.intersects(interval),
new DateTimeException(format("%s and %s do not intersect.", this, interval)));
return Interval(_begin > interval._begin ? _begin : interval._begin, _end);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the two intervals do
not intersect or if this interval is empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
NegInfInterval!Date(Date(1999, 7, 6))) ==
Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
NegInfInterval!Date(Date(2013, 1, 12))) ==
Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
--------------------
+/
Interval intersection(scope const NegInfInterval!TP interval) const
{
import std.format : format;
enforce(this.intersects(interval),
new DateTimeException(format("%s and %s do not intersect.", this, interval)));
return Interval(_begin, _end < interval._end ? _end : interval._end);
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjecent to this
interval.
Throws:
$(REF DateTimeException,std,datetime,date) if either interval is
empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
--------------------
+/
bool isAdjacent(scope const Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return _begin == interval._end || _end == interval._begin;
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjecent to this
interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
PosInfInterval!Date(Date(2012, 3, 1))));
--------------------
+/
bool isAdjacent(scope const PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _end == interval._begin;
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjecent to this
interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
NegInfInterval!Date(Date(1996, 1, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
NegInfInterval!Date(Date(2000, 1, 2))));
--------------------
+/
bool isAdjacent(scope const NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _begin == interval._end;
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the two intervals do
not intersect and are not adjacent or if either interval is empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
--------------------
+/
Interval merge(scope const Interval interval) const
{
import std.format : format;
enforce(this.isAdjacent(interval) || this.intersects(interval),
new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
auto begin = _begin < interval._begin ? _begin : interval._begin;
auto end = _end > interval._end ? _end : interval._end;
return Interval(begin, end);
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the two intervals do
not intersect and are not adjacent or if this interval is empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
PosInfInterval!Date(Date(1990, 7, 6))) ==
PosInfInterval!Date(Date(1990, 7 , 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
PosInfInterval!Date(Date(2012, 3, 1))) ==
PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval!TP merge(scope const PosInfInterval!TP interval) const
{
import std.format : format;
enforce(this.isAdjacent(interval) || this.intersects(interval),
new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the two intervals do
not intersect and are not adjacent or if this interval is empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
NegInfInterval!Date(Date(1996, 1, 2))) ==
NegInfInterval!Date(Date(2012, 3 , 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
NegInfInterval!Date(Date(2013, 1, 12))) ==
NegInfInterval!Date(Date(2013, 1 , 12)));
--------------------
+/
NegInfInterval!TP merge(scope const NegInfInterval!TP interval) const
{
import std.format : format;
enforce(this.isAdjacent(interval) || this.intersects(interval),
new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two
intervals.
Params:
interval = The interval to create a span together with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if either interval is
empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) ==
Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
--------------------
+/
Interval span(scope const Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
auto begin = _begin < interval._begin ? _begin : interval._begin;
auto end = _end > interval._end ? _end : interval._end;
return Interval(begin, end);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two
intervals.
Params:
interval = The interval to create a span together with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
PosInfInterval!Date(Date(1990, 7, 6))) ==
PosInfInterval!Date(Date(1990, 7 , 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
PosInfInterval!Date(Date(2050, 1, 1))) ==
PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval!TP span(scope const PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two
intervals.
Params:
interval = The interval to create a span together with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Example:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
NegInfInterval!Date(Date(1602, 5, 21))) ==
NegInfInterval!Date(Date(2012, 3 , 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
NegInfInterval!Date(Date(2013, 1, 12))) ==
NegInfInterval!Date(Date(2013, 1 , 12)));
--------------------
+/
NegInfInterval!TP span(scope const NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
}
/++
Shifts the interval forward or backwards in time by the given duration
(a positive duration shifts the interval forward; a negative duration
shifts it backward). Effectively, it does $(D begin += duration) and
$(D end += duration).
Params:
duration = The duration to shift the interval by.
Throws:
$(REF DateTimeException,std,datetime,date) this interval is empty
or if the resulting interval would be invalid.
Example:
--------------------
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
interval1.shift(dur!"days"(50));
assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
interval2.shift(dur!"days"(-50));
assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
--------------------
+/
void shift(D)(D duration) pure
if (__traits(compiles, begin + duration))
{
_enforceNotEmpty();
auto begin = _begin + duration;
auto end = _end + duration;
if (!_valid(begin, end))
throw new DateTimeException("Argument would result in an invalid Interval.");
_begin = begin;
_end = end;
}
static if (__traits(compiles, begin.add!"months"(1)) &&
__traits(compiles, begin.add!"years"(1)))
{
/++
Shifts the interval forward or backwards in time by the given number
of years and/or months (a positive number of years and months shifts
the interval forward; a negative number shifts it backward).
It adds the years the given years and months to both begin and end.
It effectively calls `add!"years"()` and then `add!"months"()`
on begin and end with the given number of years and months.
Params:
years = The number of years to shift the interval by.
months = The number of months to shift the interval by.
allowOverflow = Whether the days should be allowed to overflow
on `begin` and `end`, causing their month
to increment.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty or if the resulting interval would be invalid.
Example:
--------------------
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.shift(2);
assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
interval2.shift(-2);
assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
--------------------
+/
void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
if (isIntegral!T)
{
_enforceNotEmpty();
auto begin = _begin;
auto end = _end;
begin.add!"years"(years, allowOverflow);
begin.add!"months"(months, allowOverflow);
end.add!"years"(years, allowOverflow);
end.add!"months"(months, allowOverflow);
enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
_begin = begin;
_end = end;
}
}
/++
Expands the interval forwards and/or backwards in time. Effectively,
it does $(D begin -= duration) and/or $(D end += duration). Whether
it expands forwards and/or backwards in time is determined by
$(D_PARAM dir).
Params:
duration = The duration to expand the interval by.
dir = The direction in time to expand the interval.
Throws:
$(REF DateTimeException,std,datetime,date) this interval is empty
or if the resulting interval would be invalid.
Example:
--------------------
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.expand(2);
assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
interval2.expand(-2);
assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
--------------------
+/
void expand(D)(D duration, Direction dir = Direction.both) pure
if (__traits(compiles, begin + duration))
{
_enforceNotEmpty();
switch (dir)
{
case Direction.both:
{
auto begin = _begin - duration;
auto end = _end + duration;
if (!_valid(begin, end))
throw new DateTimeException("Argument would result in an invalid Interval.");
_begin = begin;
_end = end;
return;
}
case Direction.fwd:
{
auto end = _end + duration;
if (!_valid(_begin, end))
throw new DateTimeException("Argument would result in an invalid Interval.");
_end = end;
return;
}
case Direction.bwd:
{
auto begin = _begin - duration;
if (!_valid(begin, _end))
throw new DateTimeException("Argument would result in an invalid Interval.");
_begin = begin;
return;
}
default:
assert(0, "Invalid Direction.");
}
}
static if (__traits(compiles, begin.add!"months"(1)) &&
__traits(compiles, begin.add!"years"(1)))
{
/++
Expands the interval forwards and/or backwards in time. Effectively,
it subtracts the given number of months/years from `begin` and
adds them to `end`. Whether it expands forwards and/or backwards
in time is determined by $(D_PARAM dir).
Params:
years = The number of years to expand the interval by.
months = The number of months to expand the interval by.
allowOverflow = Whether the days should be allowed to overflow
on `begin` and `end`, causing their month
to increment.
dir = The direction in time to expand the interval.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty or if the resulting interval would be invalid.
Example:
--------------------
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.expand(2);
assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
interval2.expand(-2);
assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
--------------------
+/
void expand(T)(T years,
T months = 0,
AllowDayOverflow allowOverflow = AllowDayOverflow.yes,
Direction dir = Direction.both)
if (isIntegral!T)
{
_enforceNotEmpty();
switch (dir)
{
case Direction.both:
{
auto begin = _begin;
auto end = _end;
begin.add!"years"(-years, allowOverflow);
begin.add!"months"(-months, allowOverflow);
end.add!"years"(years, allowOverflow);
end.add!"months"(months, allowOverflow);
enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
_begin = begin;
_end = end;
return;
}
case Direction.fwd:
{
auto end = _end;
end.add!"years"(years, allowOverflow);
end.add!"months"(months, allowOverflow);
enforce(_valid(_begin, end),
new DateTimeException("Argument would result in an invalid Interval."));
_end = end;
return;
}
case Direction.bwd:
{
auto begin = _begin;
begin.add!"years"(-years, allowOverflow);
begin.add!"months"(-months, allowOverflow);
enforce(_valid(begin, _end),
new DateTimeException("Argument would result in an invalid Interval."));
_begin = begin;
return;
}
default:
assert(0, "Invalid Direction.");
}
}
}
/++
Returns a range which iterates forward over the interval, starting
at `begin`, using $(D_PARAM func) to generate each successive time
point.
The range's `front` is the interval's `begin`. $(D_PARAM func) is
used to generate the next `front` when `popFront` is called. If
$(D_PARAM popFirst) is `PopFirst.yes`, then `popFront` is called
before the range is returned (so that `front` is a time point which
$(D_PARAM func) would generate).
If $(D_PARAM func) ever generates a time point less than or equal to the
current `front` of the range, then a
$(REF DateTimeException,std,datetime,date) will be thrown. The range
will be empty and iteration complete when $(D_PARAM func) generates a
time point equal to or beyond the `end` of the interval.
There are helper functions in this module which generate common
delegates to pass to `fwdRange`. Their documentation starts with
"Range-generating function," making them easily searchable.
Params:
func = The function used to generate the time points of the
range over the interval.
popFirst = Whether `popFront` should be called on the range
before returning it.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Warning:
$(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
would be a function pointer to a pure function, but forcing
$(D_PARAM func) to be pure is far too restrictive to be useful, and
in order to have the ease of use of having functions which generate
functions to pass to `fwdRange`, $(D_PARAM func) must be a
delegate.
If $(D_PARAM func) retains state which changes as it is called, then
some algorithms will not work correctly, because the range's
`save` will have failed to have really saved the range's state.
To avoid such bugs, don't pass a delegate which is
not logically pure to `fwdRange`. If $(D_PARAM func) is given the
same time point with two different calls, it must return the same
result both times.
Of course, none of the functions in this module have this problem,
so it's only relevant if when creating a custom delegate.
Example:
--------------------
auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
auto func = delegate (scope const Date date) // For iterating over even-numbered days.
{
if ((date.day & 1) == 0)
return date + dur!"days"(2);
return date + dur!"days"(1);
};
auto range = interval.fwdRange(func);
// An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
assert(range.front == Date(2010, 9, 1));
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.empty);
--------------------
+/
IntervalRange!(TP, Direction.fwd) fwdRange(TP delegate(scope const TP) func, PopFirst popFirst = PopFirst.no) const
{
_enforceNotEmpty();
auto range = IntervalRange!(TP, Direction.fwd)(this, func);
if (popFirst == PopFirst.yes)
range.popFront();
return range;
}
/++
Returns a range which iterates backwards over the interval, starting
at `end`, using $(D_PARAM func) to generate each successive time
point.
The range's `front` is the interval's `end`. $(D_PARAM func) is
used to generate the next `front` when `popFront` is called. If
$(D_PARAM popFirst) is `PopFirst.yes`, then `popFront` is called
before the range is returned (so that `front` is a time point which
$(D_PARAM func) would generate).
If $(D_PARAM func) ever generates a time point greater than or equal to
the current `front` of the range, then a
$(REF DateTimeException,std,datetime,date) will be thrown. The range
will be empty and iteration complete when $(D_PARAM func) generates a
time point equal to or less than the `begin` of the interval.
There are helper functions in this module which generate common
delegates to pass to `bwdRange`. Their documentation starts with
"Range-generating function," making them easily searchable.
Params:
func = The function used to generate the time points of the
range over the interval.
popFirst = Whether `popFront` should be called on the range
before returning it.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Warning:
$(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
would be a function pointer to a pure function, but forcing
$(D_PARAM func) to be pure is far too restrictive to be useful, and
in order to have the ease of use of having functions which generate
functions to pass to `fwdRange`, $(D_PARAM func) must be a
delegate.
If $(D_PARAM func) retains state which changes as it is called, then
some algorithms will not work correctly, because the range's
`save` will have failed to have really saved the range's state.
To avoid such bugs, don't pass a delegate which is
not logically pure to `fwdRange`. If $(D_PARAM func) is given the
same time point with two different calls, it must return the same
result both times.
Of course, none of the functions in this module have this problem,
so it's only relevant for custom delegates.
Example:
--------------------
auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
auto func = delegate (scope const Date date) // For iterating over even-numbered days.
{
if ((date.day & 1) == 0)
return date - dur!"days"(2);
return date - dur!"days"(1);
};
auto range = interval.bwdRange(func);
// An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
assert(range.front == Date(2010, 9, 9));
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.empty);
--------------------
+/
IntervalRange!(TP, Direction.bwd) bwdRange(TP delegate(scope const TP) func, PopFirst popFirst = PopFirst.no) const
{
_enforceNotEmpty();
auto range = IntervalRange!(TP, Direction.bwd)(this, func);
if (popFirst == PopFirst.yes)
range.popFront();
return range;
}
/++
Converts this interval to a string.
Params:
w = A `char` accepting
$(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
Returns:
A `string` when not using an output range; `void` otherwise.
+/
string toString() const @safe nothrow
{
import std.array : appender;
auto app = appender!string();
try
toString(app);
catch (Exception e)
assert(0, "toString() threw.");
return app.data;
}
/// ditto
void toString(Writer)(ref Writer w) const
if (isOutputRange!(Writer, char))
{
import std.range.primitives : put;
put(w, '[');
_begin.toString(w);
put(w, " - ");
_end.toString(w);
put(w, ')');
}
private:
/+
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
+/
void _enforceNotEmpty(size_t line = __LINE__) const pure
{
if (empty)
throw new DateTimeException("Invalid operation for an empty Interval.", __FILE__, line);
}
/+
Whether the given values form a valid time interval.
Params:
begin = The starting point of the interval.
end = The end point of the interval.
+/
static bool _valid(scope const TP begin, scope const TP end) pure nothrow @trusted
{
return begin <= end;
}
pure invariant()
{
assert(_valid(_begin, _end), "Invariant Failure: begin is not before or equal to end.");
}
TP _begin;
TP _end;
}
// Test Interval's constructors.
@safe unittest
{
import std.datetime.date;
import std.datetime.systime;
assertThrown!DateTimeException(Interval!Date(Date(2010, 1, 1), Date(1, 1, 1)));
Interval!Date(Date.init, Date.init);
Interval!TimeOfDay(TimeOfDay.init, TimeOfDay.init);
Interval!DateTime(DateTime.init, DateTime.init);
Interval!SysTime(SysTime(0), SysTime(0));
Interval!DateTime(DateTime.init, dur!"days"(7));
// Verify Examples.
Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
assert(Interval!Date(Date(1996, 1, 2), dur!"weeks"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 23)));
assert(Interval!Date(Date(1996, 1, 2), dur!"days"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 5)));
assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"hours"(3)) ==
Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 15, 0, 0)));
assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"minutes"(3)) ==
Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 3, 0)));
assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"seconds"(3)) ==
Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"msecs"(3000)) ==
Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
}
// Test Interval's begin.
@safe unittest
{
import std.datetime.date;
assert(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).begin == Date(1, 1, 1));
assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).begin == Date(2010, 1, 1));
assert(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).begin == Date(1997, 12, 31));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(cInterval.begin == Date(2010, 7, 4));
assert(iInterval.begin == Date(2010, 7, 4));
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin == Date(1996, 1, 2));
}
// Test Interval's end.
@safe unittest
{
import std.datetime.date;
assert(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).end == Date(2010, 1, 1));
assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).end == Date(2010, 1, 1));
assert(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).end == Date(1998, 1, 1));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(cInterval.end == Date(2012, 1, 7));
assert(iInterval.end == Date(2012, 1, 7));
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end == Date(2012, 3, 1));
}
// Test Interval's length.
@safe unittest
{
import std.datetime.date;
import std.datetime.systime;
assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).length == dur!"days"(0));
assert(Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).length == dur!"days"(90));
assert(Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).length == dur!"seconds"(42_727));
assert(Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).length ==
dur!"seconds"(129_127));
assert(Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)),SysTime(DateTime(2010, 1, 2, 12, 22, 7))).length ==
dur!"seconds"(129_127));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(cInterval.length != Duration.zero);
assert(iInterval.length != Duration.zero);
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length == dur!"days"(5903));
}
// Test Interval's empty.
@safe unittest
{
import std.datetime.date;
import std.datetime.systime;
assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).empty);
assert(!Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).empty);
assert(!Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).empty);
assert(!Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).empty);
assert(!Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)), SysTime(DateTime(2010, 1, 2, 12, 22, 7))).empty);
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(!cInterval.empty);
assert(!iInterval.empty);
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
}
// Test Interval's contains(time point).
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(Date(2010, 7, 4)));
assert(!interval.contains(Date(2009, 7, 4)));
assert(!interval.contains(Date(2010, 7, 3)));
assert(interval.contains(Date(2010, 7, 4)));
assert(interval.contains(Date(2010, 7, 5)));
assert(interval.contains(Date(2011, 7, 1)));
assert(interval.contains(Date(2012, 1, 6)));
assert(!interval.contains(Date(2012, 1, 7)));
assert(!interval.contains(Date(2012, 1, 8)));
assert(!interval.contains(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(interval.contains(cdate));
assert(cInterval.contains(cdate));
assert(iInterval.contains(cdate));
// Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
}
// Test Interval's contains(Interval).
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.contains(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4),dur!"days"(0)).contains(
Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(interval.contains(interval));
assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!interval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!interval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).contains(interval));
assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).contains(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).contains(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).contains(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).contains(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).contains(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).contains(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).contains(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).contains(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).contains(interval));
assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).contains(interval));
assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).contains(interval));
assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(interval.contains(interval));
assert(interval.contains(cInterval));
assert(interval.contains(iInterval));
assert(!interval.contains(posInfInterval));
assert(!interval.contains(cPosInfInterval));
assert(!interval.contains(iPosInfInterval));
assert(!interval.contains(negInfInterval));
assert(!interval.contains(cNegInfInterval));
assert(!interval.contains(iNegInfInterval));
assert(cInterval.contains(interval));
assert(cInterval.contains(cInterval));
assert(cInterval.contains(iInterval));
assert(!cInterval.contains(posInfInterval));
assert(!cInterval.contains(cPosInfInterval));
assert(!cInterval.contains(iPosInfInterval));
assert(!cInterval.contains(negInfInterval));
assert(!cInterval.contains(cNegInfInterval));
assert(!cInterval.contains(iNegInfInterval));
assert(iInterval.contains(interval));
assert(iInterval.contains(cInterval));
assert(iInterval.contains(iInterval));
assert(!iInterval.contains(posInfInterval));
assert(!iInterval.contains(cPosInfInterval));
assert(!iInterval.contains(iPosInfInterval));
assert(!iInterval.contains(negInfInterval));
assert(!iInterval.contains(cNegInfInterval));
assert(!iInterval.contains(iNegInfInterval));
// Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
}
// Test Interval's isBefore(time point).
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(Date(2010, 7, 4)));
assert(!interval.isBefore(Date(2009, 7, 3)));
assert(!interval.isBefore(Date(2010, 7, 3)));
assert(!interval.isBefore(Date(2010, 7, 4)));
assert(!interval.isBefore(Date(2010, 7, 5)));
assert(!interval.isBefore(Date(2011, 7, 1)));
assert(!interval.isBefore(Date(2012, 1, 6)));
assert(interval.isBefore(Date(2012, 1, 7)));
assert(interval.isBefore(Date(2012, 1, 8)));
assert(interval.isBefore(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(!interval.isBefore(cdate));
assert(!cInterval.isBefore(cdate));
assert(!iInterval.isBefore(cdate));
// Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
}
// Test Interval's isBefore(Interval).
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.isBefore(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(
Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!interval.isBefore(interval));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(interval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(interval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isBefore(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isBefore(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isBefore(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isBefore(interval));
assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isBefore(interval));
assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isBefore(interval));
assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(!interval.isBefore(interval));
assert(!interval.isBefore(cInterval));
assert(!interval.isBefore(iInterval));
assert(!interval.isBefore(posInfInterval));
assert(!interval.isBefore(cPosInfInterval));
assert(!interval.isBefore(iPosInfInterval));
assert(!interval.isBefore(negInfInterval));
assert(!interval.isBefore(cNegInfInterval));
assert(!interval.isBefore(iNegInfInterval));
assert(!cInterval.isBefore(interval));
assert(!cInterval.isBefore(cInterval));
assert(!cInterval.isBefore(iInterval));
assert(!cInterval.isBefore(posInfInterval));
assert(!cInterval.isBefore(cPosInfInterval));
assert(!cInterval.isBefore(iPosInfInterval));
assert(!cInterval.isBefore(negInfInterval));
assert(!cInterval.isBefore(cNegInfInterval));
assert(!cInterval.isBefore(iNegInfInterval));
assert(!iInterval.isBefore(interval));
assert(!iInterval.isBefore(cInterval));
assert(!iInterval.isBefore(iInterval));
assert(!iInterval.isBefore(posInfInterval));
assert(!iInterval.isBefore(cPosInfInterval));
assert(!iInterval.isBefore(iPosInfInterval));
assert(!iInterval.isBefore(negInfInterval));
assert(!iInterval.isBefore(cNegInfInterval));
assert(!iInterval.isBefore(iNegInfInterval));
// Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
}
// Test Interval's isAfter(time point).
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(Date(2010, 7, 4)));
assert(interval.isAfter(Date(2009, 7, 4)));
assert(interval.isAfter(Date(2010, 7, 3)));
assert(!interval.isAfter(Date(2010, 7, 4)));
assert(!interval.isAfter(Date(2010, 7, 5)));
assert(!interval.isAfter(Date(2011, 7, 1)));
assert(!interval.isAfter(Date(2012, 1, 6)));
assert(!interval.isAfter(Date(2012, 1, 7)));
assert(!interval.isAfter(Date(2012, 1, 8)));
assert(!interval.isAfter(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(!interval.isAfter(cdate));
assert(!cInterval.isAfter(cdate));
assert(!iInterval.isAfter(cdate));
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
}
// Test Interval's isAfter(Interval).
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.isAfter(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(
Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!interval.isAfter(interval));
assert(interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!interval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!interval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAfter(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAfter(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAfter(interval));
assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAfter(interval));
assert(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAfter(interval));
assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(!interval.isAfter(interval));
assert(!interval.isAfter(cInterval));
assert(!interval.isAfter(iInterval));
assert(!interval.isAfter(posInfInterval));
assert(!interval.isAfter(cPosInfInterval));
assert(!interval.isAfter(iPosInfInterval));
assert(!interval.isAfter(negInfInterval));
assert(!interval.isAfter(cNegInfInterval));
assert(!interval.isAfter(iNegInfInterval));
assert(!cInterval.isAfter(interval));
assert(!cInterval.isAfter(cInterval));
assert(!cInterval.isAfter(iInterval));
assert(!cInterval.isAfter(posInfInterval));
assert(!cInterval.isAfter(cPosInfInterval));
assert(!cInterval.isAfter(iPosInfInterval));
assert(!cInterval.isAfter(negInfInterval));
assert(!cInterval.isAfter(cNegInfInterval));
assert(!cInterval.isAfter(iNegInfInterval));
assert(!iInterval.isAfter(interval));
assert(!iInterval.isAfter(cInterval));
assert(!iInterval.isAfter(iInterval));
assert(!iInterval.isAfter(posInfInterval));
assert(!iInterval.isAfter(cPosInfInterval));
assert(!iInterval.isAfter(iPosInfInterval));
assert(!iInterval.isAfter(negInfInterval));
assert(!iInterval.isAfter(cNegInfInterval));
assert(!iInterval.isAfter(iNegInfInterval));
// Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
}
// Test Interval's intersects().
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.intersects(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(
Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(interval.intersects(interval));
assert(!interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!interval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!interval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersects(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersects(interval));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersects(interval));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersects(interval));
assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersects(interval));
assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersects(interval));
assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
assert(interval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
assert(interval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(interval.intersects(interval));
assert(interval.intersects(cInterval));
assert(interval.intersects(iInterval));
assert(interval.intersects(posInfInterval));
assert(interval.intersects(cPosInfInterval));
assert(interval.intersects(iPosInfInterval));
assert(interval.intersects(negInfInterval));
assert(interval.intersects(cNegInfInterval));
assert(interval.intersects(iNegInfInterval));
assert(cInterval.intersects(interval));
assert(cInterval.intersects(cInterval));
assert(cInterval.intersects(iInterval));
assert(cInterval.intersects(posInfInterval));
assert(cInterval.intersects(cPosInfInterval));
assert(cInterval.intersects(iPosInfInterval));
assert(cInterval.intersects(negInfInterval));
assert(cInterval.intersects(cNegInfInterval));
assert(cInterval.intersects(iNegInfInterval));
assert(iInterval.intersects(interval));
assert(iInterval.intersects(cInterval));
assert(iInterval.intersects(iInterval));
assert(iInterval.intersects(posInfInterval));
assert(iInterval.intersects(cPosInfInterval));
assert(iInterval.intersects(iPosInfInterval));
assert(iInterval.intersects(negInfInterval));
assert(iInterval.intersects(cNegInfInterval));
assert(iInterval.intersects(iNegInfInterval));
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2000, 1, 2))));
}
// Test Interval's intersection().
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(
Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersection(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersection(interval));
assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersection(interval));
assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersection(interval));
assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 7))));
assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 8))));
assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 3))));
assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 4))));
assert(interval.intersection(interval) == interval);
assert(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
assert(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
assert(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
assert(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assert(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersection(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersection(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersection(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersection(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersection(interval) ==
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersection(interval) ==
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersection(interval) ==
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersection(interval) ==
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assert(interval.intersection(PosInfInterval!Date(Date(2010, 7, 3))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.intersection(PosInfInterval!Date(Date(2010, 7, 4))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.intersection(PosInfInterval!Date(Date(2010, 7, 5))) ==
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
assert(interval.intersection(PosInfInterval!Date(Date(2012, 1, 6))) ==
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assert(interval.intersection(NegInfInterval!Date(Date(2010, 7, 5))) ==
Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
assert(interval.intersection(NegInfInterval!Date(Date(2012, 1, 6))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 6)));
assert(interval.intersection(NegInfInterval!Date(Date(2012, 1, 7))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.intersection(NegInfInterval!Date(Date(2012, 1, 8))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(!interval.intersection(interval).empty);
assert(!interval.intersection(cInterval).empty);
assert(!interval.intersection(iInterval).empty);
assert(!interval.intersection(posInfInterval).empty);
assert(!interval.intersection(cPosInfInterval).empty);
assert(!interval.intersection(iPosInfInterval).empty);
assert(!interval.intersection(negInfInterval).empty);
assert(!interval.intersection(cNegInfInterval).empty);
assert(!interval.intersection(iNegInfInterval).empty);
assert(!cInterval.intersection(interval).empty);
assert(!cInterval.intersection(cInterval).empty);
assert(!cInterval.intersection(iInterval).empty);
assert(!cInterval.intersection(posInfInterval).empty);
assert(!cInterval.intersection(cPosInfInterval).empty);
assert(!cInterval.intersection(iPosInfInterval).empty);
assert(!cInterval.intersection(negInfInterval).empty);
assert(!cInterval.intersection(cNegInfInterval).empty);
assert(!cInterval.intersection(iNegInfInterval).empty);
assert(!iInterval.intersection(interval).empty);
assert(!iInterval.intersection(cInterval).empty);
assert(!iInterval.intersection(iInterval).empty);
assert(!iInterval.intersection(posInfInterval).empty);
assert(!iInterval.intersection(cPosInfInterval).empty);
assert(!iInterval.intersection(iPosInfInterval).empty);
assert(!iInterval.intersection(negInfInterval).empty);
assert(!iInterval.intersection(cNegInfInterval).empty);
assert(!iInterval.intersection(iNegInfInterval).empty);
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
Interval!Date(Date(1999, 1, 12),Date(2011, 9, 17))) ==
Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
PosInfInterval!Date(Date(1990, 7, 6))) ==
Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
PosInfInterval!Date(Date(1999, 1, 12))) ==
Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
NegInfInterval!Date(Date(1999, 7, 6))) ==
Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
NegInfInterval!Date(Date(2013, 1, 12))) ==
Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
}
// Test Interval's isAdjacent().
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testInterval(scope const Interval!Date interval1, scope const Interval!Date interval2)
{
interval1.isAdjacent(interval2);
}
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),
Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!interval.isAdjacent(interval));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(interval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAdjacent(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAdjacent(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAdjacent(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAdjacent(interval));
assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAdjacent(interval));
assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAdjacent(interval));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
assert(interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
assert(interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(!interval.isAdjacent(interval));
assert(!interval.isAdjacent(cInterval));
assert(!interval.isAdjacent(iInterval));
assert(!interval.isAdjacent(posInfInterval));
assert(!interval.isAdjacent(cPosInfInterval));
assert(!interval.isAdjacent(iPosInfInterval));
assert(!interval.isAdjacent(negInfInterval));
assert(!interval.isAdjacent(cNegInfInterval));
assert(!interval.isAdjacent(iNegInfInterval));
assert(!cInterval.isAdjacent(interval));
assert(!cInterval.isAdjacent(cInterval));
assert(!cInterval.isAdjacent(iInterval));
assert(!cInterval.isAdjacent(posInfInterval));
assert(!cInterval.isAdjacent(cPosInfInterval));
assert(!cInterval.isAdjacent(iPosInfInterval));
assert(!cInterval.isAdjacent(negInfInterval));
assert(!cInterval.isAdjacent(cNegInfInterval));
assert(!cInterval.isAdjacent(iNegInfInterval));
assert(!iInterval.isAdjacent(interval));
assert(!iInterval.isAdjacent(cInterval));
assert(!iInterval.isAdjacent(iInterval));
assert(!iInterval.isAdjacent(posInfInterval));
assert(!iInterval.isAdjacent(cPosInfInterval));
assert(!iInterval.isAdjacent(iPosInfInterval));
assert(!iInterval.isAdjacent(negInfInterval));
assert(!iInterval.isAdjacent(cNegInfInterval));
assert(!iInterval.isAdjacent(iNegInfInterval));
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)) .isAdjacent(NegInfInterval!Date(Date(2000, 1, 2))));
}
// Test Interval's merge().
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testInterval(I)(scope const Interval!Date interval1, scope const I interval2)
{
interval1.merge(interval2);
}
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),
Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)), interval));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)), interval));
assertThrown!DateTimeException(testInterval(interval, PosInfInterval!Date(Date(2012, 1, 8))));
assertThrown!DateTimeException(testInterval(interval, NegInfInterval!Date(Date(2010, 7, 3))));
assert(interval.merge(interval) == interval);
assert(interval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
assert(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assert(interval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).merge(interval) ==
Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).merge(interval) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).merge(interval) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).merge(interval) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).merge(interval) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).merge(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).merge(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).merge(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).merge(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).merge(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assert(interval.merge(PosInfInterval!Date(Date(2010, 7, 3))) ==
PosInfInterval!Date(Date(2010, 7, 3)));
assert(interval.merge(PosInfInterval!Date(Date(2010, 7, 4))) ==
PosInfInterval!Date(Date(2010, 7, 4)));
assert(interval.merge(PosInfInterval!Date(Date(2010, 7, 5))) ==
PosInfInterval!Date(Date(2010, 7, 4)));
assert(interval.merge(PosInfInterval!Date(Date(2012, 1, 6))) ==
PosInfInterval!Date(Date(2010, 7, 4)));
assert(interval.merge(PosInfInterval!Date(Date(2012, 1, 7))) ==
PosInfInterval!Date(Date(2010, 7, 4)));
assert(interval.merge(NegInfInterval!Date(Date(2010, 7, 4))) ==
NegInfInterval!Date(Date(2012, 1, 7)));
assert(interval.merge(NegInfInterval!Date(Date(2010, 7, 5))) ==
NegInfInterval!Date(Date(2012, 1, 7)));
assert(interval.merge(NegInfInterval!Date(Date(2012, 1, 6))) ==
NegInfInterval!Date(Date(2012, 1, 7)));
assert(interval.merge(NegInfInterval!Date(Date(2012, 1, 7))) ==
NegInfInterval!Date(Date(2012, 1, 7)));
assert(interval.merge(NegInfInterval!Date(Date(2012, 1, 8))) ==
NegInfInterval!Date(Date(2012, 1, 8)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(!interval.merge(interval).empty);
assert(!interval.merge(cInterval).empty);
assert(!interval.merge(iInterval).empty);
assert(!interval.merge(posInfInterval).empty);
assert(!interval.merge(cPosInfInterval).empty);
assert(!interval.merge(iPosInfInterval).empty);
assert(!interval.merge(negInfInterval).empty);
assert(!interval.merge(cNegInfInterval).empty);
assert(!interval.merge(iNegInfInterval).empty);
assert(!cInterval.merge(interval).empty);
assert(!cInterval.merge(cInterval).empty);
assert(!cInterval.merge(iInterval).empty);
assert(!cInterval.merge(posInfInterval).empty);
assert(!cInterval.merge(cPosInfInterval).empty);
assert(!cInterval.merge(iPosInfInterval).empty);
assert(!cInterval.merge(negInfInterval).empty);
assert(!cInterval.merge(cNegInfInterval).empty);
assert(!cInterval.merge(iNegInfInterval).empty);
assert(!iInterval.merge(interval).empty);
assert(!iInterval.merge(cInterval).empty);
assert(!iInterval.merge(iInterval).empty);
assert(!iInterval.merge(posInfInterval).empty);
assert(!iInterval.merge(cPosInfInterval).empty);
assert(!iInterval.merge(iPosInfInterval).empty);
assert(!iInterval.merge(negInfInterval).empty);
assert(!iInterval.merge(cNegInfInterval).empty);
assert(!iInterval.merge(iNegInfInterval).empty);
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(1990, 7, 6))) ==
PosInfInterval!Date(Date(1990, 7 , 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(2012, 3, 1))) ==
PosInfInterval!Date(Date(1996, 1 , 2)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1996, 1, 2))) ==
NegInfInterval!Date(Date(2012, 3 , 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) ==
NegInfInterval!Date(Date(2013, 1 , 12)));
}
// Test Interval's span().
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testInterval(scope const Interval!Date interval1, scope const Interval!Date interval2)
{
interval1.span(interval2);
}
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),interval));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)),
Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(interval.span(interval) == interval);
assert(interval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))) ==
Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
assert(interval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))) ==
Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
assert(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assert(interval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assert(interval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
assert(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).span(interval) ==
Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).span(interval) ==
Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).span(interval) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).span(interval) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).span(interval) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).span(interval) ==
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).span(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).span(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).span(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).span(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).span(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assert(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).span(interval) ==
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
assert(interval.span(PosInfInterval!Date(Date(2010, 7, 3))) == PosInfInterval!Date(Date(2010, 7, 3)));
assert(interval.span(PosInfInterval!Date(Date(2010, 7, 4))) == PosInfInterval!Date(Date(2010, 7, 4)));
assert(interval.span(PosInfInterval!Date(Date(2010, 7, 5))) == PosInfInterval!Date(Date(2010, 7, 4)));
assert(interval.span(PosInfInterval!Date(Date(2012, 1, 6))) == PosInfInterval!Date(Date(2010, 7, 4)));
assert(interval.span(PosInfInterval!Date(Date(2012, 1, 7))) == PosInfInterval!Date(Date(2010, 7, 4)));
assert(interval.span(PosInfInterval!Date(Date(2012, 1, 8))) == PosInfInterval!Date(Date(2010, 7, 4)));
assert(interval.span(NegInfInterval!Date(Date(2010, 7, 3))) == NegInfInterval!Date(Date(2012, 1, 7)));
assert(interval.span(NegInfInterval!Date(Date(2010, 7, 4))) == NegInfInterval!Date(Date(2012, 1, 7)));
assert(interval.span(NegInfInterval!Date(Date(2010, 7, 5))) == NegInfInterval!Date(Date(2012, 1, 7)));
assert(interval.span(NegInfInterval!Date(Date(2012, 1, 6))) == NegInfInterval!Date(Date(2012, 1, 7)));
assert(interval.span(NegInfInterval!Date(Date(2012, 1, 7))) == NegInfInterval!Date(Date(2012, 1, 7)));
assert(interval.span(NegInfInterval!Date(Date(2012, 1, 8))) == NegInfInterval!Date(Date(2012, 1, 8)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(!interval.span(interval).empty);
assert(!interval.span(cInterval).empty);
assert(!interval.span(iInterval).empty);
assert(!interval.span(posInfInterval).empty);
assert(!interval.span(cPosInfInterval).empty);
assert(!interval.span(iPosInfInterval).empty);
assert(!interval.span(negInfInterval).empty);
assert(!interval.span(cNegInfInterval).empty);
assert(!interval.span(iNegInfInterval).empty);
assert(!cInterval.span(interval).empty);
assert(!cInterval.span(cInterval).empty);
assert(!cInterval.span(iInterval).empty);
assert(!cInterval.span(posInfInterval).empty);
assert(!cInterval.span(cPosInfInterval).empty);
assert(!cInterval.span(iPosInfInterval).empty);
assert(!cInterval.span(negInfInterval).empty);
assert(!cInterval.span(cNegInfInterval).empty);
assert(!cInterval.span(iNegInfInterval).empty);
assert(!iInterval.span(interval).empty);
assert(!iInterval.span(cInterval).empty);
assert(!iInterval.span(iInterval).empty);
assert(!iInterval.span(posInfInterval).empty);
assert(!iInterval.span(cPosInfInterval).empty);
assert(!iInterval.span(iPosInfInterval).empty);
assert(!iInterval.span(negInfInterval).empty);
assert(!iInterval.span(cNegInfInterval).empty);
assert(!iInterval.span(iNegInfInterval).empty);
// Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) ==
Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(1990, 7, 6))) ==
PosInfInterval!Date(Date(1990, 7 , 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(2050, 1, 1))) ==
PosInfInterval!Date(Date(1996, 1 , 2)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1602, 5, 21))) ==
NegInfInterval!Date(Date(2012, 3 , 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) ==
NegInfInterval!Date(Date(2013, 1 , 12)));
}
// Test Interval's shift(duration).
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testIntervalFail(Interval!Date interval, scope const Duration duration)
{
interval.shift(duration);
}
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
static void testInterval(I)(I interval, scope const Duration duration,
scope const I expected, size_t line = __LINE__)
{
interval.shift(duration);
assert(interval == expected);
}
testInterval(interval, dur!"days"(22), Interval!Date(Date(2010, 7, 26), Date(2012, 1, 29)));
testInterval(interval, dur!"days"(-22), Interval!Date(Date(2010, 6, 12), Date(2011, 12, 16)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
// Verify Examples.
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
interval1.shift(dur!"days"(50));
assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
interval2.shift(dur!"days"(-50));
assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
}
// Test Interval's shift(int, int, AllowDayOverflow).
@safe unittest
{
import std.datetime.date;
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testIntervalFail(Interval!Date interval, int years, int months)
{
interval.shift(years, months);
}
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow,
in I expected, size_t line = __LINE__)
{
interval.shift(years, months, allow);
assert(interval == expected);
}
testInterval(interval, 5, 0, AllowDayOverflow.yes, Interval!Date(Date(2015, 7, 4), Date(2017, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, Interval!Date(Date(2001, 3, 1), Date(2011, 7, 1)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, Interval!Date(Date(2000, 12, 29), Date(2011, 5, 1)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, Interval!Date(Date(1998, 12, 29), Date(2009, 5, 1)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, Interval!Date(Date(1999, 3, 1), Date(2009, 7, 1)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, Interval!Date(Date(2001, 2, 28), Date(2011, 6, 30)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, Interval!Date(Date(2000, 12, 29), Date(2011, 4, 30)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, Interval!Date(Date(1998, 12, 29), Date(2009, 4, 30)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, Interval!Date(Date(1999, 2, 28), Date(2009, 6, 30)));
}
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.shift(5)));
static assert(!__traits(compiles, iInterval.shift(5)));
// Verify Examples.
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.shift(2);
assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
interval2.shift(-2);
assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
}
// Test Interval's expand(Duration).
@safe unittest
{
import std.datetime.date;
auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
static void testIntervalFail(I)(I interval, scope const Duration duration)
{
interval.expand(duration);
}
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)), dur!"days"(-5)));
static void testInterval(I)(I interval, scope const Duration duration,
scope const I expected, size_t line = __LINE__)
{
interval.expand(duration);
assert(interval == expected);
}
testInterval(interval, dur!"days"(22), Interval!Date(Date(2000, 6, 12), Date(2012, 1, 29)));
testInterval(interval, dur!"days"(-22), Interval!Date(Date(2000, 7, 26), Date(2011, 12, 16)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
// Verify Examples.
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.expand(dur!"days"(2));
assert(interval1 == Interval!Date(Date(1995, 12, 31), Date(2012, 3, 3)));
interval2.expand(dur!"days"(-2));
assert(interval2 == Interval!Date(Date(1996, 1, 4), Date(2012, 2, 28)));
}
// Test Interval's expand(int, int, AllowDayOverflow, Direction)
@safe unittest
{
import std.datetime.date;
{
auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
static void testIntervalFail(Interval!Date interval, int years, int months)
{
interval.expand(years, months);
}
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)), -5, 0));
static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, Direction dir,
in I expected, size_t line = __LINE__)
{
interval.expand(years, months, allow, dir);
assert(interval == expected);
}
testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.both,
Interval!Date(Date(1995, 7, 4), Date(2017, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.both,
Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.fwd,
Interval!Date(Date(2000, 7, 4), Date(2017, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.fwd,
Interval!Date(Date(2000, 7, 4), Date(2007, 1, 7)));
testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.bwd,
Interval!Date(Date(1995, 7, 4), Date(2012, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.bwd,
Interval!Date(Date(2005, 7, 4), Date(2012, 1, 7)));
auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.both,
Interval!Date(Date(1998, 12, 29), Date(2011, 7, 1)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.both,
Interval!Date(Date(1999, 3, 1), Date(2011, 5, 1)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.both,
Interval!Date(Date(2001, 3, 1), Date(2009, 5, 1)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.both,
Interval!Date(Date(2000, 12, 29), Date(2009, 7, 1)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.both,
Interval!Date(Date(1998, 12, 29), Date(2011, 6, 30)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.both,
Interval!Date(Date(1999, 2, 28), Date(2011, 4, 30)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.both,
Interval!Date(Date(2001, 2, 28), Date(2009, 4, 30)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.both,
Interval!Date(Date(2000, 12, 29), Date(2009, 6, 30)));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.fwd,
Interval!Date(Date(2000, 1, 29), Date(2011, 7, 1)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.fwd,
Interval!Date(Date(2000, 1, 29), Date(2011, 5, 1)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.fwd,
Interval!Date(Date(2000, 1, 29), Date(2009, 5, 1)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.fwd,
Interval!Date(Date(2000, 1, 29), Date(2009, 7, 1)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.fwd,
Interval!Date(Date(2000, 1, 29), Date(2011, 6, 30)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.fwd,
Interval!Date(Date(2000, 1, 29), Date(2011, 4, 30)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.fwd,
Interval!Date(Date(2000, 1, 29), Date(2009, 4, 30)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.fwd,
Interval!Date(Date(2000, 1, 29), Date(2009, 6, 30)));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.bwd,
Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.bwd,
Interval!Date(Date(1999, 3, 1), Date(2010, 5, 31)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.bwd,
Interval!Date(Date(2001, 3, 1), Date(2010, 5, 31)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.bwd,
Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.bwd,
Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.bwd,
Interval!Date(Date(1999, 2, 28), Date(2010, 5, 31)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.bwd,
Interval!Date(Date(2001, 2, 28), Date(2010, 5, 31)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.bwd,
Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
}
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.expand(5)));
static assert(!__traits(compiles, iInterval.expand(5)));
// Verify Examples.
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.expand(2);
assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
interval2.expand(-2);
assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
}
// Test Interval's fwdRange.
@system unittest
{
import std.datetime.date;
{
auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
static void testInterval1(Interval!Date interval)
{
interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
}
assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
static void testInterval2(Interval!Date interval)
{
interval.fwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).popFront();
}
assertThrown!DateTimeException(testInterval2(interval));
assert(!interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
assert(interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).empty);
assert(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).front ==
Date(2010, 9, 12));
assert(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(
everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).front == Date(2010, 9, 17));
}
// Verify Examples.
{
auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
auto func = delegate (scope const Date date)
{
if ((date.day & 1) == 0)
return date + dur!"days"(2);
return date + dur!"days"(1);
};
auto range = interval.fwdRange(func);
// An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
assert(range.front == Date(2010, 9, 1));
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.empty);
}
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(!cInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
assert(!iInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
}
// Test Interval's bwdRange.
@system unittest
{
import std.datetime.date;
{
auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
static void testInterval1(Interval!Date interval)
{
interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
}
assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
static void testInterval2(Interval!Date interval)
{
interval.bwdRange(everyDayOfWeek!(Date, Direction.fwd)(DayOfWeek.fri)).popFront();
}
assertThrown!DateTimeException(testInterval2(interval));
assert(!interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).empty);
assert(interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).empty);
assert(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(
everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).front == Date(2010, 10, 1));
assert(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(
everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).front == Date(2010, 9, 24));
}
// Verify Examples.
{
auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
auto func = delegate (scope const Date date)
{
if ((date.day & 1) == 0)
return date - dur!"days"(2);
return date - dur!"days"(1);
};
auto range = interval.bwdRange(func);
// An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
assert(range.front == Date(2010, 9, 9));
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.empty);
}
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(!cInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
assert(!iInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
}
// Test Interval's toString().
@safe unittest
{
import std.datetime.date;
assert(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).toString() == "[2010-Jul-04 - 2012-Jan-07)");
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assert(cInterval.toString());
assert(iInterval.toString());
}
/++
Represents an interval of time which has positive infinity as its end point.
Any ranges which iterate over a `PosInfInterval` are infinite. So, the
main purpose of using `PosInfInterval` is to create an infinite range
which starts at a fixed point in time and goes to positive infinity.
+/
struct PosInfInterval(TP)
{
public:
/++
Params:
begin = The time point which begins the interval.
Example:
--------------------
auto interval = PosInfInterval!Date(Date(1996, 1, 2));
--------------------
+/
this(scope const TP begin) pure nothrow
{
_begin = cast(TP) begin;
}
/++
Params:
rhs = The `PosInfInterval` to assign to this one.
+/
ref PosInfInterval opAssign(const ref PosInfInterval rhs) pure nothrow
{
_begin = cast(TP) rhs._begin;
return this;
}
/++
Params:
rhs = The `PosInfInterval` to assign to this one.
+/
ref PosInfInterval opAssign(PosInfInterval rhs) pure nothrow
{
_begin = cast(TP) rhs._begin;
return this;
}
/++
The starting point of the interval. It is included in the interval.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
--------------------
+/
@property TP begin() const pure nothrow
{
return cast(TP)_begin;
}
/++
The starting point of the interval. It is included in the interval.
Params:
timePoint = The time point to set `begin` to.
+/
@property void begin(TP timePoint) pure nothrow
{
_begin = timePoint;
}
/++
Whether the interval's length is 0. Always returns false.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).empty);
--------------------
+/
enum bool empty = false;
/++
Whether the given time point is within this interval.
Params:
timePoint = The time point to check for inclusion in this interval.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(1994, 12, 24)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(2000, 1, 5)));
--------------------
+/
bool contains(TP timePoint) const pure nothrow
{
return timePoint >= _begin;
}
/++
Whether the given interval is completely within this interval.
Params:
interval = The interval to check for inclusion in this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the given interval
is empty.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
--------------------
+/
bool contains(scope const Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return interval._begin >= _begin;
}
/++
Whether the given interval is completely within this interval.
Params:
interval = The interval to check for inclusion in this interval.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
PosInfInterval!Date(Date(1999, 5, 4))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
PosInfInterval!Date(Date(1995, 7, 2))));
--------------------
+/
bool contains(scope const PosInfInterval interval) const pure nothrow
{
return interval._begin >= _begin;
}
/++
Whether the given interval is completely within this interval.
Always returns false because an interval going to positive infinity
can never contain an interval beginning at negative infinity.
Params:
interval = The interval to check for inclusion in this interval.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
NegInfInterval!Date(Date(1996, 5, 4))));
--------------------
+/
bool contains(scope const NegInfInterval!TP interval) const pure nothrow
{
return false;
}
/++
Whether this interval is before the given time point.
Always returns false because an interval going to positive infinity
can never be before any time point.
Params:
timePoint = The time point to check whether this interval is before
it.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(1994, 12, 24)));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(2000, 1, 5)));
--------------------
+/
bool isBefore(scope const TP timePoint) const pure nothrow
{
return false;
}
/++
Whether this interval is before the given interval and does not
intersect it.
Always returns false (unless the given interval is empty) because an
interval going to positive infinity can never be before any other
interval.
Params:
interval = The interval to check for against this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the given interval
is empty.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
--------------------
+/
bool isBefore(scope const Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return false;
}
/++
Whether this interval is before the given interval and does not
intersect it.
Always returns false because an interval going to positive infinity can
never be before any other interval.
Params:
interval = The interval to check for against this interval.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
PosInfInterval!Date(Date(1992, 5, 4))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
PosInfInterval!Date(Date(2013, 3, 7))));
--------------------
+/
bool isBefore(scope const PosInfInterval interval) const pure nothrow
{
return false;
}
/++
Whether this interval is before the given interval and does not
intersect it.
Always returns false because an interval going to positive infinity can
never be before any other interval.
Params:
interval = The interval to check for against this interval.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
NegInfInterval!Date(Date(1996, 5, 4))));
--------------------
+/
bool isBefore(scope const NegInfInterval!TP interval) const pure nothrow
{
return false;
}
/++
Whether this interval is after the given time point.
Params:
timePoint = The time point to check whether this interval is after
it.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(1994, 12, 24)));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(2000, 1, 5)));
--------------------
+/
bool isAfter(scope const TP timePoint) const pure nothrow
{
return timePoint < _begin;
}
/++
Whether this interval is after the given interval and does not intersect
it.
Params:
interval = The interval to check against this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the given interval
is empty.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
--------------------
+/
bool isAfter(scope const Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return _begin >= interval._end;
}
/++
Whether this interval is after the given interval and does not intersect
it.
Always returns false because an interval going to positive infinity can
never be after another interval going to positive infinity.
Params:
interval = The interval to check against this interval.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
PosInfInterval!Date(Date(1990, 1, 7))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
PosInfInterval!Date(Date(1999, 5, 4))));
--------------------
+/
bool isAfter(scope const PosInfInterval interval) const pure nothrow
{
return false;
}
/++
Whether this interval is after the given interval and does not intersect
it.
Params:
interval = The interval to check against this interval.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
NegInfInterval!Date(Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
NegInfInterval!Date(Date(2000, 7, 1))));
--------------------
+/
bool isAfter(scope const NegInfInterval!TP interval) const pure nothrow
{
return _begin >= interval._end;
}
/++
Whether the given interval overlaps this interval.
Params:
interval = The interval to check for intersection with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the given interval
is empty.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(
Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
--------------------
+/
bool intersects(scope const Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return interval._end > _begin;
}
/++
Whether the given interval overlaps this interval.
Always returns true because two intervals going to positive infinity
always overlap.
Params:
interval = The interval to check for intersection with this
interval.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
PosInfInterval!Date(Date(1990, 1, 7))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
PosInfInterval!Date(Date(1999, 5, 4))));
--------------------
+/
bool intersects(scope const PosInfInterval interval) const pure nothrow
{
return true;
}
/++
Whether the given interval overlaps this interval.
Params:
interval = The interval to check for intersection with this
interval.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(
NegInfInterval!Date(Date(1996, 1, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
NegInfInterval!Date(Date(2000, 7, 1))));
--------------------
+/
bool intersects(scope const NegInfInterval!TP interval) const pure nothrow
{
return _begin < interval._end;
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the two intervals do
not intersect or if the given interval is empty.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
--------------------
+/
Interval!TP intersection(scope const Interval!TP interval) const
{
import std.format : format;
enforce(this.intersects(interval),
new DateTimeException(format("%s and %s do not intersect.", this, interval)));
auto begin = _begin > interval._begin ? _begin : interval._begin;
return Interval!TP(begin, interval._end);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
PosInfInterval!Date(Date(1990, 7, 6))) ==
PosInfInterval!Date(Date(1996, 1 , 2)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
PosInfInterval!Date(Date(1999, 1, 12))) ==
PosInfInterval!Date(Date(1999, 1 , 12)));
--------------------
+/
PosInfInterval intersection(scope const PosInfInterval interval) const pure nothrow
{
return PosInfInterval(_begin < interval._begin ? interval._begin : _begin);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the two intervals do
not intersect.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
NegInfInterval!Date(Date(1999, 7, 6))) ==
Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
NegInfInterval!Date(Date(2013, 1, 12))) ==
Interval!Date(Date(1996, 1 , 2), Date(2013, 1, 12)));
--------------------
+/
Interval!TP intersection(scope const NegInfInterval!TP interval) const
{
import std.format : format;
enforce(this.intersects(interval),
new DateTimeException(format("%s and %s do not intersect.", this, interval)));
return Interval!TP(_begin, interval._end);
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjecent to this
interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the given interval
is empty.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1999, 1, 12)).isAdjacent(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
--------------------
+/
bool isAdjacent(scope const Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return _begin == interval._end;
}
/++
Whether the given interval is adjacent to this interval.
Always returns false because two intervals going to positive infinity
can never be adjacent to one another.
Params:
interval = The interval to check whether its adjecent to this
interval.
Example:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
PosInfInterval!Date(Date(1990, 1, 7))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
PosInfInterval!Date(Date(1996, 1, 2))));
--------------------
+/
bool isAdjacent(scope const PosInfInterval interval) const pure nothrow
{
return false;
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjecent to this
interval.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
NegInfInterval!Date(Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
NegInfInterval!Date(Date(2000, 7, 1))));
--------------------
+/
bool isAdjacent(scope const NegInfInterval!TP interval) const pure nothrow
{
return _begin == interval._end;
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the two intervals do
not intersect and are not adjacent or if the given interval is
empty.
Note:
There is no overload for `merge` which takes a
`NegInfInterval`, because an interval
going from negative infinity to positive infinity
is not possible.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval merge(scope const Interval!TP interval) const
{
import std.format : format;
enforce(this.isAdjacent(interval) || this.intersects(interval),
new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Note:
There is no overload for `merge` which takes a
`NegInfInterval`, because an interval
going from negative infinity to positive infinity
is not possible.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
PosInfInterval!Date(Date(1990, 7, 6))) ==
PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
PosInfInterval!Date(Date(1999, 1, 12))) ==
PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval merge(scope const PosInfInterval interval) const pure nothrow
{
return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two
intervals.
Params:
interval = The interval to create a span together with this
interval.
Throws:
$(REF DateTimeException,std,datetime,date) if the given interval
is empty.
Note:
There is no overload for `span` which takes a
`NegInfInterval`, because an interval
going from negative infinity to positive infinity
is not possible.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
Interval!Date(Date(500, 8, 9), Date(1602, 1, 31))) ==
PosInfInterval!Date(Date(500, 8, 9)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval span(scope const Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two
intervals.
Params:
interval = The interval to create a span together with this
interval.
Note:
There is no overload for `span` which takes a
`NegInfInterval`, because an interval
going from negative infinity to positive infinity
is not possible.
Example:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
PosInfInterval!Date(Date(1990, 7, 6))) ==
PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
PosInfInterval!Date(Date(1999, 1, 12))) ==
PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval span(scope const PosInfInterval interval) const pure nothrow
{
return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
}
/++
Shifts the `begin` of this interval forward or backwards in time by
the given duration (a positive duration shifts the interval forward; a
negative duration shifts it backward). Effectively, it does
$(D begin += duration).
Params:
duration = The duration to shift the interval by.
Example:
--------------------
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.shift(dur!"days"(50));
assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
interval2.shift(dur!"days"(-50));
assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
--------------------
+/
void shift(D)(D duration) pure nothrow
if (__traits(compiles, begin + duration))
{
_begin += duration;
}
static if (__traits(compiles, begin.add!"months"(1)) &&
__traits(compiles, begin.add!"years"(1)))
{
/++
Shifts the `begin` of this interval forward or backwards in time
by the given number of years and/or months (a positive number of
years and months shifts the interval forward; a negative number
shifts it backward). It adds the years the given years and months to
`begin`. It effectively calls `add!"years"()` and then
`add!"months"()` on `begin` with the given number of years and
months.
Params:
years = The number of years to shift the interval by.
months = The number of months to shift the interval by.
allowOverflow = Whether the days should be allowed to overflow
on `begin`, causing its month to increment.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty or if the resulting interval would be invalid.
Example:
--------------------
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.shift(dur!"days"(50));
assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
interval2.shift(dur!"days"(-50));
assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
--------------------
+/
void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
if (isIntegral!T)
{
auto begin = _begin;
begin.add!"years"(years, allowOverflow);
begin.add!"months"(months, allowOverflow);
_begin = begin;
}
}
/++
Expands the interval backwards in time. Effectively, it does
$(D begin -= duration).
Params:
duration = The duration to expand the interval by.
Example:
--------------------
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.expand(dur!"days"(2));
assert(interval1 == PosInfInterval!Date(Date(1995, 12, 31)));
interval2.expand(dur!"days"(-2));
assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
--------------------
+/
void expand(D)(D duration) pure nothrow
if (__traits(compiles, begin + duration))
{
_begin -= duration;
}
static if (__traits(compiles, begin.add!"months"(1)) &&
__traits(compiles, begin.add!"years"(1)))
{
/++
Expands the interval forwards and/or backwards in time. Effectively,
it subtracts the given number of months/years from `begin`.
Params:
years = The number of years to expand the interval by.
months = The number of months to expand the interval by.
allowOverflow = Whether the days should be allowed to overflow
on `begin`, causing its month to increment.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty or if the resulting interval would be invalid.
Example:
--------------------
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.expand(2);
assert(interval1 == PosInfInterval!Date(Date(1994, 1, 2)));
interval2.expand(-2);
assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
--------------------
+/
void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
if (isIntegral!T)
{
auto begin = _begin;
begin.add!"years"(-years, allowOverflow);
begin.add!"months"(-months, allowOverflow);
_begin = begin;
}
}
/++
Returns a range which iterates forward over the interval, starting
at `begin`, using $(D_PARAM func) to generate each successive time
point.
The range's `front` is the interval's `begin`. $(D_PARAM func) is
used to generate the next `front` when `popFront` is called. If
$(D_PARAM popFirst) is `PopFirst.yes`, then `popFront` is called
before the range is returned (so that `front` is a time point which
$(D_PARAM func) would generate).
If $(D_PARAM func) ever generates a time point less than or equal to the
current `front` of the range, then a
$(REF DateTimeException,std,datetime,date) will be thrown.
There are helper functions in this module which generate common
delegates to pass to `fwdRange`. Their documentation starts with
"Range-generating function," to make them easily searchable.
Params:
func = The function used to generate the time points of the
range over the interval.
popFirst = Whether `popFront` should be called on the range
before returning it.
Throws:
$(REF DateTimeException,std,datetime,date) if this interval is
empty.
Warning:
$(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
would be a function pointer to a pure function, but forcing
$(D_PARAM func) to be pure is far too restrictive to be useful, and
in order to have the ease of use of having functions which generate
functions to pass to `fwdRange`, $(D_PARAM func) must be a
delegate.
If $(D_PARAM func) retains state which changes as it is called, then
some algorithms will not work correctly, because the range's
`save` will have failed to have really saved the range's state.
To avoid such bugs, don't pass a delegate which is
not logically pure to `fwdRange`. If $(D_PARAM func) is given the
same time point with two different calls, it must return the same
result both times.
Of course, none of the functions in this module have this problem,
so it's only relevant for custom delegates.
Example:
--------------------
auto interval = PosInfInterval!Date(Date(2010, 9, 1));
auto func = delegate (scope const Date date) //For iterating over even-numbered days.
{
if ((date.day & 1) == 0)
return date + dur!"days"(2);
return date + dur!"days"(1);
};
auto range = interval.fwdRange(func);
//An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
assert(range.front == Date(2010, 9, 1));
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(!range.empty);
--------------------
+/
PosInfIntervalRange!(TP) fwdRange(TP delegate(scope const TP) func, PopFirst popFirst = PopFirst.no) const
{
auto range = PosInfIntervalRange!(TP)(this, func);
if (popFirst == PopFirst.yes)
range.popFront();
return range;
}
/+
Converts this interval to a string.
+/
// Due to bug https://issues.dlang.org/show_bug.cgi?id=3715 , we can't
// have versions of toString() with extra modifiers,
// so we define one version with modifiers and one without.
string toString()
{
return _toStringImpl();
}
/++
Converts this interval to a string.
+/
// Due to bug https://issues.dlang.org/show_bug.cgi?id=3715 , we can't
// have versions of toString() with extra modifiers,
// so we define one version with modifiers and one without.
string toString() const nothrow
{
return _toStringImpl();
}
private:
/+
Since we have two versions of toString(), we have _toStringImpl()
so that they can share implementations.
+/
string _toStringImpl() const nothrow
{
import std.format : format;
try
return format("[%s - ∞)", _begin);
catch (Exception e)
assert(0, "format() threw.");
}
TP _begin;
}
//Test PosInfInterval's constructor.
@safe unittest
{
import std.datetime.date;
import std.datetime.systime;
PosInfInterval!Date(Date.init);
PosInfInterval!TimeOfDay(TimeOfDay.init);
PosInfInterval!DateTime(DateTime.init);
PosInfInterval!SysTime(SysTime(0));
//Verify Examples.
auto interval = PosInfInterval!Date(Date(1996, 1, 2));
}
//Test PosInfInterval's begin.
@safe unittest
{
import std.datetime.date;
assert(PosInfInterval!Date(Date(1, 1, 1)).begin == Date(1, 1, 1));
assert(PosInfInterval!Date(Date(2010, 1, 1)).begin == Date(2010, 1, 1));
assert(PosInfInterval!Date(Date(1997, 12, 31)).begin == Date(1997, 12, 31));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
assert(cPosInfInterval.begin != Date.init);
assert(iPosInfInterval.begin != Date.init);
//Verify Examples.
assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
}
//Test PosInfInterval's empty.
@safe unittest
{
import std.datetime.date;
import std.datetime.systime;
assert(!PosInfInterval!Date(Date(2010, 1, 1)).empty);
assert(!PosInfInterval!TimeOfDay(TimeOfDay(0, 30, 0)).empty);
assert(!PosInfInterval!DateTime(DateTime(2010, 1, 1, 0, 30, 0)).empty);
assert(!PosInfInterval!SysTime(SysTime(DateTime(2010, 1, 1