Packages
tz_extra
0.15.1
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/compiler.ex
defmodule TzExtra.Compiler do
@moduledoc false
require TzExtra.IanaFileParser
import TzExtra.Helper
alias TzExtra.IanaFileParser
def compile() do
countries = IanaFileParser.countries()
time_zones = IanaFileParser.time_zones()
get_time_zone_links_for_canonical_fun = fn canonical -> time_zones[canonical] end
countries_time_zones =
IanaFileParser.time_zones_with_country(countries)
|> add_time_zone_links(get_time_zone_links_for_canonical_fun)
|> List.insert_at(0, %{coordinates: nil, country: nil, time_zone: "UTC", time_zone_links: []})
|> add_offset_data()
|> Enum.sort_by(&{&1.country && normalize_string(&1.country.name), &1.utc_offset, &1.time_zone})
countries_time_zones_without_utc = Enum.filter(countries_time_zones, & &1.time_zone != "UTC")
canonical_time_zones =
time_zones
|> Map.keys()
|> Enum.uniq()
|> Enum.sort()
all_time_zones =
time_zones
|> Enum.map(fn {canonical, links} -> [canonical | links] end)
|> List.flatten()
|> Enum.uniq()
|> Enum.sort()
civil_time_zones =
countries_time_zones_without_utc
|> Enum.map(&(&1.time_zone))
|> Enum.uniq()
|> Enum.sort()
civil_time_zones_with_links =
countries_time_zones_without_utc
|> Enum.map(&([&1.time_zone | &1.time_zone_links]))
|> List.flatten()
|> Enum.uniq()
|> Enum.sort()
contents = [
quote do
def version() do
unquote(Tz.version())
end
def time_zone_identifiers(opts \\ []) do
exclude_non_civil = Keyword.get(opts, :exclude_non_civil, true)
exclude_alias = Keyword.get(opts, :exclude_alias, true)
cond do
exclude_non_civil ->
cond do
exclude_alias ->
unquote(Macro.escape(civil_time_zones))
true ->
unquote(Macro.escape(civil_time_zones_with_links))
end
true ->
cond do
exclude_alias ->
unquote(Macro.escape(canonical_time_zones))
true ->
unquote(Macro.escape(all_time_zones))
end
end
end
def countries_time_zones(with_utc: true) do
unquote(Macro.escape(countries_time_zones))
end
def countries_time_zones([]) do
unquote(Macro.escape(countries_time_zones_without_utc))
end
def countries_time_zones() do
unquote(Macro.escape(countries_time_zones_without_utc))
end
def countries() do
unquote(Macro.escape(countries))
end
end
]
module = :"Elixir.TzExtra"
Module.create(module, contents, Macro.Env.location(__ENV__))
:code.purge(module)
end
defp add_offset_data(time_zones) do
Enum.map(time_zones, fn time_zone ->
{:ok, periods} = Tz.PeriodsProvider.periods(time_zone.time_zone)
{utc_offset, dst_offset, zone_abbr, dst_zone_abbr} =
case hd(periods) do
{_, {utc_offset, std_offset, zone_abbr}, _, nil} ->
{utc_offset, utc_offset + std_offset, zone_abbr, zone_abbr}
{_, {utc_offset, std_offset, zone_abbr}, {_, prev_std_offset, prev_zone_abbr}, _} ->
dst_offset = utc_offset + max(std_offset, prev_std_offset)
{zone_abbr, dst_zone_abbr} =
cond do
std_offset < prev_std_offset ->
{zone_abbr, prev_zone_abbr}
std_offset > prev_std_offset ->
{prev_zone_abbr, zone_abbr}
end
{utc_offset, dst_offset, zone_abbr, dst_zone_abbr}
end
time_zone
|> Map.put(:utc_offset, utc_offset)
|> Map.put(:dst_offset, dst_offset)
|> Map.put(:pretty_utc_offset, offset_to_string(utc_offset))
|> Map.put(:pretty_dst_offset, offset_to_string(dst_offset))
|> Map.put(:zone_abbr, zone_abbr)
|> Map.put(:dst_zone_abbr, dst_zone_abbr)
end)
end
defp add_time_zone_links(countries_time_zones, get_time_zone_links_for_canonical_fun) do
Enum.map(countries_time_zones, fn %{time_zone: time_zone_name} = time_zone ->
Map.put(time_zone, :time_zone_links, get_time_zone_links_for_canonical_fun.(time_zone_name))
end)
end
end