diff --git a/src/Intervals.jl b/src/Intervals.jl index 0c606436..0090ae82 100644 --- a/src/Intervals.jl +++ b/src/Intervals.jl @@ -10,6 +10,10 @@ using Dates: AbstractDateTime, value, coarserperiod import Base: ⊆, ⊇, ⊈, ⊉, union, union!, merge +const CharInts = Union{Char, Integer} +const DatesTypes = Union{Period, TimeType} +const OrderedBaseTypes = Union{Char, Number, DatesTypes} + abstract type Bound end abstract type Bounded <: Bound end struct Closed <: Bounded end diff --git a/src/anchoredinterval.jl b/src/anchoredinterval.jl index aa62a7aa..dd7250a8 100644 --- a/src/anchoredinterval.jl +++ b/src/anchoredinterval.jl @@ -178,7 +178,7 @@ span(interval::AnchoredInterval{P}) where P = abs(P) # Allows an interval to be converted to a scalar when the set contained by the interval only # contains a single element. -function Base.convert(::Type{T}, interval::AnchoredInterval{P,T}) where {P,T} +function Base.convert(::Type{T}, interval::AnchoredInterval{P, T}) where {P, T <: OrderedBaseTypes} if isclosed(interval) && (sign(P) == 0 || first(interval) == last(interval)) return first(interval) else @@ -258,10 +258,20 @@ end ##### ARITHMETIC ##### -Base.:+(a::T, b) where {T <: AnchoredInterval} = T(anchor(a) + b) +Base.:+(a::A, b::T) where {P, T, A <: AnchoredInterval{P,T}} = A(anchor(a) + b) +Base.:+(a::A, b::Number) where {P, T <: Number, A <: AnchoredInterval{P,T}} = A(anchor(a) + b) +Base.:+(a::A, b::CharInts) where {P, T <: CharInts, A <: AnchoredInterval{P,T}} = A(anchor(a) + b) +Base.:+(a::A, b::DatesTypes) where {P, T <: DatesTypes, A <: AnchoredInterval{P,T}} = A(anchor(a) + b) -Base.:+(a, b::AnchoredInterval) = b + a -Base.:-(a::AnchoredInterval, b) = a + -b +Base.:+(a::T, b::AnchoredInterval{P, T}) where {P, T} = b + a +Base.:+(a::Number, b::AnchoredInterval{P, T}) where {P, T <: Number} = b + a +Base.:+(a::CharInts, b::AnchoredInterval{P, T}) where {P, T <: CharInts} = b + a +Base.:+(a::DatesTypes, b::AnchoredInterval{P, T}) where {P, T <: DatesTypes} = b + a + +Base.:-(a::AnchoredInterval{P, T}, b::T) where {P, T} = a + -b +Base.:-(a::AnchoredInterval{P, T}, b::Number) where {P, T <: Number} = a + -b +Base.:-(a::AnchoredInterval{P, T}, b::CharInts) where {P, T <: CharInts} = a + -b +Base.:-(a::AnchoredInterval{P, T}, b::DatesTypes) where {P, T <: DatesTypes} = a + -b # Required for StepRange{<:AnchoredInterval} Base.:-(a::AnchoredInterval, b::AnchoredInterval) = anchor(a) - anchor(b) diff --git a/src/endpoint.jl b/src/endpoint.jl index f8cad3d2..0f952c4d 100644 --- a/src/endpoint.jl +++ b/src/endpoint.jl @@ -145,8 +145,12 @@ function Base.isless(a::RightEndpoint, b::LeftEndpoint) end # Comparisons between Scalars and Endpoints -Base.:(==)(a, b::Endpoint) = a == b.endpoint && isclosed(b) -Base.:(==)(a::Endpoint, b) = b == a +Base.:(==)(a::T, b::Endpoint{T}) where {T} = a == b.endpoint && isclosed(b) +Base.:(==)(a::Endpoint{T}, b::T) where {T} = b == a +Base.:(==)(a::Number, b::Endpoint{<:Number}) = a == b.endpoint && isclosed(b) +Base.:(==)(a::Endpoint{<:Number}, b::Number) = b == a +Base.:(==)(a::DatesTypes, b::Endpoint{<:DatesTypes}) = a == b.endpoint && isclosed(b) +Base.:(==)(a::Endpoint{<:DatesTypes}, b::DatesTypes) = b == a function Base.isless(a, b::LeftEndpoint) return ( diff --git a/src/interval.jl b/src/interval.jl index 281c9842..7fd4ff87 100644 --- a/src/interval.jl +++ b/src/interval.jl @@ -250,7 +250,7 @@ end # Allows an interval to be converted to a scalar when the set contained by the interval only # contains a single element. -function Base.convert(::Type{T}, interval::Interval{T}) where T +function Base.convert(::Type{T}, interval::Interval{T}) where {T <: OrderedBaseTypes} if first(interval) == last(interval) && isclosed(interval) return first(interval) else @@ -291,11 +291,25 @@ end ##### ARITHMETIC ##### -Base.:+(a::T, b) where {T <: Interval} = T(first(a) + b, last(a) + b) +Base.:+(a::A, b::T) where {T, A <: Interval{T}} = A(first(a) + b, last(a) + b) +Base.:+(a::A, b::Number) where {T <: Number, A <: Interval{T}} = A(first(a) + b, last(a) + b) +Base.:+(a::A, b::CharInts) where {T <: CharInts, A <: Interval{T}} = A(first(a) + b, last(a) + b) +Base.:+(a::A, b::DatesTypes) where {T <: DatesTypes, A <: Interval{T}} = A(first(a) + b, last(a) + b) + +Base.:+(a::T, b::Interval{T}) where {T} = b + a +Base.:+(a::Number, b::Interval{T}) where {T <: Number} = b + a +Base.:+(a::CharInts, b::Interval{T}) where {T <: CharInts} = b + a +Base.:+(a::DatesTypes, b::Interval{T}) where {T <: DatesTypes} = b + a + +Base.:-(a::Interval{T}, b::T) where {T} = a + -b +Base.:-(a::T, b::Interval{T}) where {T} = a + -b +Base.:-(a::Interval{T}, b::Number) where {T <: Number} = a + -b +Base.:-(a::Number, b::Interval{T}) where {T <: Number} = a + -b +Base.:-(a::Interval{T}, b::CharInts) where {T <: CharInts} = a + -b +Base.:-(a::CharInts, b::Interval{T}) where {T <: CharInts} = a + -b +Base.:-(a::Interval{T}, b::DatesTypes) where {T <: DatesTypes} = a + -b +Base.:-(a::DatesTypes, b::Interval{T}) where {T <: DatesTypes} = a + -b -Base.:+(a, b::Interval) = b + a -Base.:-(a::Interval, b) = a + -b -Base.:-(a, b::Interval) = a + -b Base.:-(a::Interval{T,L,R}) where {T,L,R} = Interval{T,R,L}(-last(a), -first(a)) ##### EQUALITY #####