Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

Commit

Permalink
Support isless and == between all Period subtypes (JuliaLang#21378)
Browse files Browse the repository at this point in the history
  • Loading branch information
omus authored and JeffBezanson committed May 2, 2017
1 parent 9fc78ae commit ef02bc6
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
16 changes: 10 additions & 6 deletions base/dates/periods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ default(p::Union{T,Type{T}}) where {T<:DatePeriod} = T(1)
default(p::Union{T,Type{T}}) where {T<:TimePeriod} = T(0)

(-)(x::P) where {P<:Period} = P(-value(x))
==(x::P, y::P) where {P<:Period} = value(x) == value(y)
==(x::Period, y::Period) = (==)(promote(x, y)...)
Base.isless(x::P, y::P) where {P<:Period} = isless(value(x), value(y))
(==)(x::P, y::P) where {P<:Period} = value(x) == value(y)
Base.isless(x::Period, y::Period) = isless(promote(x, y)...)

# Period Arithmetic, grouped by dimensionality:
import Base: div, fld, mod, rem, gcd, lcm, +, -, *, /, %
Expand Down Expand Up @@ -425,9 +427,6 @@ for i = 1:length(fixedperiod_conversions)
N *= nc
end
end
# have to declare thusly so that diagonal dispatch above takes precedence:
(==)(x::T, y::S) where {T<:FixedPeriod,S<:FixedPeriod} = (==)(promote(x, y)...)
Base.isless(x::T, y::S) where {T<:FixedPeriod,S<:FixedPeriod} = isless(promote(x, y)...)

# other periods with fixed conversions but which aren't fixed time periods
const OtherPeriod = Union{Month, Year}
Expand All @@ -439,8 +438,13 @@ let vmax = typemax(Int64) ÷ 12, vmin = typemin(Int64) ÷ 12
end
Base.convert(::Type{Year}, x::Month) = Year(divexact(value(x), 12))
Base.promote_rule(::Type{Year}, ::Type{Month}) = Month
(==)(x::T, y::S) where {T<:OtherPeriod,S<:OtherPeriod} = (==)(promote(x, y)...)
Base.isless(x::T, y::S) where {T<:OtherPeriod,S<:OtherPeriod} = isless(promote(x, y)...)

# disallow comparing fixed to other periods
(==)(x::FixedPeriod, y::OtherPeriod) = throw(MethodError(==, (x, y)))
(==)(x::OtherPeriod, y::FixedPeriod) = throw(MethodError(==, (x, y)))

Base.isless(x::FixedPeriod, y::OtherPeriod) = throw(MethodError(isless, (x, y)))
Base.isless(x::OtherPeriod, y::FixedPeriod) = throw(MethodError(isless, (x, y)))

# truncating conversions to milliseconds and days:
toms(c::Nanosecond) = div(value(c), 1000000)
Expand Down
20 changes: 20 additions & 0 deletions test/dates/periods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,26 @@ test = ((((((((dt + y) - m) + w) - d) + h) - mi) + s) - ms)
@test !(Dates.Millisecond(-1) > Dates.Millisecond(1))
@test Dates.Millisecond(1) == Dates.Millisecond(1)
@test_throws MethodError Dates.Year(1) < Dates.Millisecond(1)
@test_throws MethodError Dates.Millisecond(1) < Dates.Year(1)
@test_throws MethodError Dates.Year(1) == Dates.Millisecond(1)
@test_throws MethodError Dates.Millisecond(1) == Dates.Year(1)

# Allow comparisons with new Period subtypes
let
# https://en.wikipedia.org/wiki/Swatch_Internet_Time
struct Beat <: Dates.Period
value::Int64
end

Dates.value(b::Beat) = b.value
Dates.toms(b::Beat) = Dates.value(b) * 86400
Dates._units(b::Beat) = " beat" * (abs(Dates.value(b)) == 1 ? "" : "s")
Base.promote_rule(::Type{Dates.Day}, ::Type{Beat}) = Dates.Millisecond
Base.convert{T<:Dates.Millisecond}(::Type{T}, b::Beat) = T(Dates.toms(b))

@test Beat(1000) == Dates.Day(1)
@test Beat(1) < Dates.Day(1)
end

@test Dates.Year("1") == y
@test Dates.Month("1") == m
Expand Down

0 comments on commit ef02bc6

Please sign in to comment.