Skip to content

Commit

Permalink
Edit/Fix ranges.jl.
Browse files Browse the repository at this point in the history
  • Loading branch information
antimon2 committed May 4, 2017
1 parent fb06ce2 commit f8b97b2
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/QDates.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ include("accessors.jl")
include("query.jl")
include("arithmetic.jl")
include("conversions.jl")
# include("ranges.jl")
include("ranges.jl")
# include("adjusters.jl")
# include("rounding.jl")
include("io.jl")
Expand Down
21 changes: 21 additions & 0 deletions src/ranges.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# ranges.jl

# Given a start and end date, how many steps/periods are in between
Dates.guess(a::QDate, b::QDate, c) = Int64(div(Int64(b - a), days(c)))

function Dates.len(a::QDate,b::QDate,c)
lo, hi, st = min(a,b), max(a,b), abs(c)
i = Dates.guess(a,b,c)-1
try
while lo+st*i <= hi
i += 1
end
catch ex
if !isa(ex, ArgumentError)
rethrow()
# else
# #pass
end
end
return i-1
end
17 changes: 9 additions & 8 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@

immutable QDate <: TimeType
instant::UTInstant{Day}
QDate(instant::UTInstant{Day}) = new(instant)
QDate(instant::UTInstant{Day}) = new(_check_instant(instant))
end
@inline function _check_instant(instant::UTInstant{Day})
val = instant.periods.value
if !(FIRST_VALUE <= val <= LAST_VALUE)
throw(ArgumentError("Instant value: $val out of range ($FIRST_VALUE:$LAST_VALUE)"))
end
instant
end

@inline QDate(year::Integer, month::Integer=1, day::Integer=1) = QDate(year, month, false, day)
function QDate(year::Integer, month::Integer, leap::Bool, day::Integer)
# jdn = _rqref(year, month, leap, day)
Expand All @@ -22,13 +30,6 @@ end
_rqref(Cint[FIRST_VALUE+DAYS_OFFSET,year,0,month,day,0,leap])
end

function _check_value(value::Int)
if !(FIRST_VALUE <= value <= LAST_VALUE)
throw(DomainError())
end
end
@inline _check_value(instant::UTInstant{Day}) = _check_value(instant.periods.value)

@inline QDate(y::Year, m::Month=Month(1), d::Day=Day(1)) = QDate(value(y), value(m), false, value(d))
@inline QDate(y::Year, m::Month, l::Bool, d::Day=Day(1)) = QDate(value(y), value(m), l, value(d))

Expand Down
3 changes: 2 additions & 1 deletion test/accessors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ function test_qdates(from,to)
end
end
end
test_qdates(445,2100)
# test_qdates(445,2100)
test_qdates(1970,2020)

# broadcasting
a = QDates.QDate(2014,1,1)
Expand Down
215 changes: 215 additions & 0 deletions test/ranges.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
# ranges.jl

function test_almost_all_combos()
let T=QDates.QDate
f1 = T(2014); l1 = T(2013,12,30)
f2 = T(2014); l2 = T(2014)
f3 = T(1970); l3 = T(2020)
# f4 = typemin(T); l4 = typemax(T)

for P in (Dates.Day, Dates.Month, Dates.Year)
for pos_step in (P(1),P(2),P(50))
# empty range
dr = f1:pos_step:l1
@test length(dr) == 0
@test isempty(dr)
@test first(dr) == f1
@test last(dr) < f1
@test length([i for i in dr]) == 0
@test_throws ArgumentError minimum(dr)
@test_throws ArgumentError maximum(dr)
@test_throws BoundsError dr[1]
@test findin(dr,dr) == Int64[]
@test [dr;] == T[]
@test isempty(reverse(dr))
@test length(reverse(dr)) == 0
@test first(reverse(dr)) < f1
@test last(reverse(dr)) >= f1
@test issorted(dr)
@test sortperm(dr) == 1:1:0
@test !(f1 in dr)
@test !(l1 in dr)
@test !(f1-pos_step in dr)
@test !(l1+pos_step in dr)

# for (f,l) in ((f2,l2),(f3,l3),(f4,l4))
for (f,l) in ((f2,l2),(f3,l3))
dr = f:pos_step:l
len = length(dr)
@test len > 0
@test typeof(len) <: Int64
@test !isempty(dr)
@test first(dr) == f
@test last(dr) <= l
@test minimum(dr) == first(dr)
@test maximum(dr) == last(dr)
@test dr[1] == f
@test dr[end] <= l
@test next(dr,start(dr)) == (first(dr),1)

