defmodule LibraryFees do def datetime_from_string(string) do {:ok, dt} = NaiveDateTime.from_iso8601(string) dt end def before_noon?(datetime) do datetime.hour < 12 end def return_date(checkout_datetime) do dt = NaiveDateTime.to_date(checkout_datetime) case before_noon?(checkout_datetime) do true -> Date.add(dt, 28) _ -> Date.add(dt, 29) end end def days_late(planned_return_date, actual_return_datetime) do actual_return_datetime |> Date.diff(planned_return_date) |> max(0) end def monday?(datetime) do Date.day_of_week(NaiveDateTime.to_date(datetime)) == 1 end def calculate_late_fee(checkout, return, rate) do checkout_datetime = datetime_from_string(checkout) return_datetime = datetime_from_string(return) raw_fee = days_late(return_date(checkout_datetime), return_datetime) * rate if monday?(return_datetime) do floor(raw_fee * 0.5) else raw_fee end end end