Packages
tz
0.7.1
0.28.2
0.28.1
0.28.0
0.27.3
0.27.2
0.27.1
0.27.0
0.26.6
0.26.5
0.26.4
0.26.3
0.26.2
0.26.1
0.26.0
0.25.1
0.25.0
0.24.0
0.23.0
0.22.0
0.21.1
0.21.0
0.20.1
0.20.0
0.19.0
0.17.0
0.16.2
0.16.1
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.2
0.8.1
0.8.0
0.7.3
0.7.2
0.7.1
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Time zone support for Elixir
Current section
Files
Jump to
Current section
Files
lib/update_periodically.ex
if Code.ensure_loaded?(Mint.HTTP) do
defmodule Tz.UpdatePeriodically do
use GenServer
require Logger
alias Tz.Compiler
alias Tz.PeriodsProvider
alias Tz.HTTP.HTTPClient
alias Tz.HTTP.HTTPResponse
def start_link(_) do
GenServer.start_link(__MODULE__, %{})
end
def init(state) do
schedule_work()
{:ok, state}
end
def handle_info(:work, state) do
Logger.debug("Tz is checking for IANA time zone database updates")
if maybe_update_tz_database() == :updated do
Logger.info("Tz is recompiling time zone periods...")
Code.compiler_options(ignore_module_conflict: true)
Compiler.compile()
Code.compiler_options(ignore_module_conflict: false)
Logger.info("Tz compilation done")
end
schedule_work()
{:noreply, state}
end
defp schedule_work() do
Process.send_after(self(), :work, 24 * 60 * 60 * 1000) # In 24 hours
end
defp maybe_update_tz_database() do
case fetch_iana_tz_version() do
{:ok, latest_version} ->
if latest_version != PeriodsProvider.version() do
case update_tz_database(latest_version) do
:ok ->
delete_tz_database(PeriodsProvider.version())
:updated
_ -> :error
end
end
:error ->
Logger.error("Tz failed to read the latest version of the IANA time zone database")
:no_update
end
end
defp fetch_iana_tz_version() do
case HTTPClient.request("GET", "/time-zones/tzdb/version", hostname: "data.iana.org") do
%HTTPResponse{body: body, status_code: 200} ->
{:ok, body |> List.first() |> String.trim()}
_ ->
:error
end
end
defp update_tz_database(version) do
case download_tz_database(version) do
{:ok, content} ->
extract_tz_database(version, content)
:ok
:error ->
Logger.error("Tz failed to download the latest archived IANA time zone database (version #{version})")
:error
end
end
defp download_tz_database(version) do
Logger.info("Tz is downloading the latest IANA time zone database (version #{version})...")
case HTTPClient.request("GET", "/time-zones/releases/tzdata#{version}.tar.gz", hostname: "data.iana.org") do
%HTTPResponse{body: body, status_code: 200} ->
Logger.info("Tz download done")
{:ok, body}
_ ->
:error
end
end
defp extract_tz_database(version, content) do
tmp_archive_path = Path.join(:code.priv_dir(:tz), "tzdata#{version}.tar.gz")
tz_data_dir = "tzdata#{version}"
:ok = File.write!(tmp_archive_path, content)
:ok = :erl_tar.extract(tmp_archive_path, [:compressed, {:cwd, Path.join(:code.priv_dir(:tz), tz_data_dir)}])
:ok = File.rm!(tmp_archive_path)
end
defp delete_tz_database(version) do
Path.join(:code.priv_dir(:tz), "tzdata#{version}")
|> File.rm_rf!()
end
end
end