if len < 10000
dr1 = [i for i in dr]
@test length(dr1) == len
@test findin(dr,dr) == [1:len;]
@test length([dr;]) == len
end
@test !isempty(reverse(dr))
@test length(reverse(dr)) == len
@test last(reverse(dr)) == f
@test issorted(dr)
@test f in dr

end
end
for neg_step in (P(-1),P(-2),P(-50))
# empty range
dr = l1:neg_step:f1
@test length(dr) == 0
@test isempty(dr)
@test first(dr) == l1
@test last(dr) > l1
@test length([i for i in dr]) == 0
@test_throws ArgumentError minimum(dr)
@test_throws ArgumentError maximum(dr)
@test_throws BoundsError dr[1]
@test findin(dr,dr) == Int64[]
@test [dr;] == T[]
@test isempty(reverse(dr))
@test length(reverse(dr)) == 0
@test first(reverse(dr)) > l1
@test last(reverse(dr)) <= l1
@test !issorted(dr)
@test sortperm(dr) == 0:-1:1
@test !(l1 in dr)
@test !(l1 in dr)
@test !(l1-neg_step in dr)
@test !(l1+neg_step in dr)

# for (f,l) in ((f2,l2),(f3,l3),(f4,l4))
for (f,l) in ((f2,l2),(f3,l3))
dr = l:neg_step:f
len = length(dr)
@test len > 0
@test typeof(len) <: Int64
@test !isempty(dr)
@test first(dr) == l
@test last(dr) >= f
@test minimum(dr) == last(dr)
@test maximum(dr) == first(dr)
@test dr[1] == l
@test dr[end] >= f
@test next(dr,start(dr)) == (first(dr),1)

if len < 10000
dr1 = [i for i in dr]
@test length(dr1) == len
@test findin(dr,dr) == [1:len;]
@test length([dr;]) == len
end
@test !isempty(reverse(dr))
@test length(reverse(dr)) == len
@test !issorted(dr)
@test l in dr
end
end
end
end
end
test_almost_all_combos()

# All the range representations we want to test
# Date ranges
dr = QDates.QDate(2014,1,1):QDates.QDate(2014,2,1)
dr1 = QDates.QDate(2014,1,1):QDates.QDate(2014,1,1)
dr2 = QDates.QDate(2014,1,1):QDates.QDate(2013,2,1) # empty range
dr3 = QDates.QDate(2014,1,1):Dates.Day(-1):QDates.QDate(2013,1,1) # negative step
# Big ranges
dr4 = QDates.QDate(500):QDates.QDate(2000,1,1)
dr9 = typemin(QDates.QDate):typemax(QDates.QDate)
# Non-default steps
dr10 = typemax(QDates.QDate):Dates.Day(-1):typemin(QDates.QDate)
dr12 = typemin(QDates.QDate):Dates.Month(1):typemax(QDates.QDate)
dr13 = typemin(QDates.QDate):Dates.Year(1):typemax(QDates.QDate)
dr15 = typemin(QDates.QDate):Dates.Month(100):typemax(QDates.QDate)
dr16 = typemin(QDates.QDate):Dates.Year(1000):typemax(QDates.QDate)
dr20 = typemin(QDates.QDate):Dates.Day(2):typemax(QDates.QDate)

drs = Any[dr,dr1,dr2,dr3,dr4,dr9,dr10,
dr12,dr13,dr15,dr16,dr20]

@test map(length,drs) == map(x->size(x)[1],drs)
@test all(x->findin(x,x) == [1:length(x);], drs[1:4])
@test isempty(dr2)
@test all(x->reverse(x) == last(x):-step(x):first(x),drs)
@test all(x->minimum(x) == (step(x) < zero(step(x)) ? last(x) : first(x)),drs[4:end])
@test all(x->maximum(x) == (step(x) < zero(step(x)) ? first(x) : last(x)),drs[4:end])
@test all(drs[1:3]) do dd
for (i,d) in enumerate(dd)
@test d == (first(dd) + Dates.Day(i-1))
end
true
end
# @test_throws MethodError dr + 1
a = QDates.QDate(2014,1,1)
b = QDates.QDate(2014,2,1)
@test map!(x->x+Dates.Day(1),Array{QDates.QDate}(30),dr) == [(a+Dates.Day(1)):(b+Dates.Day(1));]
@test map(x->x+Dates.Day(1),dr) == [(a+Dates.Day(1)):(b+Dates.Day(1));]

