Skip to content

Commit

Permalink
* Make DayOfWeek an Enum, deprecate dayofweek. (#19210)
Browse files Browse the repository at this point in the history
* Provide optional argument to `firsdayofweek`/`lastdayofweek` (#19208)
* A few misc fixes.
  • Loading branch information
simonbyrne committed Nov 18, 2016
1 parent 01ef3c3 commit 03bee90
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 112 deletions.
2 changes: 1 addition & 1 deletion base/dates/Dates.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export Period, DatePeriod, TimePeriod,
yearmonthday, yearmonth, monthday, year, month, week, day,
hour, minute, second, millisecond, dayofmonth,
# query.jl
dayofweek, isleapyear, daysinmonth, daysinyear, dayofyear, dayname, dayabbr,
DayOfWeek, isleapyear, daysinmonth, daysinyear, dayofyear, dayname, dayabbr,
dayofweekofmonth, daysofweekinmonth, monthname, monthabbr,
quarterofyear, dayofquarter,
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday,
Expand Down
7 changes: 7 additions & 0 deletions base/dates/accessors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,15 @@ end

# Accessor functions
value(dt::TimeType) = dt.instant.periods.value

"""
days(dt::TimeType) -> Int64
The Rata Die day number: the number of days since `Date("0000-12-31")`.
"""
days(dt::Date) = value(dt)
days(dt::DateTime) = fld(value(dt),86400000)

year(dt::TimeType) = year(days(dt))
month(dt::TimeType) = month(days(dt))
week(dt::TimeType) = week(days(dt))
Expand Down
66 changes: 29 additions & 37 deletions base/dates/adjusters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,26 @@ Dates.trunc(::Dates.TimeType, ::Type{Dates.Period})

# Adjusters
"""
firstdayofweek(dt::TimeType) -> TimeType
firstdayofweek(dt::TimeType[, firstday::DayOfWeek=Monday]) -> TimeType
Adjusts `dt` to the Monday of its week.
Adjusts `dt` to the first day of its week. The optional second argument specifies the
`DayOfWeek` which starts the week: by default, this is `Monday`, as per ISO 8601.
"""
function firstdayofweek end

firstdayofweek(dt::Date) = Date(UTD(value(dt) - dayofweek(dt) + 1))
firstdayofweek(dt::DateTime) = DateTime(firstdayofweek(Date(dt)))
firstdayofweek(dt::Date, firstday::DayOfWeek=Monday) = dt - Day(mod(Int(DayOfWeek(dt)) - Int(firstday),7))
firstdayofweek(dt::DateTime, firstday::DayOfWeek=Monday) = DateTime(firstdayofweek(Date(dt),firstday))

"""
lastdayofweek(dt::TimeType) -> TimeType
lastdayofweek(dt::TimeType[, lastday::DayOfWeek=Sunday]) -> TimeType
Adjusts `dt` to the Sunday of its week.
Adjusts `dt` to the last day of its week. The optional second argument specifies the
`DayOfWeek` which ends the week: by default, this is `Sunday`, as per ISO 8601.
"""
function lastdayofweek end

lastdayofweek(dt::Date) = Date(UTD(value(dt) + (7 - dayofweek(dt))))
lastdayofweek(dt::DateTime) = DateTime(lastdayofweek(Date(dt)))
lastdayofweek(dt::Date, lastday::DayOfWeek=Sunday) = dt + Day(mod(Int(lastday) - Int(DayOfWeek(dt)),7))
lastdayofweek(dt::DateTime, lastday::DayOfWeek=Sunday) = DateTime(lastdayofweek(Date(dt),lastday))

"""
firstdayofmonth(dt::TimeType) -> TimeType
Expand All @@ -49,7 +51,7 @@ Adjusts `dt` to the first day of its month.
"""
function firstdayofmonth end

firstdayofmonth(dt::Date) = Date(UTD(value(dt) - day(dt) + 1))
firstdayofmonth(dt::Date) = dt - Day(dayofmonth(dt) - 1)
firstdayofmonth(dt::DateTime) = DateTime(firstdayofmonth(Date(dt)))

"""
Expand All @@ -61,7 +63,7 @@ function lastdayofmonth end

function lastdayofmonth(dt::Date)
y, m, d = yearmonthday(dt)
return Date(UTD(value(dt) + daysinmonth(y, m) - d))
return dt + Day(daysinmonth(y, m) - d)
end
lastdayofmonth(dt::DateTime) = DateTime(lastdayofmonth(Date(dt)))

Expand All @@ -72,7 +74,7 @@ Adjusts `dt` to the first day of its year.
"""
function firstdayofyear end

firstdayofyear(dt::Date) = Date(UTD(value(dt) - dayofyear(dt) + 1))
firstdayofyear(dt::Date) = dt - Day(dayofyear(dt) - 1)
firstdayofyear(dt::DateTime) = DateTime(firstdayofyear(Date(dt)))

"""
Expand All @@ -84,7 +86,7 @@ function lastdayofyear end

function lastdayofyear(dt::Date)
y, m, d = yearmonthday(dt)
return Date(UTD(value(dt) + daysinyear(y) - dayofyear(y, m, d)))
return dt + Day(daysinyear(y) - dayofyear(y, m, d))
end
lastdayofyear(dt::DateTime) = DateTime(lastdayofyear(Date(dt)))

Expand Down Expand Up @@ -184,24 +186,14 @@ function DateTime(func::Function, y, m, d, h, mi, s; step::Period=Millisecond(1)
return adjust(DateFunction(func, negate, DateTime(y)), DateTime(y, m, d, h, mi, s), 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)))

# "same" indicates whether the current date can be considered or not
"""
tonext(dt::TimeType,dow::Int;same::Bool=false) -> TimeType
tonext(dt::TimeType, dow::DayOfWeek; same::Bool=false) -> TimeType
Adjusts `dt` to the next day of week corresponding to `dow` with `1 = Monday, 2 = Tuesday,
etc`. Setting `same=true` allows the current `dt` to be considered as the next `dow`,
allowing for no adjustment to occur.
Adjusts `dt` to the next day of week corresponding to `dow`. Setting `same=true` allows
the current `dt` to be considered as the next `dow`, allowing for no adjustment to occur.
"""
tonext(dt::TimeType, dow::Int; same::Bool=false) = adjust(ISDAYOFWEEK[dow], same ? dt : dt+Day(1), Day(1), 7)
tonext(dt::TimeType, dow::DayOfWeek; same::Bool=false) = lastdayofweek(same ? dt : dt+Day(1), dow)

# Return the next TimeType where func evals true using step in incrementing
"""
Expand All @@ -217,13 +209,13 @@ function tonext(func::Function, dt::TimeType;step::Period=Day(1), negate::Bool=f
end

"""
toprev(dt::TimeType,dow::Int;same::Bool=false) -> TimeType
toprev(dt::TimeType, dow::DayOfWeek; same::Bool=false) -> TimeType
Adjusts `dt` to the previous day of week corresponding to `dow` with `1 = Monday, 2 =
Tuesday, etc`. Setting `same=true` allows the current `dt` to be considered as the previous
`dow`, allowing for no adjustment to occur.
Adjusts `dt` to the previous day of week corresponding to `dow`. Setting `same=true`
allows the current `dt` to be considered as the previous `dow`, allowing for no adjustment
to occur.
"""
toprev(dt::TimeType, dow::Int; same::Bool=false) = adjust(ISDAYOFWEEK[dow], same ? dt : dt+Day(-1), Day(-1), 7)
toprev(dt::TimeType, dow::DayOfWeek; same::Bool=false) = firstdayofweek(same ? dt : dt-Day(1), dow)

"""
toprev(func::Function,dt::TimeType;step=Day(-1),negate=false,limit=10000,same=false) -> TimeType
Expand All @@ -239,24 +231,24 @@ end

# Return the first TimeType that falls on dow in the Month or Year
"""
tofirst(dt::TimeType,dow::Int;of=Month) -> TimeType
tofirst(dt::TimeType, dow::DayOfWeek; of=Month) -> TimeType
Adjusts `dt` to the first `dow` of its month. Alternatively, `of=Year` will adjust to the
first `dow` of the year.
"""
function tofirst(dt::TimeType, dow::Int; of::Union{Type{Year}, Type{Month}}=Month)
function tofirst(dt::TimeType, dow::DayOfWeek; of::Union{Type{Year}, Type{Month}}=Month)
dt = of <: Month ? firstdayofmonth(dt) : firstdayofyear(dt)
return adjust(ISDAYOFWEEK[dow], dt, Day(1), 366)
lastdayofweek(dt, dow)
end

# Return the last TimeType that falls on dow in the Month or Year
"""
tolast(dt::TimeType,dow::Int;of=Month) -> TimeType
tolast(dt::TimeType, dow::DayOfWeek; of=Month) -> TimeType
Adjusts `dt` to the last `dow` of its month. Alternatively, `of=Year` will adjust to the
last `dow` of the year.
"""
function tolast(dt::TimeType, dow::Int; of::Union{Type{Year}, Type{Month}}=Month)
function tolast(dt::TimeType, dow::DayOfWeek; of::Union{Type{Year}, Type{Month}}=Month)
dt = of <: Month ? lastdayofmonth(dt) : lastdayofyear(dt)
return adjust(ISDAYOFWEEK[dow], dt, Day(-1), 366)
firstdayofweek(dt, dow)
end
4 changes: 2 additions & 2 deletions base/dates/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,9 @@ function slotformat(slot::Slot{Month},dt,locale)
end
function slotformat(slot::Slot{DayOfWeekSlot},dt,locale)
if slot.letter == 'e'
return VALUETODAYOFWEEKABBR[locale][dayofweek(dt)]
return VALUETODAYOFWEEKABBR[locale][DayOfWeek(dt)]
else # == 'E'
return VALUETODAYOFWEEK[locale][dayofweek(dt)]
return VALUETODAYOFWEEK[locale][DayOfWeek(dt)]
end
end
slotformat(slot::Slot{Millisecond},dt,locale) = rpad(string(millisecond(dt)/1000.0)[3:end], slot.width, "0")
Expand Down
75 changes: 44 additions & 31 deletions base/dates/query.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@

### Core query functions

# Monday = 1....Sunday = 7
dayofweek(days) = mod1(days,7)

# Number of days in year
"""
daysinyear(dt::TimeType) -> Int
Expand All @@ -20,49 +17,64 @@ const MONTHDAYS = [0,31,59,90,120,151,181,212,243,273,304,334]
dayofyear(y,m,d) = MONTHDAYS[m] + d + (m > 2 && isleapyear(y))

### Days of the Week
"""
dayofweek(dt::TimeType) -> Int64
@enum DayOfWeek Monday=1 Tuesday=2 Wednesday=3 Thursday=4 Friday=5 Saturday=6 Sunday=7

Returns the day of the week as an `Int64` with `1 = Monday, 2 = Tuesday, etc.`.
"""
dayofweek(dt::TimeType) = dayofweek(days(dt))
DayOfWeek(n::Integer)
const Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday = 1,2,3,4,5,6,7
const Mon,Tue,Wed,Thu,Fri,Sat,Sun = 1,2,3,4,5,6,7
const english_daysofweek = Dict(1=>"Monday",2=>"Tuesday",3=>"Wednesday",
4=>"Thursday",5=>"Friday",6=>"Saturday",7=>"Sunday")
const VALUETODAYOFWEEK = Dict{String,Dict{Int,String}}("english"=>english_daysofweek)
const english_daysofweekabbr = Dict(1=>"Mon",2=>"Tue",3=>"Wed",
4=>"Thu",5=>"Fri",6=>"Sat",7=>"Sun")
const VALUETODAYOFWEEKABBR = Dict{String,Dict{Int,String}}("english"=>english_daysofweekabbr)
dayname(dt::Integer;locale::AbstractString="english") = VALUETODAYOFWEEK[locale][dt]
An `Enum` with `DayOfWeek(1) == Monday`, `DayOfWeek(2) == Tuesday`, etc. Accepts an
arbitrary-sized integer, from which days will be computed modulo 7.
```jldoctest
julia> DayOfWeek(8) == Monday
true
```
"""
dayabbr(dt::TimeType; locale="english") -> AbstractString
DayOfWeek(n::Integer) = convert(DayOfWeek, mod1(n, 7))

Return the abbreviated name corresponding to the day of the week of the `Date` or `DateTime`
in the given `locale`.
"""
dayabbr(dt::Integer;locale::AbstractString="english") = VALUETODAYOFWEEKABBR[locale][dt]
DayOfWeek(dt::TimeType)
Returns the day of the week of `dt` as an element of the enum `DayOfWeek`.
"""
DayOfWeek(dt::TimeType) = DayOfWeek(days(dt))


const Mon,Tue,Wed,Thu,Fri,Sat,Sun = Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday

const english_daysofweek = Dict(k => string(k) for k in instances(DayOfWeek))
const VALUETODAYOFWEEK = Dict{String,Dict{DayOfWeek,String}}("english"=>english_daysofweek)

const english_daysofweekabbr = Dict(k => string(k)[1:3] for k in instances(DayOfWeek))
const VALUETODAYOFWEEKABBR = Dict{String,Dict{DayOfWeek,String}}("english"=>english_daysofweekabbr)

dayname(dow::DayOfWeek;locale::AbstractString="english") = VALUETODAYOFWEEK[locale][dow]
dayabbr(dow::DayOfWeek;locale::AbstractString="english") = VALUETODAYOFWEEKABBR[locale][dow]

"""
dayname(dt::TimeType; locale="english") -> AbstractString
Return the full day name corresponding to the day of the week of the `Date` or `DateTime` in
the given `locale`.
"""
dayname(dt::TimeType;locale::AbstractString="english") = VALUETODAYOFWEEK[locale][dayofweek(dt)]
dayname(dt::TimeType;locale::AbstractString="english") = VALUETODAYOFWEEK[locale][DayOfWeek(dt)]

dayabbr(dt::TimeType;locale::AbstractString="english") = VALUETODAYOFWEEKABBR[locale][dayofweek(dt)]
"""
dayabbr(dt::TimeType; locale="english") -> AbstractString
Return the abbreviated name corresponding to the day of the week of the `Date` or `DateTime`
in the given `locale`.
"""
dayabbr(dt::TimeType;locale::AbstractString="english") = VALUETODAYOFWEEKABBR[locale][DayOfWeek(dt)]

# Convenience methods for each day
ismonday(dt::TimeType) = dayofweek(dt) == Mon
istuesday(dt::TimeType) = dayofweek(dt) == Tue
iswednesday(dt::TimeType) = dayofweek(dt) == Wed
isthursday(dt::TimeType) = dayofweek(dt) == Thu
isfriday(dt::TimeType) = dayofweek(dt) == Fri
issaturday(dt::TimeType) = dayofweek(dt) == Sat
issunday(dt::TimeType) = dayofweek(dt) == Sun
ismonday(dt::TimeType) = DayOfWeek(dt) == Mon
istuesday(dt::TimeType) = DayOfWeek(dt) == Tue
iswednesday(dt::TimeType) = DayOfWeek(dt) == Wed
isthursday(dt::TimeType) = DayOfWeek(dt) == Thu
isfriday(dt::TimeType) = DayOfWeek(dt) == Fri
issaturday(dt::TimeType) = DayOfWeek(dt) == Sat
issunday(dt::TimeType) = DayOfWeek(dt) == Sun

# i.e. 1st Monday? 2nd Monday? 3rd Wednesday? 5th Sunday?
"""
Expand All @@ -71,9 +83,10 @@ issunday(dt::TimeType) = dayofweek(dt) == Sun
For the day of week of `dt`, returns which number it is in `dt`'s month. So if the day of
the week of `dt` is Monday, then `1 = First Monday of the month, 2 = Second Monday of the
month, etc.` In the range 1:5.
See also `daysofweekinmonth`.
"""
dayofweekofmonth(dt::TimeType) = (d = day(dt); return d < 8 ? 1 :
d < 15 ? 2 : d < 22 ? 3 : d < 29 ? 4 : 5)
dayofweekofmonth(dt::TimeType) = fld1(dayofmonth(dt), 7)

# Total number of a day of week in the month
# e.g. are there 4 or 5 Mondays in this month?
Expand Down
16 changes: 16 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,22 @@ eval(Base.Dates, quote
end
end
recur{T<:TimeType}(fun::Function, start::T, stop::T; step::Period=Day(1), negate::Bool=false, limit::Int=10000) = recur(fun, start:step:stop; negate=negate)

# #19212
eval(Base.Dates,quote
@deprecate(dayofweek(dt), Int64(DayOfWeek(dt)))
@deprecate(tonext(dt::TimeType, dow::Int; same::Bool=false),
tonext(dt, DayOfWeek(dow); same=same))
@deprecate(toprev(dt::TimeType, dow::Int; same::Bool=false),
toprev(dt, DayOfWeek(dow); same=same))
@deprecate(tofirst(dt::TimeType, dow::Int; of::Union{Type{Year}, Type{Month}}=Month),
tofirst(dt, DayOfWeek(dow); same=same))
@deprecate(tolast(dt::TimeType, dow::Int; of::Union{Type{Year}, Type{Month}}=Month),
tolast(dt, DayOfWeek(dow); same=same))
@deprecate(dayname(dt::Integer;locale::AbstractString="english"),
dayname(DayOfWeek(dt); locale=locale))
@deprecate(dayabbr(dt::Integer;locale::AbstractString="english"),
dayabbr(DayOfWeek(dt); locale=locale))
end)

# End deprecations scheduled for 0.6
Loading

0 comments on commit 03bee90

Please sign in to comment.