Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate negate keyword argument in Dates adjuster API #20213

Merged
merged 3 commits into from
Jan 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 62 additions & 54 deletions base/dates/adjusters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ lastdayofquarter(dt::DateTime) = DateTime(lastdayofquarter(Date(dt)))
immutable DateFunction
f::Function
# validate boolean, single-arg inner constructor
function DateFunction(f::ANY, negate::Bool, dt::TimeType)
function DateFunction(f::ANY, dt::TimeType)
isa(f(dt), Bool) || throw(ArgumentError("Provided function must take a single TimeType argument and return true or false"))
return new(negate ? x -> !f(x)::Bool : f)
return new(f)
end
end
Base.show(io::IO, df::DateFunction) = println(io, df.f)
Expand All @@ -143,89 +143,97 @@ function adjust(df::DateFunction, start, step, limit)
throw(ArgumentError("Adjustment limit reached: $limit iterations"))
end

function adjust(func::Function, start; step::Period=Day(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, start), start, step, limit)
function adjust(func::Function, start; step::Period=Day(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:adjust, func, "func,start", negate)
return adjust(DateFunction(func, start), start, step, limit)
end

# Constructors using DateFunctions

"""
Date(f::Function, y[, m, d]; step=Day(1), negate=false, limit=10000) -> Date
Date(f::Function, y[, m, d]; step=Day(1), limit=10000) -> Date

Create a `Date` through the adjuster API. The starting point will be constructed from the
provided `y, m, d` arguments, and will be adjusted until `f::Function` returns `true`. The
step size in adjusting can be provided manually through the `step` keyword. If
`negate=true`, then the adjusting will stop when `f::Function` returns `false` instead of
`true`. `limit` provides a limit to the max number of iterations the adjustment API will
provided `y, m, d` arguments, and will be adjusted until `f::Function` returns `true`.
The step size in adjusting can be provided manually through the `step` keyword.
`limit` provides a limit to the max number of iterations the adjustment API will
pursue before throwing an error (given that `f::Function` is never satisfied).
"""
function Date(func::Function, y, m=1, d=1;step::Period=Day(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, Date(y, m, d)), Date(y, m, d), step, limit)
function Date(func::Function, y, m=1, d=1;step::Period=Day(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:Date, func, "func,y,m,d", negate)
return adjust(DateFunction(func, Date(y, m, d)), Date(y, m, d), step, limit)
end

"""
DateTime(f::Function, y[, m, d, h, mi, s]; step=Day(1), negate=false, limit=10000) -> DateTime
DateTime(f::Function, y[, m, d, h, mi, s]; step=Day(1), limit=10000) -> DateTime

Create a `DateTime` through the adjuster API. The starting point will be constructed from
the provided `y, m, d...` arguments, and will be adjusted until `f::Function` returns
`true`. The step size in adjusting can be provided manually through the `step` keyword. If
`negate=true`, then the adjusting will stop when `f::Function` returns `false` instead of
`true`. `limit` provides a limit to the max number of iterations the adjustment API will
`true`. The step size in adjusting can be provided manually through the `step` keyword.
`limit` provides a limit to the max number of iterations the adjustment API will
pursue before throwing an error (in the case that `f::Function` is never satisfied).
"""
DateTime(::Function, args...)

function DateTime(func::Function, y, m=1; step::Period=Day(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, DateTime(y, m)), DateTime(y, m), step, limit)
function DateTime(func::Function, y, m=1; step::Period=Day(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:DateTime, func, "func,y,m", negate)
return adjust(DateFunction(func, DateTime(y, m)), DateTime(y, m), step, limit)
end
function DateTime(func::Function, y, m, d; step::Period=Hour(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, DateTime(y)), DateTime(y, m, d), step, limit)
function DateTime(func::Function, y, m, d; step::Period=Hour(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:DateTime, func, "func,y,m,d", negate)
return adjust(DateFunction(func, DateTime(y)), DateTime(y, m, d), step, limit)
end
function DateTime(func::Function, y, m, d, h; step::Period=Minute(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, DateTime(y)), DateTime(y, m, d, h), step, limit)
function DateTime(func::Function, y, m, d, h; step::Period=Minute(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:DateTime, func, "func,y,m,d,h", negate)
return adjust(DateFunction(func, DateTime(y)), DateTime(y, m, d, h), step, limit)
end
function DateTime(func::Function, y, m, d, h, mi; step::Period=Second(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, DateTime(y)), DateTime(y, m, d, h, mi), step, limit)
function DateTime(func::Function, y, m, d, h, mi; step::Period=Second(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:DateTime, func, "func,y,m,d,h,mi", negate)
return adjust(DateFunction(func, DateTime(y)), DateTime(y, m, d, h, mi), step, limit)
end
function DateTime(func::Function, y, m, d, h, mi, s; step::Period=Millisecond(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, DateTime(y)), DateTime(y, m, d, h, mi, s), step, limit)
function DateTime(func::Function, y, m, d, h, mi, s; step::Period=Millisecond(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:DateTime, func, "func,y,m,d,h,mi,s", negate)
return adjust(DateFunction(func, DateTime(y)), DateTime(y, m, d, h, mi, s), step, limit)
end

"""
Time(f::Function, h[, mi, s, ms, us]; step=Second(1), negate=false, limit=10000) -> Time
Time(f::Function, h[, mi, s, ms, us]; step=Second(1), limit=10000) -> Time

Create a `Time` through the adjuster API. The starting point will be constructed from the
provided `h, mi, s, ms, us` arguments, and will be adjusted until `f::Function` returns `true`. The step
size in adjusting can be provided manually through the `step` keyword. If `negate=true`,
then the adjusting will stop when `f::Function` returns `false` instead of `true`. `limit`
provided `h, mi, s, ms, us` arguments, and will be adjusted until `f::Function` returns `true`.
The step size in adjusting can be provided manually through the `step` keyword. `limit`
provides a limit to the max number of iterations the adjustment API will pursue before
throwing an error (in the case that `f::Function` is never satisfied). Note that the default step
will adjust to allow for greater precision for the given arguments; i.e. if hour, minute, and second
arguments are provided, the default step will be `Millisecond(1)` instead of `Second(1)`.
"""
Time(::Function, args...)

function Time(func::Function, h, mi=0; step::Period=Second(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, Time(h, mi)), Time(h, mi), step, limit)
function Time(func::Function, h, mi=0; step::Period=Second(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:Time, func, "func,h,mi", negate)
return adjust(DateFunction(func, Time(h, mi)), Time(h, mi), step, limit)
end
function Time(func::Function, h, mi, s; step::Period=Millisecond(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, Time(h, mi, s)), Time(h, mi, s), step, limit)
function Time(func::Function, h, mi, s; step::Period=Millisecond(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:Time, func, "func,h,mi,s", negate)
return adjust(DateFunction(func, Time(h, mi, s)), Time(h, mi, s), step, limit)
end
function Time(func::Function, h, mi, s, ms; step::Period=Microsecond(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate,Time(h, mi, s, ms)),Time(h, mi, s, ms), step, limit)
function Time(func::Function, h, mi, s, ms; step::Period=Microsecond(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:Time, func, "func,h,mi,s,ms", negate)
return adjust(DateFunction(func, Time(h, mi, s, ms)), Time(h, mi, s, ms), step, limit)
end
function Time(func::Function, h, mi, s, ms, us; step::Period=Nanosecond(1), negate::Bool=false, limit::Int=10000)
return adjust(DateFunction(func, negate, Time(h, mi, s, ms, us)), Time(h, mi, s, ms, us), step, limit)
function Time(func::Function, h, mi, s, ms, us; step::Period=Nanosecond(1), negate=nothing, limit::Int=10000)
func = deprecate_negate(:Time, func, "func,h,mi,s,ms,us", negate)
return adjust(DateFunction(func, Time(h, mi, s, ms, us)), Time(h, mi, s, ms, us), step, limit)
end

# Return the next TimeType that falls on dow
ISDAYOFWEEK = Dict(Mon => DateFunction(ismonday, false, Date(0)),
Tue => DateFunction(istuesday, false, Date(0)),
Wed => DateFunction(iswednesday, false, Date(0)),
Thu => DateFunction(isthursday, false, Date(0)),
Fri => DateFunction(isfriday, false, Date(0)),
Sat => DateFunction(issaturday, false, Date(0)),
Sun => DateFunction(issunday, false, Date(0)))
ISDAYOFWEEK = Dict(Mon => DateFunction(ismonday, Date(0)),
Tue => DateFunction(istuesday, Date(0)),
Wed => DateFunction(iswednesday, Date(0)),
Thu => DateFunction(isthursday, Date(0)),
Fri => DateFunction(isfriday, Date(0)),
Sat => DateFunction(issaturday, Date(0)),
Sun => DateFunction(issunday, Date(0)))

# "same" indicates whether the current date can be considered or not
"""
Expand All @@ -239,15 +247,15 @@ tonext(dt::TimeType, dow::Int; same::Bool=false) = adjust(ISDAYOFWEEK[dow], same

# Return the next TimeType where func evals true using step in incrementing
"""
tonext(func::Function,dt::TimeType;step=Day(1),negate=false,limit=10000,same=false) -> TimeType
tonext(func::Function,dt::TimeType;step=Day(1),limit=10000,same=false) -> TimeType

Adjusts `dt` by iterating at most `limit` iterations by `step` increments until `func`
returns `true`. `func` must take a single `TimeType` argument and return a `Bool`. `same`
allows `dt` to be considered in satisfying `func`. `negate` will make the adjustment process
terminate when `func` returns `false` instead of `true`.
allows `dt` to be considered in satisfying `func`.
"""
function tonext(func::Function, dt::TimeType;step::Period=Day(1), negate::Bool=false, limit::Int=10000, same::Bool=false)
return adjust(DateFunction(func, negate, dt), same ? dt : dt+step, step, limit)
function tonext(func::Function, dt::TimeType;step::Period=Day(1), negate=nothing, limit::Int=10000, same::Bool=false)
func = deprecate_negate(:tonext, func, "func,dt", negate)
return adjust(DateFunction(func, dt), same ? dt : dt+step, step, limit)
end

"""
Expand All @@ -260,15 +268,15 @@ Tuesday, etc`. Setting `same=true` allows the current `dt` to be considered as t
toprev(dt::TimeType, dow::Int; same::Bool=false) = adjust(ISDAYOFWEEK[dow], same ? dt : dt+Day(-1), Day(-1), 7)

"""
toprev(func::Function,dt::TimeType;step=Day(-1),negate=false,limit=10000,same=false) -> TimeType
toprev(func::Function,dt::TimeType;step=Day(-1),limit=10000,same=false) -> TimeType

Adjusts `dt` by iterating at most `limit` iterations by `step` increments until `func`
returns `true`. `func` must take a single `TimeType` argument and return a `Bool`. `same`
allows `dt` to be considered in satisfying `func`. `negate` will make the adjustment process
terminate when `func` returns `false` instead of `true`.
allows `dt` to be considered in satisfying `func`.
"""
function toprev(func::Function, dt::TimeType; step::Period=Day(-1), negate::Bool=false, limit::Int=10000, same::Bool=false)
return adjust(DateFunction(func, negate, dt), same ? dt : dt+step, step, limit)
function toprev(func::Function, dt::TimeType; step::Period=Day(-1), negate=nothing, limit::Int=10000, same::Bool=false)
func = deprecate_negate(:toprev, func, "func,dt", negate)
return adjust(DateFunction(func, dt), same ? dt : dt+step, step, limit)
end

# Return the first TimeType that falls on dow in the Month or Year
Expand Down
18 changes: 17 additions & 1 deletion base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,7 @@ end
# Not exported
eval(LibGit2, quote
function owner(x)
depwarn("owner(x) is deprecated, use repository(x) instead.", :owner)
Base.depwarn("owner(x) is deprecated, use repository(x) instead.", :owner)
repository(x)
end
end)
Expand All @@ -1786,4 +1786,20 @@ function colon{T<:Dates.Period}(start::T, stop::T)
colon(start, T(1), stop)
end

# when this deprecation is deleted, remove all calls to it, and all
# negate=nothing keyword arguments, from base/dates/adjusters.jl
eval(Dates, quote
function deprecate_negate(f, func, sig, negate)
if negate === nothing
return func
else
msg = "$f($sig; negate=$negate) is deprecated, use $f("
negate && (msg *= "!")
msg *= "$sig) instead."
Base.depwarn(msg, f)
return negate ? !func : func
end
end
end)

# End deprecations scheduled for 0.6
11 changes: 6 additions & 5 deletions test/dates/adjusters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ dt = Dates.Date(2014,5,21)

@test Dates.tonext(Dates.Date(0),Dates.Mon) == Dates.Date(0,1,3)

#test func, diff steps, negate, same
#test func, diff steps, same
@test Dates.tonext(Dates.iswednesday,dt) == Dates.Date(2014,5,28)
@test Dates.tonext(Dates.iswednesday,dt;same=true) == dt
@test Dates.tonext(Dates.isthursday,dt) == Dates.Date(2014,5,22)
Expand All @@ -240,7 +240,8 @@ dt = Dates.Date(2014,5,21)
@test Dates.tonext(Dates.istuesday,dt) == Dates.Date(2014,5,27)
@test Dates.tonext(Dates.ismonday,Dates.Date(0)) == Dates.Date(0,1,3)

@test Dates.tonext(x->!Dates.iswednesday(x),dt;negate=true) == Dates.Date(2014,5,28)
@test Dates.tonext(!Dates.iswednesday,dt) == Dates.Date(2014,5,22)
@test Dates.tonext(!Dates.isthursday,dt) == Dates.Date(2014,5,23)
# Reach adjust limit
@test_throws ArgumentError Dates.tonext(Dates.iswednesday,dt;limit=6)

Expand Down Expand Up @@ -322,8 +323,8 @@ Januarymondays2014 = [Dates.Date(2014,1,6),Dates.Date(2014,1,13),Dates.Date(2014
@test filter(Dates.ismonday,startdate:stopdate) == Januarymondays2014

@test_throws MethodError filter((x,y)->x+y,Dates.Date(2013):Dates.Date(2014))
@test_throws MethodError Dates.DateFunction((x,y)->x+y, false, Date(0))
@test_throws ArgumentError Dates.DateFunction((dt)->2, false, Date(0))
@test_throws MethodError Dates.DateFunction((x,y)->x+y, Date(0))
@test_throws ArgumentError Dates.DateFunction((dt)->2, Date(0))
@test length(filter(x->true,Dates.Date(2013):Dates.Date(2013,2))) == 32
@test length(filter(x->true,Dates.Date(2013):Dates.Date(2013,1,1))) == 1
@test length(filter(x->true,Dates.Date(2013):Dates.Date(2013,1,2))) == 2
Expand Down Expand Up @@ -469,4 +470,4 @@ r = Dates.Time(x->Dates.second(x) == 5, 1)
r = filter(x->Dates.second(x) == 5, Dates.Time(0):Dates.Time(10))
@test length(r) == 600
@test first(r) == Dates.Time(0,0,5)
@test last(r) == Dates.Time(9,59,5)
@test last(r) == Dates.Time(9,59,5)
4 changes: 2 additions & 2 deletions test/dates/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -536,5 +536,5 @@ a = Dates.Time(23,1,1)
@test map(x->a in x,drs[1:4]) == [true,true,false,true]
@test a in dr

@test all(x->sort(x) == (step(x) < zero(step(x)) ? reverse(x) : x),drs)
@test all(x->step(x) < zero(step(x)) ? issorted(reverse(x)) : issorted(x),drs)
@test all(x->sort(x) == (step(x) < zero(step(x)) ? reverse(x) : x), drs)
@test all(x->step(x) < zero(step(x)) ? issorted(reverse(x)) : issorted(x), drs)