mirror of
https://github.com/hakanensari/frankfurter.git
synced 2024-11-21 18:42:29 +01:00
Ensure intuitive behavior when querying across holidays (#71)
This commit is contained in:
parent
e5815737c1
commit
7c99f214e6
File diff suppressed because one or more lines are too long
15
lib/day.rb
15
lib/day.rb
@ -3,13 +3,24 @@
|
|||||||
class Day < Sequel::Model
|
class Day < Sequel::Model
|
||||||
dataset_module do
|
dataset_module do
|
||||||
def latest(date = Date.today)
|
def latest(date = Date.today)
|
||||||
where(date: select(:date).where(Sequel.lit("date <= ?", date))
|
where(date: select(:date).where(Sequel[:date] <= date)
|
||||||
.order(Sequel.desc(:date))
|
.order(Sequel.desc(:date))
|
||||||
.limit(1))
|
.limit(1))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns rates for a given date interval
|
||||||
|
#
|
||||||
|
# If the start date falls on a holiday/weekend, rates start from the closest preceding business day.
|
||||||
def between(interval)
|
def between(interval)
|
||||||
where(date: interval)
|
return where(false) if interval.begin > Date.today
|
||||||
|
|
||||||
|
previous_date = select(:date)
|
||||||
|
.where(Sequel[:date] <= interval.begin)
|
||||||
|
.order(Sequel.desc(:date))
|
||||||
|
.limit(1)
|
||||||
|
|
||||||
|
where(Sequel.expr(:date) >= Sequel.function(:coalesce, previous_date, interval.begin))
|
||||||
|
.where(Sequel.expr(:date) <= interval.end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def currencies
|
def currencies
|
||||||
|
@ -5,29 +5,54 @@ require "day"
|
|||||||
|
|
||||||
describe Day do
|
describe Day do
|
||||||
describe ".latest" do
|
describe ".latest" do
|
||||||
it "returns latest rates before given date" do
|
it "returns latest available rates on given date" do
|
||||||
|
date = Date.parse("2010-01-04")
|
||||||
|
data = Day.latest(date)
|
||||||
|
_(data.to_a.sample.date).must_equal(date)
|
||||||
|
|
||||||
date = Date.parse("2010-01-01")
|
date = Date.parse("2010-01-01")
|
||||||
data = Day.latest(date)
|
data = Day.latest(date)
|
||||||
_(data.first.date).must_be(:<=, date)
|
_(data.to_a.sample.date).must_equal(Date.parse("2009-12-31"))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns nothing if there are no rates before given date" do
|
it "returns nothing if date predates dataset" do
|
||||||
_(Day.latest(Date.parse("1998-01-01"))).must_be_empty
|
_(Day.latest(Date.parse("1901-01-01"))).must_be_empty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe ".between" do
|
describe ".between" do
|
||||||
it "returns rates between given dates" do
|
it "returns rates between given working dates" do
|
||||||
start_date = Date.parse("2010-01-01")
|
start_date = Date.parse("2010-01-04")
|
||||||
end_date = Date.parse("2010-01-31")
|
end_date = Date.parse("2010-01-29")
|
||||||
dates = Day.between((start_date..end_date)).map(:date).sort
|
dates = Day.between((start_date..end_date)).map(:date).sort
|
||||||
_(dates.first).must_be(:>=, start_date)
|
_(dates.first).must_equal(start_date)
|
||||||
_(dates.last).must_be(:<=, end_date)
|
_(dates.last).must_equal(end_date)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns nothing if there are no rates between given dates" do
|
it "starts on preceding business day if start date is a holiday" do
|
||||||
interval = (Date.parse("1998-01-01")..Date.parse("1998-01-31"))
|
start_date = Date.parse("2024-11-03")
|
||||||
|
end_date = Date.parse("2024-11-04")
|
||||||
|
dates = Day.between((start_date..end_date)).map(:date)
|
||||||
|
_(dates).must_include(Date.parse("2024-11-01"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns nothing if end date predates dataset" do
|
||||||
|
interval = (Date.parse("1901-01-01")..Date.parse("1901-01-31"))
|
||||||
_(Day.between(interval)).must_be_empty
|
_(Day.between(interval)).must_be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "allows start date to predate dataset" do
|
||||||
|
start_date = Date.parse("1901-01-01")
|
||||||
|
end_date = Date.parse("2024-01-01")
|
||||||
|
dates = Day.between((start_date..end_date)).map(:date)
|
||||||
|
_(dates).wont_be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns nothing if queried for the future" do
|
||||||
|
start_date = Date.today + 1
|
||||||
|
end_date = start_date + 1
|
||||||
|
dates = Day.between((start_date..end_date)).map(:date)
|
||||||
|
_(dates).must_be_empty
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -22,8 +22,16 @@ module Quote
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "quotes given date interval" do
|
it "quotes given date interval" do
|
||||||
_(Date.parse(quote.formatted[:start_date])).must_be(:>=, dates.first)
|
returned_start = Date.parse(quote.formatted[:start_date])
|
||||||
_(Date.parse(quote.formatted[:end_date])).must_be(:<=, dates.last)
|
returned_end = Date.parse(quote.formatted[:end_date])
|
||||||
|
|
||||||
|
# The returned start date should be the closest working day (before or on) the requested start
|
||||||
|
_(returned_start).must_be(:<=, dates.first)
|
||||||
|
# But it shouldn't be too far back (maybe 10 business days)
|
||||||
|
_(returned_start).must_be(:>, dates.first - 10)
|
||||||
|
|
||||||
|
# End date should still be within the requested range
|
||||||
|
_(returned_end).must_be(:<=, dates.last)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "quotes against the Euro" do
|
it "quotes against the Euro" do
|
||||||
|
Loading…
Reference in New Issue
Block a user