Skip to content

Commit

Permalink
modified Types such that Year and Month are part of CalendarPeriod wr…
Browse files Browse the repository at this point in the history
…apped around Int

Week, Day, Hour, Minute, Second are wrapped around Real to allow for conversion between
Millisecond remained wrapped around Int
Ref Issue #9393
  • Loading branch information
Kyle Buzby committed Dec 21, 2014
1 parent d6514f4 commit 7ed7be7
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 17 deletions.
2 changes: 1 addition & 1 deletion base/Dates.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ include("dates/ranges.jl")
include("dates/adjusters.jl")
include("dates/io.jl")

export Period, DatePeriod, TimePeriod,
export Period, CalendarPeriod, TimePeriod,
Year, Month, Week, Day, Hour, Minute, Second, Millisecond,
TimeZone, UTC, TimeType, DateTime, Date,
# accessors.jl
Expand Down
14 changes: 11 additions & 3 deletions base/dates/periods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,16 @@ Base.typemin{P<:Period}(::Type{P}) = P(typemin(Int64))
Base.typemax{P<:Period}(::Type{P}) = P(typemax(Int64))

# Default values (as used by TimeTypes)
default{T<:DatePeriod}(p::Union(T,Type{T})) = one(p)
default{T<:TimePeriod}(p::Union(T,Type{T})) = zero(p)
for t in (:Year,:Month,:Week,:Day)
@eval begin
default{T<:$t}(p::Union(T,Type{T})) = one(p)
end
end
for t in (:Hour, :Minute, :Second, :Millisecond)
@eval begin
default{T<:$t}(p::Union(T,Type{T})) = zero(p)
end
end

(-){P<:Period}(x::P) = P(-value(x))
Base.isless{P<:Period}(x::P,y::P) = isless(value(x),value(y))
Expand Down Expand Up @@ -247,7 +255,7 @@ for i = 1:length(fixedperiod_conversions)
N = n
for j = i+1:length(fixedperiod_conversions) # more-precise periods
(Tc,nc) = fixedperiod_conversions[j]
@eval Base.convert(::Type{$T}, x::$Tc) = $T(divexact(value(x), $N))
@eval Base.convert(::Type{$T}, x::$Tc) = $T(value(x)/$N)
@eval Base.promote_rule(::Type{$T},::Type{$Tc}) = $Tc
N *= nc
end
Expand Down
27 changes: 18 additions & 9 deletions base/dates/types.jl
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@

abstract AbstractTime

abstract Period <: AbstractTime
abstract DatePeriod <: Period
abstract CalendarPeriod <: Period
abstract TimePeriod <: Period

for T in (:Year,:Month,:Week,:Day)
@eval immutable $T <: DatePeriod
for T in (:Year,:Month)
@eval immutable $T <: CalendarPeriod
value::Int64
$T(v::Number) = new(v)
end
end
for T in (:Hour,:Minute,:Second,:Millisecond)
for T in (:Week,:Day,:Hour,:Minute,:Second)
@eval immutable $T <: TimePeriod
value::Int64
$T(v::Number) = new(v)
value::Real
$T(v::Real) = new(v)
end
end
immutable Millisecond <: TimePeriod
value::Int64
Millisecond(v::Number) = new(v)
end

# Instant types represent different monotonically increasing timelines
abstract Instant <: AbstractTime
Expand Down Expand Up @@ -63,7 +68,9 @@ function totaldays(y,m,d)
z = m < 3 ? y - 1 : y
mdays = SHIFTEDMONTHDAYS[m]
# days + month_days + year_days
return d + mdays + 365z + fld(z,4) - fld(z,100) + fld(z,400) - 306
return with_rounding(Float64,RoundDown) do
d + mdays + 365z + fld(z,4) - fld(z,100) + fld(z,400) - 306
end
end

# If the year is divisible by 4, except for every 100 years, except for every 400 years
Expand All @@ -83,13 +90,15 @@ function DateTime(y::Int64,m::Int64=1,d::Int64=1,
-1 < mi < 60 || throw(ArgumentError("Minute: $mi out of range (1:59)"))
-1 < s < 60 || throw(ArgumentError("Second: $s out of range (1:59)"))
-1 < ms < 1000 || throw(ArgumentError("Millisecond: $ms out of range (1:999)"))
rata = ms + 1000*(s + 60mi + 3600h + 86400*totaldays(y,m,d))
rata = with_rounding(Float64,RoundDown) do
(ms + 1000*(s + 60mi + 3600h + 86400*totaldays(y,m,d)))
end
return DateTime(UTM(rata))
end
function Date(y::Int64,m::Int64=1,d::Int64=1)
0 < m < 13 || throw(ArgumentError("Month: $m out of range (1:12)"))
0 < d < daysinmonth(y,m)+1 || throw(ArgumentError("Day: $d out of range (1:$daysinmonth(y,m))"))
return Date(UTD(totaldays(y,m,d)))
return Date(UTD(trunc(totaldays(y,m,d))))
end

# Convenience constructors from Periods
Expand Down
3 changes: 0 additions & 3 deletions test/dates/conversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ let t = Dates.Period[Dates.Week(2), Dates.Day(14), Dates.Hour(14*24), Dates.Minu
Pj = typeof(t[j])
tj1 = t[j] + one(Pj)
@test t[i] < tj1
@test_throws InexactError Pi(tj1)
@test_throws InexactError Pj(Pi(typemax(Int64)))
@test_throws InexactError Pj(Pi(typemin(Int64)))
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions test/dates/periods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,7 @@ emptyperiod = ((y + d) - d) - y
@test 8d - s == 1w + 23h + 59mi + 59s
@test h + 3mi == 63mi
@test y - m == 11m


#Gadfly issue with date_bar
@test Dates.Day(40)/39 == Dates.Day(40/39)
2 changes: 1 addition & 1 deletion test/dates/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function test_all_combos()
f3 = T(-2000); l3 = T(2000)
f4 = typemin(T); l4 = typemax(T)

for P in subtypes(Dates.DatePeriod)
for P in subtypes(Dates.CalendarPeriod)
for pos_step in (P(1),P(2),P(50),P(2048),P(10000))
# empty range
dr = f1:pos_step:l1
Expand Down

0 comments on commit 7ed7be7

Please sign in to comment.