Current section
Files
Jump to
Current section
Files
lib/periods/conversion.ex
defmodule Periods.Conversion do
@moduledoc false
alias Periods.Parser
alias Periods.Period
@units Periods.all_units()
defmodule ConversionError do
use Periods.Errors
def exception({:cannot_convert_to_month, unit}) do
%ConversionError{message: "cannot convert #{unit} to month"}
end
end
def convert!(period, unit) do
case convert(period, unit) do
%Period{} = converted_period -> converted_period
{:error, message} -> raise ConversionError.exception(message)
end
end
def convert(%Period{unit: unit} = period, unit) when unit in @units, do: period
def convert(%Period{unit: :millisecond} = period, :second) do
new_amount = div(period.amount, 1000)
%Period{amount: new_amount, unit: :second}
end
def convert(%Period{unit: :millisecond} = period, :minute) do
new_amount = div(period.amount, 60_000)
%Period{amount: new_amount, unit: :minute}
end
def convert(%Period{unit: :millisecond} = period, :hour) do
new_amount = div(period.amount, 3_600_000)
%Period{amount: new_amount, unit: :hour}
end
def convert(%Period{unit: :millisecond} = period, :day) do
new_amount = div(period.amount, 86_400_000)
%Period{amount: new_amount, unit: :day}
end
def convert(%Period{unit: :millisecond} = period, :week) do
new_amount = div(period.amount, 604_800_000)
%Period{amount: new_amount, unit: :week}
end
def convert(%Period{unit: :millisecond} = period, :year) do
new_amount = div(period.amount, 31_536_000_000)
%Period{amount: new_amount, unit: :year}
end
def convert(%Period{unit: :millisecond} = period, :decade) do
new_amount = div(period.amount, 315_360_000_000)
%Period{amount: new_amount, unit: :decade}
end
def convert(%Period{unit: :second} = period, :millisecond) do
new_amount = period.amount * 1000
%Period{amount: new_amount, unit: :millisecond}
end
def convert(%Period{unit: :second} = period, :minute) do
new_amount = div(period.amount, 60)
%Period{amount: new_amount, unit: :minute}
end
def convert(%Period{unit: :second} = period, :hour) do
new_amount = div(period.amount, 3_600)
%Period{amount: new_amount, unit: :hour}
end
def convert(%Period{unit: :second} = period, :day) do
new_amount = div(period.amount, 86_400)
%Period{amount: new_amount, unit: :day}
end
def convert(%Period{unit: :second} = period, :week) do
new_amount = div(period.amount, 604_800)
%Period{amount: new_amount, unit: :week}
end
def convert(%Period{unit: :second} = period, :year) do
new_amount = div(period.amount, 31_536_000)
%Period{amount: new_amount, unit: :year}
end
def convert(%Period{unit: :second} = period, :decade) do
new_amount = div(period.amount, 315_360_000)
%Period{amount: new_amount, unit: :decade}
end
def convert(%Period{unit: :minute} = period, :millisecond) do
new_amount = period.amount * 60_000
%Period{amount: new_amount, unit: :millisecond}
end
def convert(%Period{unit: :minute} = period, :second) do
new_amount = period.amount * 60
%Period{amount: new_amount, unit: :second}
end
def convert(%Period{unit: :minute} = period, :hour) do
new_amount = div(period.amount, 60)
%Period{amount: new_amount, unit: :hour}
end
def convert(%Period{unit: :minute} = period, :day) do
new_amount = div(period.amount, 1_440)
%Period{amount: new_amount, unit: :day}
end
def convert(%Period{unit: :minute} = period, :week) do
new_amount = div(period.amount, 10_080)
%Period{amount: new_amount, unit: :week}
end
def convert(%Period{unit: :minute} = period, :year) do
new_amount = div(period.amount, 525_600)
%Period{amount: new_amount, unit: :year}
end
def convert(%Period{unit: :minute} = period, :decade) do
new_amount = div(period.amount, 5_256_000)
%Period{amount: new_amount, unit: :decade}
end
def convert(%Period{unit: :hour} = period, :millisecond) do
new_amount = period.amount * 3_600_000
%Period{amount: new_amount, unit: :millisecond}
end
def convert(%Period{unit: :hour} = period, :second) do
new_amount = period.amount * 3_600
%Period{amount: new_amount, unit: :second}
end
def convert(%Period{unit: :hour} = period, :minute) do
new_amount = period.amount * 60
%Period{amount: new_amount, unit: :minute}
end
def convert(%Period{unit: :hour} = period, :day) do
new_amount = div(period.amount, 24)
%Period{amount: new_amount, unit: :day}
end
def convert(%Period{unit: :hour} = period, :week) do
new_amount = div(period.amount, 168)
%Period{amount: new_amount, unit: :week}
end
def convert(%Period{unit: :hour} = period, :year) do
new_amount = div(period.amount, 8_760)
%Period{amount: new_amount, unit: :year}
end
def convert(%Period{unit: :hour} = period, :decade) do
new_amount = div(period.amount, 87_600)
%Period{amount: new_amount, unit: :decade}
end
def convert(%Period{unit: :day} = period, :millisecond) do
new_amount = period.amount * 86_400_000
%Period{amount: new_amount, unit: :millisecond}
end
def convert(%Period{unit: :day} = period, :second) do
new_amount = period.amount * 86_400
%Period{amount: new_amount, unit: :second}
end
def convert(%Period{unit: :day} = period, :minute) do
new_amount = period.amount * 1_440
%Period{amount: new_amount, unit: :minute}
end
def convert(%Period{unit: :day} = period, :hour) do
new_amount = period.amount * 24
%Period{amount: new_amount, unit: :hour}
end
def convert(%Period{unit: :day} = period, :week) do
new_amount = div(period.amount, 7)
%Period{amount: new_amount, unit: :week}
end
def convert(%Period{unit: :day} = period, :year) do
new_amount = div(period.amount, 365)
%Period{amount: new_amount, unit: :year}
end
def convert(%Period{unit: :day} = period, :decade) do
new_amount = div(period.amount, 3_650)
%Period{amount: new_amount, unit: :decade}
end
def convert(%Period{unit: :week} = period, :millisecond) do
new_amount = period.amount * 604_800_000
%Period{amount: new_amount, unit: :millisecond}
end
def convert(%Period{unit: :week} = period, :second) do
new_amount = period.amount * 604_800
%Period{amount: new_amount, unit: :second}
end
def convert(%Period{unit: :week} = period, :minute) do
new_amount = period.amount * 10_080
%Period{amount: new_amount, unit: :minute}
end
def convert(%Period{unit: :week} = period, :hour) do
new_amount = period.amount * 168
%Period{amount: new_amount, unit: :hour}
end
def convert(%Period{unit: :week} = period, :day) do
new_amount = period.amount * 7
%Period{amount: new_amount, unit: :day}
end
def convert(%Period{unit: :week} = period, :year) do
new_amount = div(period.amount, 52)
%Period{amount: new_amount, unit: :year}
end
def convert(%Period{unit: :week} = period, :decade) do
new_amount = div(period.amount, 520)
%Period{amount: new_amount, unit: :decade}
end
def convert(%Period{unit: :month} = period, :year) do
new_amount = div(period.amount, 12)
%Period{amount: new_amount, unit: :year}
end
def convert(%Period{unit: :month} = period, :decade) do
new_amount = div(period.amount, 120)
%Period{amount: new_amount, unit: :decade}
end
def convert(%Period{unit: :year} = period, :millisecond) do
new_amount = period.amount * 31_536_000_000
%Period{amount: new_amount, unit: :millisecond}
end
def convert(%Period{unit: :year} = period, :second) do
new_amount = period.amount * 31_536_000
%Period{amount: new_amount, unit: :second}
end
def convert(%Period{unit: :year} = period, :minute) do
new_amount = period.amount * 525_600
%Period{amount: new_amount, unit: :minute}
end
def convert(%Period{unit: :year} = period, :hour) do
new_amount = period.amount * 8_760
%Period{amount: new_amount, unit: :hour}
end
def convert(%Period{unit: :year} = period, :day) do
new_amount = period.amount * 365
%Period{amount: new_amount, unit: :day}
end
def convert(%Period{unit: :year} = period, :week) do
new_amount = period.amount * 52
%Period{amount: new_amount, unit: :week}
end
def convert(%Period{unit: :year} = period, :month) do
new_amount = period.amount * 12
%Period{amount: new_amount, unit: :month}
end
def convert(%Period{unit: :year} = period, :decade) do
new_amount = div(period.amount, 10)
%Period{amount: new_amount, unit: :decade}
end
def convert(%Period{unit: :decade} = period, :millisecond) do
new_amount = period.amount * 315_360_000_000
%Period{amount: new_amount, unit: :millisecond}
end
def convert(%Period{unit: :decade} = period, :second) do
new_amount = period.amount * 315_360_000
%Period{amount: new_amount, unit: :second}
end
def convert(%Period{unit: :decade} = period, :minute) do
new_amount = period.amount * 5_256_000
%Period{amount: new_amount, unit: :minute}
end
def convert(%Period{unit: :decade} = period, :hour) do
new_amount = period.amount * 87_600
%Period{amount: new_amount, unit: :hour}
end
def convert(%Period{unit: :decade} = period, :day) do
new_amount = period.amount * 3650
%Period{amount: new_amount, unit: :day}
end
def convert(%Period{unit: :decade} = period, :week) do
new_amount = period.amount * 520
%Period{amount: new_amount, unit: :week}
end
def convert(%Period{unit: :decade} = period, :month) do
new_amount = period.amount * 120
%Period{amount: new_amount, unit: :month}
end
def convert(%Period{unit: :decade} = period, :year) do
new_amount = period.amount * 10
%Period{amount: new_amount, unit: :year}
end
def convert(%Period{unit: unit}, :month), do: {:error, {:cannot_convert_to_month, unit}}
def convert(%Period{} = period, unit) do
case Parser.parse_unit(unit) do
{:ok, parsed_unit} -> convert(period, parsed_unit)
{:error, message} -> {:error, message}
end
end
def convert(_period, _unit), do: {:error, :invalid_arguments}
@doc """
Returns the smaller of two units based on the Periods unit ordering.
## Examples
iex> Periods.Conversion.lowest_unit(:day, :second)
:second
iex> Periods.Conversion.lowest_unit(:year, :month)
:month
"""
def lowest_unit(unit_1, unit_2) do
index_units = Enum.with_index(Periods.all_units())
unit_1_index = Keyword.get(index_units, unit_1)
unit_2_index = Keyword.get(index_units, unit_2)
case unit_1_index < unit_2_index do
true -> unit_1
false -> unit_2
end
end
end