Skip to content

Commit

Permalink
Remove commutative subtraction methods. Fixes #20205
Browse files Browse the repository at this point in the history
  • Loading branch information
quinnj committed Jan 26, 2017
1 parent 665563b commit 94aa901
Show file tree
Hide file tree
Showing 3 changed files with 409 additions and 418 deletions.
78 changes: 39 additions & 39 deletions base/dates/arithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

# Instant arithmetic
(+)(x::Instant) = x
(-){T<:Instant}(x::T,y::T) = x.periods - y.periods
(-){T<:Instant}(x::T, y::T) = x.periods - y.periods

# TimeType arithmetic
(+)(x::TimeType) = x
(-){T<:TimeType}(x::T,y::T) = x.instant - y.instant
(-){T<:TimeType}(x::T, y::T) = x.instant - y.instant

# Date-Time arithmetic
"""
Expand All @@ -24,74 +24,74 @@ end
(+)(t::Time, dt::Date) = dt + t

# TimeType-Year arithmetic
function (+)(dt::DateTime,y::Year)
oy,m,d = yearmonthday(dt); ny = oy+value(y); ld = daysinmonth(ny,m)
return DateTime(ny,m,d <= ld ? d : ld,hour(dt),minute(dt),second(dt),millisecond(dt))
function (+)(dt::DateTime, y::Year)
oy, m, d = yearmonthday(dt); ny = oy + value(y); ld = daysinmonth(ny, m)
return DateTime(ny, m, d <= ld ? d : ld, hour(dt), minute(dt), second(dt), millisecond(dt))
end
function (+)(dt::Date,y::Year)
oy,m,d = yearmonthday(dt); ny = oy+value(y); ld = daysinmonth(ny,m)
return Date(ny,m,d <= ld ? d : ld)
oy, m, d = yearmonthday(dt); ny = oy + value(y); ld = daysinmonth(ny, m)
return Date(ny, m, d <= ld ? d : ld)
end
function (-)(dt::DateTime,y::Year)
oy,m,d = yearmonthday(dt); ny = oy-value(y); ld = daysinmonth(ny,m)
return DateTime(ny,m,d <= ld ? d : ld,hour(dt),minute(dt),second(dt),millisecond(dt))
oy, m, d = yearmonthday(dt); ny = oy - value(y); ld = daysinmonth(ny, m)
return DateTime(ny, m, d <= ld ? d : ld, hour(dt), minute(dt), second(dt), millisecond(dt))
end
function (-)(dt::Date,y::Year)
oy,m,d = yearmonthday(dt); ny = oy-value(y); ld = daysinmonth(ny,m)
return Date(ny,m,d <= ld ? d : ld)
oy, m, d = yearmonthday(dt); ny = oy - value(y); ld = daysinmonth(ny, m)
return Date(ny, m, d <= ld ? d : ld)
end

# TimeType-Month arithmetic
# monthwrap adds two months with wraparound behavior (i.e. 12 + 1 == 1)
monthwrap(m1,m2) = (v = mod1(m1+m2,12); return v < 0 ? 12 + v : v)
monthwrap(m1, m2) = (v = mod1(m1 + m2, 12); return v < 0 ? 12 + v : v)
# yearwrap takes a starting year/month and a month to add and returns
# the resulting year with wraparound behavior (i.e. 2000-12 + 1 == 2001)
yearwrap(y,m1,m2) = y + fld(m1 + m2 - 1,12)
yearwrap(y, m1, m2) = y + fld(m1 + m2 - 1, 12)

function (+)(dt::DateTime,z::Month)
function (+)(dt::DateTime, z::Month)
y,m,d = yearmonthday(dt)
ny = yearwrap(y,m,value(z))
mm = monthwrap(m,value(z)); ld = daysinmonth(ny,mm)
return DateTime(ny,mm,d <= ld ? d : ld,hour(dt),minute(dt),second(dt),millisecond(dt))
ny = yearwrap(y, m, value(z))
mm = monthwrap(m, value(z)); ld = daysinmonth(ny, mm)
return DateTime(ny, mm, d <= ld ? d : ld, hour(dt), minute(dt), second(dt), millisecond(dt))
end
function (+)(dt::Date,z::Month)
function (+)(dt::Date, z::Month)
y,m,d = yearmonthday(dt)
ny = yearwrap(y,m,value(z))
mm = monthwrap(m,value(z)); ld = daysinmonth(ny,mm)
return Date(ny,mm,d <= ld ? d : ld)
ny = yearwrap(y, m, value(z))
mm = monthwrap(m, value(z)); ld = daysinmonth(ny, mm)
return Date(ny, mm, d <= ld ? d : ld)
end
function (-)(dt::DateTime,z::Month)
function (-)(dt::DateTime, z::Month)
y,m,d = yearmonthday(dt)
ny = yearwrap(y,m,-value(z))
mm = monthwrap(m,-value(z)); ld = daysinmonth(ny,mm)
return DateTime(ny,mm,d <= ld ? d : ld,hour(dt),minute(dt),second(dt),millisecond(dt))
ny = yearwrap(y, m, -value(z))
mm = monthwrap(m, -value(z)); ld = daysinmonth(ny, mm)
return DateTime(ny, mm, d <= ld ? d : ld, hour(dt), minute(dt), second(dt), millisecond(dt))
end
function (-)(dt::Date,z::Month)
function (-)(dt::Date, z::Month)
y,m,d = yearmonthday(dt)
ny = yearwrap(y,m,-value(z))
mm = monthwrap(m,-value(z)); ld = daysinmonth(ny,mm)
return Date(ny,mm,d <= ld ? d : ld)
ny = yearwrap(y, m, -value(z))
mm = monthwrap(m, -value(z)); ld = daysinmonth(ny, mm)
return Date(ny, mm, d <= ld ? d : ld)
end
(+)(x::Date, y::Week) = return Date(UTD(value(x) + 7*value(y)))
(-)(x::Date, y::Week) = return Date(UTD(value(x) - 7*value(y)))
(+)(x::Date, y::Week) = return Date(UTD(value(x) + 7 * value(y)))
(-)(x::Date, y::Week) = return Date(UTD(value(x) - 7 * value(y)))
(+)(x::Date, y::Day) = return Date(UTD(value(x) + value(y)))
(-)(x::Date, y::Day) = return Date(UTD(value(x) - value(y)))
(+)(x::DateTime, y::Period) = return DateTime(UTM(value(x) + toms(y)))
(-)(x::DateTime, y::Period) = return DateTime(UTM(value(x) - toms(y)))
(+)(x::Time, y::TimePeriod) = return Time(Nanosecond(value(x) + tons(y)))
(-)(x::Time, y::TimePeriod) = return Time(Nanosecond(value(x) - tons(y)))
(+)(y::Period, x::TimeType) = x + y
(-)(y::Period, x::TimeType) = x - y

for op in (:+, :-)
@eval begin
# GeneralPeriod, AbstractArray{TimeType}
($op){T<:TimeType}(x::AbstractArray{T}, y::GeneralPeriod) = broadcast($op,x,y)
($op){T<:TimeType}(y::GeneralPeriod, x::AbstractArray{T}) = broadcast($op,x,y)

# TimeType, StridedArray{GeneralPeriod}
($op){T<:TimeType,P<:GeneralPeriod}(x::StridedArray{P}, y::T) = broadcast($op,x,y)
($op){P<:GeneralPeriod}(y::TimeType, x::StridedArray{P}) = broadcast($op,x,y)
($op){T<:TimeType}(x::AbstractArray{T}, y::GeneralPeriod) = broadcast($op, x, y)
($op){P<:GeneralPeriod}(y::TimeType, x::StridedArray{P}) = broadcast($op, x, y)
end
if op == :+
@eval begin
($op){T<:TimeType}(y::GeneralPeriod, x::AbstractArray{T}) = broadcast($op, x, y)
($op){T<:TimeType,P<:GeneralPeriod}(x::StridedArray{P}, y::T) = broadcast($op, x, y)
end
end
end

Expand Down
36 changes: 18 additions & 18 deletions base/dates/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,35 @@ Base.range(start::Date, len::Integer) = range(start, Day(1), len)
throw(ArgumentError("must specify step as a Period when constructing Dates ranges"))

# Given a start and end date, how many steps/periods are in between
guess(a::DateTime,b::DateTime,c) = floor(Int64,(Int128(value(b)) - Int128(value(a)))/toms(c))
guess(a::Date,b::Date,c) = Int64(div(value(b - a),days(c)))
len(a::Time,b::Time,c) = Int64(div(value(b - a), tons(c)))
function len(a,b,c)
lo, hi, st = min(a,b), max(a,b), abs(c)
i = guess(a,b,c)-1
while lo+st*i <= hi
guess(a::DateTime, b::DateTime, c) = floor(Int64, (Int128(value(b)) - Int128(value(a))) / toms(c))
guess(a::Date, b::Date, c) = Int64(div(value(b - a), days(c)))
len(a::Time, b::Time, c) = Int64(div(value(b - a), tons(c)))
function len(a, b, c)
lo, hi, st = min(a, b), max(a, b), abs(c)
i = guess(a, b, c) - 1
while lo + st * i <= hi
i += 1
end
return i-1
return i - 1
end
Base.length{T<:TimeType}(r::StepRange{T}) = isempty(r) ? 0 : len(r.start,r.stop,r.step) + 1
Base.length{T<:TimeType}(r::StepRange{T}) = isempty(r) ? 0 : len(r.start, r.stop, r.step) + 1
# Period ranges hook into Int64 overflow detection
Base.length{P<:Period}(r::StepRange{P}) = length(StepRange(value(r.start),value(r.step),value(r.stop)))
Base.length{P<:Period}(r::StepRange{P}) = length(StepRange(value(r.start), value(r.step), value(r.stop)))

# Used to calculate the last valid date in the range given the start, stop, and step
# last = stop - steprem(start,stop,step)
Base.steprem{T<:TimeType}(a::T,b::T,c) = b - (a + c*len(a,b,c))
# last = stop - steprem(start, stop, step)
Base.steprem{T<:TimeType}(a::T, b::T, c) = b - (a + c * len(a, b, c))

import Base.in
function in{T<:TimeType}(x::T, r::StepRange{T})
n = len(first(r),x,step(r)) + 1
n = len(first(r), x, step(r)) + 1
n >= 1 && n <= length(r) && r[n] == x
end

Base.start{T<:TimeType}(r::StepRange{T}) = 0
Base.next{T<:TimeType}(r::StepRange{T}, i::Int) = (r.start+r.step*i,i+1)
Base.done{T<:TimeType,S<:Period}(r::StepRange{T,S}, i::Integer) = length(r) <= i
Base.next{T<:TimeType}(r::StepRange{T}, i::Int) = (r.start + r.step*i, i + 1)
Base.done{T<:TimeType, S<:Period}(r::StepRange{T, S}, i::Integer) = length(r) <= i

+{T<:TimeType}(x::Period, r::Range{T}) = (x+first(r)):step(r):(x+last(r))
+{T<:TimeType}(r::Range{T},x::Period) = x + r
-{T<:TimeType}(r::Range{T},x::Period) = (first(r)-x):step(r):(last(r)-x)
+{T<:TimeType}(x::Period, r::Range{T}) = (x + first(r)):step(r):(x + last(r))
+{T<:TimeType}(r::Range{T}, x::Period) = x + r
-{T<:TimeType}(r::Range{T}, x::Period) = (first(r)-x):step(r):(last(r)-x)
Loading

0 comments on commit 94aa901

Please sign in to comment.