diff --git a/README.md b/README.md index 95c13f4a..46ed994c 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ This package defines: * `AbstractInterval`, along with its subtypes: * `Interval{T}`, which represents a non-iterable range between two endpoints of type `T` - * `AnchoredInterval{P, T}`, which represents a non-iterable range defined by a single + * `AnchoredInterval{T, P}`, which represents a non-iterable range defined by a single value `anchor::T` and the value type `P` which represents the size of the range - * `HourEnding`, a type alias for `AnchoredInterval{Hour(-1)}` - * `HourBeginning`, a type alias for `AnchoredInterval{Hour(1)}` + * `HourEnding`, a type alias for `AnchoredInterval{T, Hour(-1)}` + * `HourBeginning`, a type alias for `AnchoredInterval{T, Hour(1)}` * `HE` and `HB`, pseudoconstructors for `HourEnding` and `HourBeginning` that round the anchor up (`HE`) or down (`HB`) to the nearest hour * `Inclusivity`, which represents whether an `AbstractInterval` is open, half-open, or diff --git a/docs/src/index.md b/docs/src/index.md index 450173f9..56bec1c9 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -3,10 +3,10 @@ This package defines: * `AbstractInterval`, along with its subtypes: * `Interval{T}`, which represents a non-iterable range between two endpoints of type `T` - * `AnchoredInterval{P, T}`, which represents a non-iterable range defined by a single + * `AnchoredInterval{T, P}`, which represents a non-iterable range defined by a single value `anchor::T` and the value type `P` which represents the size of the range - * `HourEnding`, a type alias for `AnchoredInterval{Hour(-1), T}` - * `HourBeginning`, a type alias for `AnchoredInterval{Hour(1), T}` + * `HourEnding`, a type alias for `AnchoredInterval{T, Hour(-1)}` + * `HourBeginning`, a type alias for `AnchoredInterval{T, Hour(1)}` * `HE` and `HB`, pseudoconstructors for `HourEnding` and `HourBeginning` that round the anchor up (`HE`) or down (`HB`) to the nearest hour * `Inclusivity`, which represents whether an `AbstractInterval` is open, half-open, or diff --git a/src/anchoredinterval.jl b/src/anchoredinterval.jl index 22a269b2..96a22863 100644 --- a/src/anchoredinterval.jl +++ b/src/anchoredinterval.jl @@ -1,8 +1,11 @@ using Base.Dates: value, coarserperiod """ - AnchoredInterval{P, T}(anchor::T, [inclusivity::Inclusivity]) where {P, T} -> AnchoredInterval{P, T} - AnchoredInterval{P, T}(anchor::T, [closed_left::Bool, closed_right::Bool]) where {P, T} -> AnchoredInterval{P, T} + AnchoredInterval{T, P}(anchor::T, [inclusivity::Inclusivity]) -> AnchoredInterval{T, P} + AnchoredInterval{T, P}(anchor::T, [closed_left::Bool, closed_right::Bool]) -> AnchoredInterval{T, P} + + AnchoredInterval(anchor::T, P, [inclusivity::Inclusivity]) -> AnchoredInterval{T, P} + AnchoredInterval(anchor::T, P, [closed_left::Bool, closed_right::Bool]) -> AnchoredInterval{T, P} `AnchoredInterval` is a subtype of `AbstractInterval` that represents a non-iterable range or span of values defined not by two endpoints but instead by a single `anchor` point and @@ -21,8 +24,8 @@ included for positive values of `P` and the greater endpoint included for negati range of values. This happens most often with dates and times, where "HE15" is often used as shorthand for (14:00..15:00]. -To this end, `HourEnding` is a type alias for `AnchoredInterval{Hour(-1)}`. Similarly, -`HourBeginning` is a type alias for `AnchoredInterval{Hour(1)}`. +To this end, `HourEnding` is a type alias for `AnchoredInterval{T, Hour(-1)} where T`. +Similarly, `HourBeginning` is a type alias for `AnchoredInterval{T, Hour(1)} where T`. ### Rounding @@ -48,44 +51,42 @@ HourBeginning{DateTime}(2016-08-11T02:00:00, Inclusivity(true, false)) ### Example ```julia -julia> AnchoredInterval{Hour(-1)}(DateTime(2016, 8, 11, 12)) +julia> AnchoredInterval(DateTime(2016, 8, 11, 12), Hour(-1)) HourEnding{DateTime}(2016-08-11T12:00:00, Inclusivity(false, true)) -julia> AnchoredInterval{Day(1)}(DateTime(2016, 8, 11)) -AnchoredInterval{1 day, DateTime}(2016-08-11T00:00:00, Inclusivity(true, false)) +julia> AnchoredInterval(DateTime(2016, 8, 11), Day(1)) +AnchoredInterval{DateTime, 1 day}(2016-08-11T00:00:00, Inclusivity(true, false)) -julia> AnchoredInterval{Minute(5)}(DateTime(2016, 8, 11, 12, 30), true, true) -AnchoredInterval{5 minutes, DateTime}(2016-08-11T12:30:00, Inclusivity(true, true)) +julia> AnchoredInterval(DateTime(2016, 8, 11, 12, 30), Minute(5), true, true) +AnchoredInterval{DateTime, 5 minutes}(2016-08-11T12:30:00, Inclusivity(true, true)) ``` See also: [`Interval`](@ref), [`Inclusivity`](@ref), [`HE`](@ref), [`HB`](@ref) """ -struct AnchoredInterval{P, T} <: AbstractInterval{T} +struct AnchoredInterval{T, P} <: AbstractInterval{T} anchor::T inclusivity::Inclusivity end # When an interval is anchored to the lesser endpoint, default to Inclusivity(false, true) # When an interval is anchored to the greater endpoint, default to Inclusivity(true, false) -function AnchoredInterval{P, T}(i::T) where {P, T} - return AnchoredInterval{P, T}(i::T, Inclusivity(P ≥ zero(P), P ≤ zero(P))) +function AnchoredInterval{T, P}(i::T) where {T, P} + return AnchoredInterval{T, P}(i::T, Inclusivity(P ≥ zero(P), P ≤ zero(P))) end -AnchoredInterval{P}(i::T, inc::Inclusivity) where {P, T} = AnchoredInterval{P, T}(i, inc) -AnchoredInterval{P}(i::T) where {P, T} = AnchoredInterval{P, T}(i) - -function AnchoredInterval{P, T}(i::T, x::Bool, y::Bool) where {P, T} - return AnchoredInterval{P, T}(i, Inclusivity(x, y)) +function AnchoredInterval{T, P}(i::T, x::Bool, y::Bool) where {T, P} + return AnchoredInterval{T, P}(i, Inclusivity(x, y)) end -function AnchoredInterval{P}(i::T, x::Bool, y::Bool) where {P, T} - return AnchoredInterval{P, T}(i, Inclusivity(x, y)) -end +AnchoredInterval(i::T, span, inc::Inclusivity) where T = AnchoredInterval{T, span}(i, inc) +AnchoredInterval(i::T, span, x::Bool, y::Bool) where T = AnchoredInterval{T, span}(i, x, y) +AnchoredInterval(i::T, span) where T = AnchoredInterval{T, span}(i) + -const HourEnding{T} = AnchoredInterval{Hour(-1), T} where T <: TimeType +const HourEnding{T} = AnchoredInterval{T, Hour(-1)} where T <: TimeType HourEnding(a::T, args...) where T = HourEnding{T}(a, args...) -const HourBeginning{T} = AnchoredInterval{Hour(1), T} where T <: TimeType +const HourBeginning{T} = AnchoredInterval{T, Hour(1)} where T <: TimeType HourBeginning(a::T, args...) where T = HourBeginning{T}(a, args...) """ @@ -104,32 +105,38 @@ nearest hour. """ HB(a, args...) = HourBeginning(floor(a, Hour), args...) -function Base.copy(x::AnchoredInterval{P, T}) where {P, T} - return AnchoredInterval{P, T}(anchor(x), inclusivity(x)) +function Base.copy(x::AnchoredInterval{T, P}) where {T, P} + return AnchoredInterval{T, P}(anchor(x), inclusivity(x)) end ##### ACCESSORS ##### -Base.first(interval::AnchoredInterval{P}) where P = min(interval.anchor, interval.anchor+P) -Base.last(interval::AnchoredInterval{P}) where P = max(interval.anchor, interval.anchor+P) +function Base.first(interval::AnchoredInterval{T, P}) where {T, P} + min(interval.anchor, interval.anchor + P) +end + +function Base.last(interval::AnchoredInterval{T, P}) where {T, P} + max(interval.anchor, interval.anchor + P) +end + anchor(interval::AnchoredInterval) = interval.anchor -span(interval::AnchoredInterval{P}) where P = abs(P) +span(interval::AnchoredInterval{T, P}) where {T, P} = abs(P) ##### CONVERSION ##### -function Base.convert(::Type{Interval}, interval::AnchoredInterval{P, T}) where {P, T} +function Base.convert(::Type{Interval}, interval::AnchoredInterval{T}) where T return Interval{T}(first(interval), last(interval), inclusivity(interval)) end -function Base.convert(::Type{Interval{T}}, interval::AnchoredInterval{P, T}) where {P, T} +function Base.convert(::Type{Interval{T}}, interval::AnchoredInterval{T}) where T return Interval{T}(first(interval), last(interval), inclusivity(interval)) end -Base.convert(::Type{T}, interval::AnchoredInterval{P, T}) where {P, T} = anchor(interval) +Base.convert(::Type{T}, interval::AnchoredInterval{T}) where T = anchor(interval) # Date/DateTime attempt to convert to Int64 instead of falling back to convert(T, ...) -Base.Date(interval::AnchoredInterval{P, Date}) where P = convert(Date, interval) -Base.DateTime(interval::AnchoredInterval{P, DateTime}) where P = convert(DateTime, interval) +Base.Date(interval::AnchoredInterval{Date}) = convert(Date, interval) +Base.DateTime(interval::AnchoredInterval{DateTime}) = convert(DateTime, interval) ##### DISPLAY ##### @@ -139,8 +146,8 @@ Base.show(io::IO, ::Type{HourBeginning}) = print(io, "HourBeginning{T}") Base.show(io::IO, ::Type{HourEnding{T}}) where T <: TimeType = print(io, "HourEnding{$T}") Base.show(io::IO, ::Type{HourBeginning{T}}) where T <: TimeType = print(io, "HourBeginning{$T}") -function Base.show(io::IO, ::Type{AnchoredInterval{P, T}}) where {P, T} - print(io, "AnchoredInterval{$P, $T}") +function Base.show(io::IO, ::Type{AnchoredInterval{T, P}}) where {T, P} + print(io, "AnchoredInterval{$T, $P}") end function Base.show(io::IO, interval::T) where T <: AnchoredInterval @@ -155,7 +162,7 @@ function Base.show(io::IO, interval::T) where T <: AnchoredInterval end end -function Base.print(io::IO, interval::AnchoredInterval{P, T}) where {P, T <: TimeType} +function Base.print(io::IO, interval::AnchoredInterval{<:TimeType}) # Print to io in order to keep properties like :limit and :compact if get(io, :compact, false) io = IOContext(io, :limit=>true) @@ -174,11 +181,11 @@ Base.:-(a::AnchoredInterval, b) = a + -b # Required for StepRange{<:AnchoredInterval} Base.:-(a::AnchoredInterval, b::AnchoredInterval) = anchor(a) - anchor(b) -Base.:-(a::T, b::AnchoredInterval{P, T}) where {P, T <: Number} = a + -b +Base.:-(a::T, b::AnchoredInterval{T}) where {T <: Number} = a + -b -function Base.:-(a::AnchoredInterval{P, T}) where {P, T <: Number} +function Base.:-(a::AnchoredInterval{T, P}) where {T <: Number, P} inc = inclusivity(a) - AnchoredInterval{-P, T}(-anchor(a), Inclusivity(last(inc), first(inc))) + AnchoredInterval{T, -P}(-anchor(a), Inclusivity(last(inc), first(inc))) end ##### RANGE ##### @@ -189,7 +196,7 @@ function Base.steprem(a::T, b::T, c) where {T <: AnchoredInterval} end # Infer step for two-argument StepRange{<:AnchoredInterval} -function Base.colon(start::AnchoredInterval{P, T}, stop::AnchoredInterval{P, T}) where {P,T} +function Base.colon(start::AnchoredInterval{T, P}, stop::AnchoredInterval{T, P}) where {T,P} return colon(start, abs(P), stop) end @@ -199,11 +206,11 @@ end ##### SET OPERATIONS ##### -function Base.isempty(interval::AnchoredInterval{P, T}) where {P, T} +function Base.isempty(interval::AnchoredInterval{T, P}) where {T, P} return P == zero(P) && !isclosed(interval) end -function Base.intersect(a::AnchoredInterval{P, T}, b::AnchoredInterval{Q, T}) where {P,Q,T} +function Base.intersect(a::AnchoredInterval{T, P}, b::AnchoredInterval{T, Q}) where {T,P,Q} interval = invoke(intersect, Tuple{AbstractInterval{T}, AbstractInterval{T}}, a, b) sp = isa(P, Period) ? canonicalize(typeof(P), span(interval)) : span(interval) @@ -215,7 +222,7 @@ function Base.intersect(a::AnchoredInterval{P, T}, b::AnchoredInterval{Q, T}) wh new_P = sp end - return AnchoredInterval{new_P, T}(anchor, inclusivity(interval)) + return AnchoredInterval{T, new_P}(anchor, inclusivity(interval)) end ##### UTILITIES ##### diff --git a/src/description.jl b/src/description.jl index 8ad85aa4..17a51944 100644 --- a/src/description.jl +++ b/src/description.jl @@ -1,8 +1,10 @@ using Base.Dates: value, coarserperiod -description(interval::AnchoredInterval{P}) where P = description(interval, P > zero(P) ? "B" : "E") +function description(interval::AnchoredInterval{T, P}) where {T, P} + description(interval, P > zero(P) ? "B" : "E") +end -function description(interval::AnchoredInterval{P, T}, s::String) where {P, T} +function description(interval::AnchoredInterval{T, P}, s::String) where {T, P} return string( first(inclusivity(interval)) ? '[' : '(', description(anchor(interval), abs(P), s), @@ -10,7 +12,7 @@ function description(interval::AnchoredInterval{P, T}, s::String) where {P, T} ) end -function description(interval::AnchoredInterval{P, ZonedDateTime}, s::String) where P +function description(interval::AnchoredInterval{ZonedDateTime, P}, s::String) where P return string( first(inclusivity(interval)) ? '[' : '(', description(anchor(interval), abs(P), s), diff --git a/src/endpoint.jl b/src/endpoint.jl index caa75e10..8d70a75c 100644 --- a/src/endpoint.jl +++ b/src/endpoint.jl @@ -2,6 +2,9 @@ struct Direction{T} end const Left = Direction{:Left}() const Right = Direction{:Right}() +const Beginning = Left +const Ending = Right + struct Endpoint{T, D} endpoint::T included::Bool diff --git a/test/anchoredinterval.jl b/test/anchoredinterval.jl index 6bbfdf37..d4a582e0 100644 --- a/test/anchoredinterval.jl +++ b/test/anchoredinterval.jl @@ -4,18 +4,19 @@ using Intervals: canonicalize dt = DateTime(2016, 8, 11, 2) @testset "constructor" begin - expected = AnchoredInterval{Hour(-1), DateTime}(dt, Inclusivity(false, true)) - @test AnchoredInterval{Hour(-1), DateTime}(dt) == expected - @test AnchoredInterval{Hour(-1)}(dt) == expected + expected = AnchoredInterval{DateTime, Hour(-1)}(dt, Inclusivity(false, true)) + @test AnchoredInterval{DateTime, Hour(-1)}(dt) == expected + @test_throws MethodError AnchoredInterval{Hour(-1)}(dt) + @test AnchoredInterval(dt, Hour(-1)) == expected @test HourEnding{DateTime}(dt) == expected @test HourEnding(dt) == expected @test HE(dt) == expected @test HE(dt - Minute(59)) == expected - expected = AnchoredInterval{Hour(1), DateTime}(dt, Inclusivity(true, false)) - @test AnchoredInterval{Hour(1), DateTime}(dt) == expected - @test AnchoredInterval{Hour(1)}(dt) == expected - @test HourBeginning{DateTime}(dt) == expected + expected = AnchoredInterval{DateTime, Hour(1)}(dt, Inclusivity(true, false)) + @test AnchoredInterval{DateTime, Hour(1)}(dt) == expected + @test_throws MethodError AnchoredInterval{Hour(1)}(dt) + @test AnchoredInterval(dt, Hour(1)) == expected @test HourBeginning(dt) == expected @test HB(dt) == expected @test HB(dt + Minute(59)) == expected @@ -24,16 +25,16 @@ using Intervals: canonicalize @test HourEnding{DateTime}(dt, true, false) == HourEnding{DateTime}(dt, Inclusivity(true, false)) @test HourEnding(dt, true, false) == HourEnding(dt, Inclusivity(true, false)) - @test AnchoredInterval{Day(1), DateTime}(dt, false, false) == - AnchoredInterval{Day(1), DateTime}(dt, Inclusivity(false, false)) - @test AnchoredInterval{Day(1)}(dt, false, false) == - AnchoredInterval{Day(1)}(dt, Inclusivity(false, false)) + @test AnchoredInterval{DateTime, Day(1)}(dt, false, false) == + AnchoredInterval{DateTime, Day(1)}(dt, Inclusivity(false, false)) + @test AnchoredInterval(dt, Day(1), false, false) == + AnchoredInterval(dt, Day(1), Inclusivity(false, false)) @test HE(dt, true, true) == HourEnding(dt, Inclusivity(true, true)) @test HB(dt, true, true) == HourBeginning(dt, Inclusivity(true, true)) # Non-period AnchoredIntervals - @test AnchoredInterval{-10}(10) isa AnchoredInterval - @test AnchoredInterval{25}('a') isa AnchoredInterval + @test AnchoredInterval(10, -10) isa AnchoredInterval + @test AnchoredInterval('a', 25) isa AnchoredInterval end @testset "conversion" begin @@ -51,52 +52,52 @@ using Intervals: canonicalize @testset "accessors" begin inc = Inclusivity(true, true) - P = Minute(-15) - interval = AnchoredInterval{P}(dt, inc) + p = Minute(-15) + interval = AnchoredInterval(dt, p, inc) @test first(interval) == DateTime(2016, 8, 11, 1, 45) @test last(interval) == dt - @test span(interval) == -P + @test span(interval) == -p @test inclusivity(interval) == inc inc = Inclusivity(false, false) - P = Day(1) - interval = AnchoredInterval{P}(Date(dt), inc) + p = Day(1) + interval = AnchoredInterval(Date(dt), p, inc) @test first(interval) == Date(2016, 8, 11) @test last(interval) == Date(2016, 8, 12) - @test span(interval) == P + @test span(interval) == p @test inclusivity(interval) == inc # DST transition endpoint = ZonedDateTime(2018, 3, 11, 3, tz"America/Winnipeg") - interval = AnchoredInterval{Hour(-2)}(endpoint) + interval = AnchoredInterval(endpoint, Hour(-2)) @test span(interval) == Hour(2) startpoint = ZonedDateTime(2018, 3, 11, tz"America/Winnipeg") - interval = AnchoredInterval{Day(1)}(startpoint) + interval = AnchoredInterval(startpoint, Day(1)) @test first(interval) == startpoint @test last(interval) == ZonedDateTime(2018, 3, 12, tz"America/Winnipeg") @test span(interval) == Day(1) endpoint = ZonedDateTime(2018, 11, 4, 2, tz"America/Winnipeg") - interval = AnchoredInterval{Hour(-2)}(endpoint) + interval = AnchoredInterval(endpoint, Hour(-2)) @test span(interval) == Hour(2) startpoint = ZonedDateTime(2018, 11, 4, tz"America/Winnipeg") - interval = AnchoredInterval{Day(1)}(startpoint) + interval = AnchoredInterval(startpoint, Day(1)) @test first(interval) == startpoint @test last(interval) == ZonedDateTime(2018, 11, 5, tz"America/Winnipeg") @test span(interval) == Day(1) # Non-period AnchoredIntervals - interval = AnchoredInterval{-10}(10) + interval = AnchoredInterval(10, -10) @test first(interval) == 0 @test last(interval) == 10 @test inclusivity(interval) == Inclusivity(false, true) @test span(interval) == 10 - interval = AnchoredInterval{25}('a') + interval = AnchoredInterval('a', 25) @test first(interval) == 'a' @test last(interval) == 'z' @test inclusivity(interval) == Inclusivity(true, false) @@ -106,24 +107,24 @@ using Intervals: canonicalize @testset "display" begin @test sprint(show, HourEnding) == "HourEnding{T}" @test sprint(show, HourBeginning) == "HourBeginning{T}" - @test sprint(show, AnchoredInterval{Hour(-1)}) == - "Intervals.AnchoredInterval{-1 hour,T} where T" - @test sprint(show, AnchoredInterval{Hour(1)}) == - "Intervals.AnchoredInterval{1 hour,T} where T" + @test sprint(show, AnchoredInterval{T, Hour(-1)} where T) == + "Intervals.AnchoredInterval{T,-1 hour} where T" + @test sprint(show, AnchoredInterval{T, Hour(1)} where T) == + "Intervals.AnchoredInterval{T,1 hour} where T" @test sprint(show, HourEnding{DateTime}) == "HourEnding{DateTime}" @test sprint(show, HourBeginning{DateTime}) == "HourBeginning{DateTime}" - @test sprint(show, AnchoredInterval{Hour(-1), DateTime}) == "HourEnding{DateTime}" - @test sprint(show, AnchoredInterval{Hour(1), DateTime}) == "HourBeginning{DateTime}" - - @test sprint(show, AnchoredInterval{Day(-1)}) == - "Intervals.AnchoredInterval{-1 day,T} where T" - @test sprint(show, AnchoredInterval{Day(1)}) == - "Intervals.AnchoredInterval{1 day,T} where T" - @test sprint(show, AnchoredInterval{Day(-1), DateTime}) == - "AnchoredInterval{-1 day, DateTime}" - @test sprint(show, AnchoredInterval{Day(1), DateTime}) == - "AnchoredInterval{1 day, DateTime}" + @test sprint(show, AnchoredInterval{DateTime, Hour(-1)}) == "HourEnding{DateTime}" + @test sprint(show, AnchoredInterval{DateTime, Hour(1)}) == "HourBeginning{DateTime}" + + @test sprint(show, AnchoredInterval{T, Day(-1)} where T) == + "Intervals.AnchoredInterval{T,-1 day} where T" + @test sprint(show, AnchoredInterval{T, Day(1)} where T) == + "Intervals.AnchoredInterval{T,1 day} where T" + @test sprint(show, AnchoredInterval{DateTime, Day(-1)}) == + "AnchoredInterval{DateTime, -1 day}" + @test sprint(show, AnchoredInterval{DateTime, Day(1)}) == + "AnchoredInterval{DateTime, 1 day}" interval = HourEnding(dt) @test string(interval) == "(2016-08-11 HE02]" @@ -175,99 +176,99 @@ using Intervals: canonicalize "Inclusivity(false, true))", ) - interval = AnchoredInterval{Year(-1)}(Date(dt)) + interval = AnchoredInterval(Date(dt), Year(-1)) @test string(interval) == "(YE 2016-08-11]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == - "AnchoredInterval{-1 year, Date}(2016-08-11, Inclusivity(false, true))" + "AnchoredInterval{Date, -1 year}(2016-08-11, Inclusivity(false, true))" - interval = AnchoredInterval{Year(-1)}(ceil(Date(dt), Year)) + interval = AnchoredInterval(ceil(Date(dt), Year), Year(-1)) @test string(interval) == "(YE 2017-01-01]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == - "AnchoredInterval{-1 year, Date}(2017-01-01, Inclusivity(false, true))" + "AnchoredInterval{Date, -1 year}(2017-01-01, Inclusivity(false, true))" - interval = AnchoredInterval{Month(-1)}(dt) + interval = AnchoredInterval(dt, Month(-1)) @test string(interval) == "(MoE 2016-08-11 02:00:00]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == string( - "AnchoredInterval{-1 month, DateTime}(2016-08-11T02:00:00, ", + "AnchoredInterval{DateTime, -1 month}(2016-08-11T02:00:00, ", "Inclusivity(false, true))", ) - interval = AnchoredInterval{Month(-1)}(ceil(dt, Month)) + interval = AnchoredInterval(ceil(dt, Month), Month(-1)) @test string(interval) == "(MoE 2016-09-01]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == string( - "AnchoredInterval{-1 month, DateTime}(2016-09-01T00:00:00, ", + "AnchoredInterval{DateTime, -1 month}(2016-09-01T00:00:00, ", "Inclusivity(false, true))", ) - interval = AnchoredInterval{Day(-1)}(DateTime(dt)) + interval = AnchoredInterval(DateTime(dt), Day(-1)) @test string(interval) == "(DE 2016-08-11 02:00:00]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == string( - "AnchoredInterval{-1 day, DateTime}(2016-08-11T02:00:00, ", + "AnchoredInterval{DateTime, -1 day}(2016-08-11T02:00:00, ", "Inclusivity(false, true))" ) - interval = AnchoredInterval{Day(-1)}(ceil(DateTime(dt), Day)) + interval = AnchoredInterval(ceil(DateTime(dt), Day), Day(-1)) @test string(interval) == "(DE 2016-08-12]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == string( - "AnchoredInterval{-1 day, DateTime}(2016-08-12T00:00:00, ", + "AnchoredInterval{DateTime, -1 day}(2016-08-12T00:00:00, ", "Inclusivity(false, true))" ) # Date(dt) will truncate the DateTime to the nearest day - interval = AnchoredInterval{Day(-1)}(Date(dt)) + interval = AnchoredInterval(Date(dt), Day(-1)) @test string(interval) == "(DE 2016-08-11]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == - "AnchoredInterval{-1 day, Date}(2016-08-11, Inclusivity(false, true))" + "AnchoredInterval{Date, -1 day}(2016-08-11, Inclusivity(false, true))" - interval = AnchoredInterval{Minute(-5)}(dt) + interval = AnchoredInterval(dt, Minute(-5)) @test string(interval) == "(2016-08-11 5ME02:00]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == string( - "AnchoredInterval{-5 minutes, DateTime}(2016-08-11T02:00:00, ", + "AnchoredInterval{DateTime, -5 minutes}(2016-08-11T02:00:00, ", "Inclusivity(false, true))", ) - interval = AnchoredInterval{Second(-30)}(dt) + interval = AnchoredInterval(dt, Second(-30)) @test string(interval) == "(2016-08-11 30SE02:00:00]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == string( - "AnchoredInterval{-30 seconds, DateTime}(2016-08-11T02:00:00, ", + "AnchoredInterval{DateTime, -30 seconds}(2016-08-11T02:00:00, ", "Inclusivity(false, true))", ) - interval = AnchoredInterval{Millisecond(-10)}(dt) + interval = AnchoredInterval(dt, Millisecond(-10)) @test string(interval) == "(2016-08-11 10msE02:00:00.000]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == string( - "AnchoredInterval{-10 milliseconds, DateTime}(2016-08-11T02:00:00, ", + "AnchoredInterval{DateTime, -10 milliseconds}(2016-08-11T02:00:00, ", "Inclusivity(false, true))", ) # Non-period AnchoredIntervals - interval = AnchoredInterval{-10}(10) + interval = AnchoredInterval(10, -10) @test string(interval) == "(0..10]" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == - "AnchoredInterval{-10, $Int}(10, Inclusivity(false, true))" + "AnchoredInterval{$Int, -10}(10, Inclusivity(false, true))" - interval = AnchoredInterval{25}('a') + interval = AnchoredInterval('a', 25) @test string(interval) == "[a..z)" @test sprint(showcompact, interval) == string(interval) @test sprint(show, interval) == - "AnchoredInterval{25, Char}('a', Inclusivity(true, false))" + "AnchoredInterval{Char, 25}('a', Inclusivity(true, false))" end @testset "equality" begin he = HourEnding(dt) hb = HourBeginning(dt) - me = AnchoredInterval{Minute(-1)}(dt) + me = AnchoredInterval(dt, Minute(-1)) cpe = copy(he) cpb = copy(hb) @@ -340,9 +341,9 @@ using Intervals: canonicalize @test he + Minute(30) == HourEnding(dt + Minute(30)) @test he - Minute(30) == HourEnding(dt - Minute(30)) - ai = AnchoredInterval{Minute(-60)}(dt) - @test ai + Minute(30) == AnchoredInterval{Minute(-60)}(dt + Minute(30)) - @test ai - Minute(30) == AnchoredInterval{Minute(-60)}(dt - Minute(30)) + ai = AnchoredInterval(dt, Minute(-60)) + @test ai + Minute(30) == AnchoredInterval(dt + Minute(30), Minute(-60)) + @test ai - Minute(30) == AnchoredInterval(dt - Minute(30), Minute(-60)) # Subtracting AnchoredInterval{P, T} from T doesn't make sense if T is a TimeType @test_throws MethodError Hour(1) - he @@ -350,31 +351,31 @@ using Intervals: canonicalize # DST transition endpoint = ZonedDateTime(2018, 3, 11, 3, tz"America/Winnipeg") - interval = AnchoredInterval{Hour(-2)}(endpoint) + interval = AnchoredInterval(endpoint, Hour(-2)) @test span(interval) == Hour(2) endpoint = ZonedDateTime(2018, 11, 4, 2, tz"America/Winnipeg") - interval = AnchoredInterval{Hour(-2)}(endpoint) + interval = AnchoredInterval(endpoint, Hour(-2)) @test span(interval) == Hour(2) # Non-period AnchoredIntervals - @test AnchoredInterval{10}('a') + 2 == AnchoredInterval{10}('c') - @test AnchoredInterval{10}('d') - 2 == AnchoredInterval{10}('b') + @test AnchoredInterval('a', 10) + 2 == AnchoredInterval('c', 10) + @test AnchoredInterval('d', 10) - 2 == AnchoredInterval('b', 10) - @test AnchoredInterval{-1}(20) + 2 == AnchoredInterval{-1}(22) - @test AnchoredInterval{-1}(20) - 2 == AnchoredInterval{-1}(18) + @test AnchoredInterval(20, -1) + 2 == AnchoredInterval(22, -1) + @test AnchoredInterval(20, -1) - 2 == AnchoredInterval(18, -1) - @test -AnchoredInterval{2}(10) == AnchoredInterval{-2}(-10) # -[10,12)==(-12,-10] - @test -AnchoredInterval{-2}(10) == AnchoredInterval{2}(-10) # -(8,10]==[-10,-8) + @test -AnchoredInterval(10, 2) == AnchoredInterval(-10, -2) # -[10,12)==(-12,-10] + @test -AnchoredInterval(10, -2) == AnchoredInterval(-10, 2) # -(8,10]==[-10,-8) - @test 15 - AnchoredInterval{-2}(10) == AnchoredInterval{2}(5) # 15-(8,10]==[5,8) - @test 15 - AnchoredInterval{2}(10) == AnchoredInterval{-2}(5) # 15-[10,12)==(3,5] + @test 15 - AnchoredInterval(10, -2) == AnchoredInterval(5, 2) # 15-(8,10]==[5,8) + @test 15 - AnchoredInterval(10, 2) == AnchoredInterval(5, -2) # 15-[10,12)==(3,5] - @test_throws MethodError -AnchoredInterval{10}('a') - @test_throws MethodError -AnchoredInterval{-10}('z') + @test_throws MethodError -AnchoredInterval('a', 10) + @test_throws MethodError -AnchoredInterval('z', -10) - @test_throws MethodError 10 - AnchoredInterval{10}('a') - @test_throws MethodError 10 - AnchoredInterval{-10}('z') + @test_throws MethodError 10 - AnchoredInterval('a', 10) + @test_throws MethodError 10 - AnchoredInterval('z', -10) end @testset "range" begin @@ -405,20 +406,20 @@ using Intervals: canonicalize end @testset "isempty" begin - for P in [Year(1), Month(1), Day(1), Hour(1), Minute(1), Second(1)] + for p in [Year(1), Month(1), Day(1), Hour(1), Minute(1), Second(1)] for sign in [+, -] - @test !isempty(AnchoredInterval{sign(P)}(dt, Inclusivity(false, false))) - @test !isempty(AnchoredInterval{sign(P)}(dt, Inclusivity(false, true))) - @test !isempty(AnchoredInterval{sign(P)}(dt, Inclusivity(true, false))) - @test !isempty(AnchoredInterval{sign(P)}(dt, Inclusivity(true, true))) + @test !isempty(AnchoredInterval(dt, sign(p), Inclusivity(false, false))) + @test !isempty(AnchoredInterval(dt, sign(p), Inclusivity(false, true))) + @test !isempty(AnchoredInterval(dt, sign(p), Inclusivity(true, false))) + @test !isempty(AnchoredInterval(dt, sign(p), Inclusivity(true, true))) end end - for P in [Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)] - @test isempty(AnchoredInterval{P}(dt, Inclusivity(false, false))) - @test isempty(AnchoredInterval{P}(dt, Inclusivity(false, true))) - @test isempty(AnchoredInterval{P}(dt, Inclusivity(true, false))) - @test !isempty(AnchoredInterval{P}(dt, Inclusivity(true, true))) + for p in [Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)] + @test isempty(AnchoredInterval(dt, p, Inclusivity(false, false))) + @test isempty(AnchoredInterval(dt, p, Inclusivity(false, true))) + @test isempty(AnchoredInterval(dt, p, Inclusivity(true, false))) + @test !isempty(AnchoredInterval(dt, p, Inclusivity(true, true))) end end @@ -452,7 +453,7 @@ using Intervals: canonicalize @test isempty(intersect(HourEnding(dt), HourEnding(dt + Hour(1)))) # Single point overlap - expected = AnchoredInterval{Hour(0)}(dt, Inclusivity(true, true)) + expected = AnchoredInterval(dt, Hour(0), Inclusivity(true, true)) @test intersect( HourEnding(dt, Inclusivity(true, true)), HourEnding(dt + Hour(1), Inclusivity(true, true)), @@ -460,8 +461,8 @@ using Intervals: canonicalize # Hour overlap he = HourEnding(dt) - @test intersect(he, AnchoredInterval{Hour(-2)}(dt)) == he - @test intersect(AnchoredInterval{Hour(-3)}(dt + Hour(1)), he) == he + @test intersect(he, AnchoredInterval(dt, Hour(-2))) == he + @test intersect(AnchoredInterval(dt + Hour(1), Hour(-3)), he) == he @test intersect(HourBeginning(dt - Hour(1)), he) == HourBeginning(dt - Hour(1), Inclusivity(false, false)) @@ -478,11 +479,11 @@ using Intervals: canonicalize # This should probably be an AnchoredInterval{Hour(0)}, but it's not important @test intersect(HourEnding(dt), HourBeginning(dt)) == - AnchoredInterval{Hour(0)}(dt, Inclusivity(true, true)) + AnchoredInterval(dt, Hour(0), Inclusivity(true, true)) # Non-period AnchoredIntervals - @test intersect(AnchoredInterval{-2}(3), AnchoredInterval{-2}(4)) == - AnchoredInterval{-1}(3) + @test intersect(AnchoredInterval(3, -2), AnchoredInterval(4, -2)) == + AnchoredInterval(3, -1) end @testset "canonicalize" begin