lib/backend.ex

defmodule ICalendarTimezones.Backend do
  @moduledoc """
  Module that loads the timezone information
  """
  @zone_list_path "libical/zoneinfo/zones.tab"

  @doc """
  Loads and returns all of the timezone's data
  """
  @spec timezones_data :: map()
  def timezones_data do
    Enum.reduce(timezones_list(), %{}, fn tz_id, acc ->
      Map.put(acc, tz_id, vtimezone(tz_id))
    end)
  end

  @doc """
  Retuns the list of IANA timezones identifiers
  """
  @spec timezones_list :: list(String.t())
  def timezones_list do
    @zone_list_path
    |> File.stream!()
    |> Stream.map(&String.trim/1)
    |> Stream.map(&String.split/1)
    |> Stream.map(&List.last/1)
    |> Enum.to_list()
  end

  @doc """
  Returns the VCALENDAR vobject data for a TZID.
  """
  @spec vtimezone(String.t()) :: String.t()
  def vtimezone(tz_id) when is_binary(tz_id) do
    tz_id
    |> path()
    |> read_file()
  end

  @spec path(String.t()) :: String.t()
  defp path(tz_id) when is_binary(tz_id) do
    Path.join("libical/zoneinfo", tz_id <> ".ics")
  end

  @spec read_file(String.t()) :: String.t()
  defp read_file(path) when is_binary(path) do
    File.read!(path)
  end
end