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

day of week cleanup #19212

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
* Make DayOfWeek an Enum, deprecate dayofweek. (#19210)
* Provide optional argument to `firsdayofweek`/`lastdayofweek` (#19208)
* A few misc fixes.
  • Loading branch information
simonbyrne committed Nov 18, 2016
commit 03bee90c88a2602856c2801e76395d38678d2634
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd like to still keep this lowercase dayofweek, it follows the more general pattern in Dates with types being proper-cased and accessors being lowercased.


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