// 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 finiteLines 1–500 of 9158. Load more
// 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