Skip to content

Instantly share code, notes, and snippets.

@rafaltrojanowski
Last active September 11, 2020 07:12
Show Gist options
  • Save rafaltrojanowski/a946f4a5aa7a493d1d9a49771a6c6f0a to your computer and use it in GitHub Desktop.
Save rafaltrojanowski/a946f4a5aa7a493d1d9a49771a6c6f0a to your computer and use it in GitHub Desktop.
require 'date'
def daily_cost(start_date, end_date, time_period_costs)
daily_cost = {}
if start_date > end_date
raise "Wrong time period given."
end
(start_date..end_date).each do |date|
time_period_costs.each do |time_period_cost|
unless time_period_cost[:cost].is_a?(Float)
raise "Wrong cost given."
end
daily_cost[date] ||= 0
if time_period_cost[:time_period] == :daily
daily_cost[date] = time_period_cost[:cost]
elsif time_period_cost[:time_period] == :weekly
daily_cost[date] += time_period_cost[:cost] / 7
elsif time_period_cost[:time_period] == :monthly
daily_cost[date] += time_period_cost[:cost] / days_in_month(date.year, date.month)
else
raise "Wrong time interval given."
end
end
end
daily_cost
end
def days_in_month(year, month)
Date.new(year, month, -1).day
end
require 'spec_helper'
require_relative '../daily_cost.rb'
describe '#daily_cost' do
it 'should work when empty time periods passed in' do
expect(daily_cost(Date.new, Date.new, {})).to eq({})
end
describe "error handling" do
it 'raises wrong time period' do
start_date = Date.new(2020, 9, 2)
end_date = Date.new(2020, 9, 1)
expect {daily_cost(start_date, end_date, {})}
.to raise_error(RuntimeError, "Wrong time period given.")
end
it 'raises wrong time interval' do
start_date = Date.new(2020, 9, 1)
end_date = Date.new(2020, 9, 2)
time_period_costs = [
{
time_period: :yearly,
cost: 30.0
}
]
expect {daily_cost(start_date, end_date, time_period_costs)}
.to raise_error(RuntimeError, "Wrong time interval given.")
end
end
context 'when mixed time periods passed in' do
it 'returns correct value for all time periods' do
start_date = Date.new(2019, 10, 1)
end_date = Date.new(2019, 10, 3)
time_period_costs = [
{
time_period: :daily,
cost: 10.0
},
{
time_period: :weekly,
cost: 70.0
},
{
time_period: :monthly,
cost: 31.0
}
]
expect(daily_cost(start_date, end_date, time_period_costs))
.to eq({
Date.new(2019, 10, 1) => 21.0,
Date.new(2019, 10, 2) => 21.0,
Date.new(2019, 10, 3) => 21.0
})
end
it 'returns correct value for daily and weekly' do
start_date = Date.new(2019, 10, 1)
end_date = Date.new(2019, 10, 3)
time_period_costs = [
{
time_period: :daily,
cost: 10.0
},
{
time_period: :weekly,
cost: 70.0
}
]
expect(daily_cost(start_date, end_date, time_period_costs))
.to eq({
Date.new(2019, 10, 1) => 20.0,
Date.new(2019, 10, 2) => 20.0,
Date.new(2019, 10, 3) => 20.0
})
end
end
context 'when single time period passed in' do
it 'works with daily time period' do
start_date = Date.new(2019, 10, 1)
end_date = Date.new(2019, 10, 3)
time_period_costs = [
{
time_period: :daily,
cost: 10.0
}
]
expect(daily_cost(start_date, end_date, time_period_costs))
.to eq({
Date.new(2019, 10, 1) => 10.0,
Date.new(2019, 10, 2) => 10.0,
Date.new(2019, 10, 3) => 10.0
})
end
it 'works with weekly time period' do
start_date = Date.new(2019, 10, 1)
end_date = Date.new(2019, 10, 3)
time_period_costs = [
{
time_period: :weekly,
cost: 70.0
}
]
expect(daily_cost(start_date, end_date, time_period_costs))
.to eq({
Date.new(2019, 10, 1) => 10.0,
Date.new(2019, 10, 2) => 10.0,
Date.new(2019, 10, 3) => 10.0
})
end
it 'works with monthly time period' do
start_date = Date.new(2019, 10, 1)
end_date = Date.new(2019, 10, 3)
time_period_costs = [
{
time_period: :monthly,
cost: 31.0
}
]
expect(daily_cost(start_date, end_date, time_period_costs))
.to eq({
Date.new(2019, 10, 1) => 1.0,
Date.new(2019, 10, 2) => 1.0,
Date.new(2019, 10, 3) => 1.0
})
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment