Packages
tz_extra
0.2.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.1
0.22.0
0.21.1
0.21.0
0.20.1
0.20.0
0.17.0
0.16.7
0.16.6
0.16.5
0.16.3
0.16.2
0.16.1
0.16.0
0.15.1
0.15.0
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Time zone-related utilities
Current section
Files
Jump to
Current section
Files
lib/file_parser/zone_parser.ex
defmodule TzExtra.FileParser.ZoneParser do
@moduledoc false
def parse(file_path, countries) do
File.stream!(file_path)
|> strip_comments()
|> strip_empty()
|> trim()
|> Enum.to_list()
|> parse_strings_into_maps()
|> add_country_names(countries)
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
maps =
Enum.zip([
[:country_codes, :coordinates, :name, :_],
String.split(string, ~r{\s}, trim: true, parts: 4)
|> Enum.map(& String.trim(&1))
])
|> Enum.into(%{})
|> Map.delete(:_)
|> denormalize_entry()
maps ++ parse_strings_into_maps(tail)
end
defp denormalize_entry(%{} = entry) do
country_codes = String.split(entry.country_codes, ",", trim: true)
for country_code <- country_codes do
%{
country_code: country_code,
coordinates: entry.coordinates,
name: entry.name,
short_name: String.split(entry.name, "/") |> List.last()
}
end
end
defp add_country_names(list, countries) do
Enum.map(list, fn map ->
{country_code, map} = pop_in(map, [:country_code])
country = Enum.find(countries, & &1.code == country_code)
Map.put(map, :country, country)
end)
end
end