@test map(x->a in x,drs[1:4]) == [true,true,false,true]
@test a in dr
@test b in dr
@test QDates.QDate(2014,1,3) in dr
@test QDates.QDate(2014,1,15) in dr
@test QDates.QDate(2014,1,26) in dr
@test !(QDates.QDate(2013,1,1) 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 length(b:Dates.Day(-1):a) == 30
@test length(b:a) == 0
@test length(b:Dates.Day(1):a) == 0
@test length(a:Dates.Day(2):b) == 15
@test last(a:Dates.Day(2):b) == QDates.QDate(2014,1,29)
@test length(a:Dates.Day(7):b) == 5
@test last(a:Dates.Day(7):b) == QDates.QDate(2014,1,29)
@test length(a:Dates.Day(30):b) == 1
@test last(a:Dates.Day(30):b) == QDates.QDate(2014,1,1)
@test (a:b)[1] == QDates.QDate(2014,1,1)
@test (a:b)[2] == QDates.QDate(2014,1,2)
@test (a:b)[7] == QDates.QDate(2014,1,7)
@test (a:b)[end] == b
@test first(a:QDates.QDate(2099,1,1)) == a
@test first(a:typemax(QDates.QDate)) == a
@test first(typemin(QDates.QDate):typemax(QDates.QDate)) == typemin(QDates.QDate)

# Non-default step sizes
@test length(typemin(QDates.QDate):Dates.Month(1):typemax(QDates.QDate)) == 20482
@test length(typemin(QDates.QDate):Dates.Year(1):typemax(QDates.QDate)) == 1656

c = QDates.QDate(2014,6,1)
@test length(a:Dates.Month(1):c) == 6
@test [a:Dates.Month(1):c;] == [a + Dates.Month(1)*i for i in 0:5]
@test [a:Dates.Month(2):QDates.QDate(2014,1,2);] == [a]
@test [c:Dates.Month(-1):a;] == reverse([a:Dates.Month(1):c;])
@test length(a:Dates.Month(1):QDates.QDate(2014,10,1)) == 11

d = QDates.QDate(2020,1,1)
@test length(a:Dates.Year(1):d) == 7
@test first(a:Dates.Year(1):d) == a
@test last(a:Dates.Year(1):d) == d
@test length(a:Dates.Month(12):d) == 7
@test first(a:Dates.Month(12):d) == a
@test last(a:Dates.Month(12):d) == QDates.QDate(2019,11,1)
@test length(a:Dates.Day(365):d) == 6
@test first(a:Dates.Day(365):d) == a
@test last(a:Dates.Day(365):d) == QDates.QDate(2018,12,25)

@test length(a:Dates.Year(1):QDates.QDate(2020,2,1)) == 7
@test length(a:Dates.Year(1):QDates.QDate(2020,6,1)) == 7
@test length(a:Dates.Year(1):QDates.QDate(2020,11,1)) == 7
@test length(a:Dates.Year(1):QDates.QDate(2020,12,30)) == 7
@test length(a:Dates.Year(1):QDates.QDate(2021,1,1)) == 8
@test length(QDates.QDate(2000):Dates.Year(-10):QDates.QDate(1900)) == 11
@test length(QDates.QDate(2000,6,23):Dates.Year(-10):QDates.QDate(1900,2,28)) == 11
@test length(QDates.QDate(2000,1,1):Dates.Year(1):QDates.QDate(2000,2,1)) == 1
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using QDates
using Base.Test

tests = ["types", "accessors", "query", "arithmetic", "conversions"]
tests = ["types", "accessors", "query", "arithmetic", "conversions", "ranges"]

for test in tests
println("start testing: $test.jl")
Expand Down
5 changes: 4 additions & 1 deletion test/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ test = QDates.QDate(2017,1,1)
@test_throws InexactError QDates.QDate(1.2f0,1.f0,1.f0)
@test_throws InexactError QDates.QDate(3//4,Rational(1),Rational(1)) == test

# Months, days, hours, minutes, seconds, and milliseconds must be in range
# Value must be in range
@test_throws ArgumentError QDates.QDate(Dates.UTD(QDates.FIRST_VALUE - 1))
@test_throws ArgumentError QDates.QDate(Dates.UTD(QDates.LAST_VALUE + 1))
# Months and days must be in range
@test_throws ArgumentError QDates.QDate(444,1,1)
@test_throws ArgumentError QDates.QDate(2101,1,1)
@test_throws ArgumentError QDates.QDate(2013,0,1)
Expand Down

0 comments on commit f8b97b2

Please sign in to comment.