Current section

Files

Jump to
tz_extra lib file_parser zone_rule_parser.ex
Raw

lib/file_parser/zone_rule_parser.ex

defmodule TzExtra.FileParser.ZoneRuleParser do
@moduledoc false
def parse(file_path) do
File.stream!(file_path)
|> strip_comments()
|> strip_empty()
|> trim()
|> Enum.to_list()
|> parse_strings_into_maps()
end
defp strip_comments(stream) do
stream
|> Stream.filter(&(!Regex.match?(~r/^[\s]*#/, &1)))
|> Stream.map(&Regex.replace(~r/[\s]*#.+/, &1, ""))
end
defp strip_empty(stream) do
Stream.filter(stream, &(!Regex.match?(~r/^[\s]*\n$/, &1)))
end
defp trim(stream) do
Stream.map(stream, &String.trim(&1))
end
defp parse_strings_into_maps([]), do: []
defp parse_strings_into_maps([string | tail]) do
map =
cond do
String.starts_with?(string, "Link") ->
parse_link_string_into_map(string)
String.starts_with?(string, "Zone") ->
parse_zone_string_into_map(string)
true ->
nil
end
if(map == nil, do: [], else: [map]) ++ parse_strings_into_maps(tail)
end
defp parse_link_string_into_map(link_string) do
Enum.zip([
[:canonical_zone_name, :link_zone_name],
tl(String.split(link_string, ~r{\s}, trim: true, parts: 3))
|> Enum.map(& String.trim(&1))
])
|> Enum.into(%{})
|> Map.put(:record_type, :link)
end
defp parse_zone_string_into_map(zone_string) do
Enum.zip([
[:name, :std_offset_from_utc_time, :rules, :format_time_zone_abbr, :to],
tl(String.split(zone_string, ~r{\s}, trim: true, parts: 6))
|> Enum.map(& String.trim(&1))
])
|> Enum.into(%{})
|> Map.take([:name])
|> Map.put(:record_type, :zone)
end
end