Current section
Files
Jump to
Current section
Files
lib/postal_code.ex
defmodule PostalCode do
@moduledoc """
Postal code parser for the Norwegian postal code system.
"""
alias CSV
@doc """
Accepts a postal code in string format, and returns the postal place.
## Examples
iex> PostalCode.postal_code_to_place("0186")
{:ok, "OSLO"}
iex> PostalCode.postal_code_to_place("0638")
:no_results
iex> PostalCode.postal_code_to_place(0186)
{:error, "Invalid type of postal code, must be string."}
iex> PostalCode.postal_code_to_place("018")
{:error, "Length must be 4."}
"""
def postal_code_to_place(postal_code)
when is_binary(postal_code) and bit_size(postal_code) == 32 do
case get_matching_postal_code(postal_code, :erik) do
[_, place, _, _, _, _, _, _, _, _, _, _, _, _] ->
{:ok, place |> String.split(" (") |> List.first()}
_ ->
:no_results
end
end
def postal_code_to_place(postal_code) when is_binary(postal_code),
do: {:error, "Length must be 4."}
def postal_code_to_place(_postal_code),
do: {:error, "Invalid type of postal code, must be string."}
def postal_code_to_location(postal_code)
when is_binary(postal_code) and bit_size(postal_code) == 32 do
case get_matching_postal_code(postal_code, :erik) do
[_, _, _, _, _, _, _, _, _, latitude, longitude, _, _, _] ->
{latitude, longitude}
_ ->
:no_results
end
end
def postal_code_to_location(postal_code) when is_binary(postal_code),
do: {:error, "Length must be 4."}
def postal_code_to_location(_postal_code),
do: {:error, "Invalid type of postal code, must be string"}
@doc false
defp get_erik_file do
Path.join(File.cwd!(), "postnummer.csv")
|> File.stream!([:encoding, :utf8])
|> CSV.decode(encoding: :utf8)
|> Enum.map(fn x ->
case x do
{:ok, list} ->
Enum.at(
Enum.map(list, fn y -> y |> String.replace("\r", "") |> String.split("\t") end),
0
)
end
end)
end
defp get_matching_postal_code(postal_code, :erik) do
Enum.find(get_erik_file(), fn x -> Enum.at(x, 0) == postal_code end)
end
end