Skip to content

Commit cc1dbb3

Browse files
committed
fix: Parametrize iana database download_url
1 parent 830f445 commit cc1dbb3

27 files changed

+614
-293
lines changed

.formatter.exs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Used by "mix format"
22
[
3-
inputs: ["lib/tzdata/period_builder.ex", "test/tz_period_builder_test.exs"]
3+
import_deps: [:hackney],
4+
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}"]
45
]

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ erl_crash.dump
44
*.ez
55
/doc
66
/priv/latest_remote_poll.txt
7+
/priv/tmp_downloads

VERSION

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1.2.0

config/config.exs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# This file is responsible for configuring your application
22
# and its dependencies with the aid of the Mix.Config module.
3-
use Mix.Config
3+
import Config
44

55
config :logger, utc_log: true
66
config :tzdata, :autoupdate, :enabled
7+
8+
config :tzdata, download_url: "https://data.iana.org/time-zones/tzdata-latest.tar.gz"
79
# config :tzdata, :data_dir, "/etc/elixir_tzdata_storage"

lib/tzdata.ex

+62-41
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,21 @@ defmodule Tzdata do
3131
zone_list provides a list of all the zone names that can be used with
3232
DateTime. This includes aliases.
3333
"""
34-
@spec zone_list() :: [Calendar.time_zone]
35-
def zone_list, do: Tzdata.ReleaseReader.zone_and_link_list
34+
@spec zone_list() :: [Calendar.time_zone()]
35+
def zone_list, do: Tzdata.ReleaseReader.zone_and_link_list()
3636

3737
@doc """
3838
Like zone_list, but excludes aliases for zones.
3939
"""
40-
@spec canonical_zone_list() :: [Calendar.time_zone]
41-
def canonical_zone_list, do: Tzdata.ReleaseReader.zone_list
40+
@spec canonical_zone_list() :: [Calendar.time_zone()]
41+
def canonical_zone_list, do: Tzdata.ReleaseReader.zone_list()
4242

4343
@doc """
4444
A list of aliases for zone names. For instance Europe/Jersey
4545
is an alias for Europe/London. Aliases are also known as linked zones.
4646
"""
47-
@spec zone_alias_list() :: [Calendar.time_zone]
48-
def zone_alias_list, do: Tzdata.ReleaseReader.link_list
47+
@spec zone_alias_list() :: [Calendar.time_zone()]
48+
def zone_alias_list, do: Tzdata.ReleaseReader.link_list()
4949

5050
@doc """
5151
Takes the name of a zone. Returns true if zone exists. Otherwise false.
@@ -57,7 +57,7 @@ defmodule Tzdata do
5757
iex> Tzdata.zone_exists? "Europe/Jersey"
5858
true
5959
"""
60-
@spec zone_exists?(String.t) :: boolean()
60+
@spec zone_exists?(String.t()) :: boolean()
6161
def zone_exists?(name), do: Enum.member?(zone_list(), name)
6262

6363
@doc """
@@ -69,7 +69,7 @@ defmodule Tzdata do
6969
iex> Tzdata.canonical_zone? "Europe/Jersey"
7070
false
7171
"""
72-
@spec canonical_zone?(Calendar.time_zone) :: boolean()
72+
@spec canonical_zone?(Calendar.time_zone()) :: boolean()
7373
def canonical_zone?(name), do: Enum.member?(canonical_zone_list(), name)
7474

7575
@doc """
@@ -81,7 +81,7 @@ defmodule Tzdata do
8181
iex> Tzdata.zone_alias? "Europe/London"
8282
false
8383
"""
84-
@spec zone_alias?(Calendar.time_zone) :: boolean()
84+
@spec zone_alias?(Calendar.time_zone()) :: boolean()
8585
def zone_alias?(name), do: Enum.member?(zone_alias_list(), name)
8686

8787
@doc """
@@ -90,16 +90,16 @@ defmodule Tzdata do
9090
iex> Tzdata.links["Europe/Jersey"]
9191
"Europe/London"
9292
"""
93-
@spec links() :: %{Calendar.time_zone => Calendar.time_zone}
94-
def links, do: Tzdata.ReleaseReader.links
93+
@spec links() :: %{Calendar.time_zone() => Calendar.time_zone()}
94+
def links, do: Tzdata.ReleaseReader.links()
9595

9696
@doc """
9797
Returns a map with keys being group names and the values lists of
9898
time zone names. The group names mirror the file names used by the tzinfo
9999
database.
100100
"""
101-
@spec zone_lists_grouped() :: %{atom() => [Calendar.time_zone]}
102-
def zone_lists_grouped, do: Tzdata.ReleaseReader.by_group
101+
@spec zone_lists_grouped() :: %{atom() => [Calendar.time_zone()]}
102+
def zone_lists_grouped, do: Tzdata.ReleaseReader.by_group()
103103

104104
@doc """
105105
Returns tzdata release version as a string.
@@ -109,8 +109,8 @@ defmodule Tzdata do
109109
Tzdata.tzdata_version
110110
"2014i"
111111
"""
112-
@spec tzdata_version() :: String.t
113-
def tzdata_version, do: Tzdata.ReleaseReader.release_version
112+
@spec tzdata_version() :: String.t()
113+
def tzdata_version, do: Tzdata.ReleaseReader.release_version()
114114

115115
@doc """
116116
Returns a list of periods for the `zone_name` provided as an argument.
@@ -138,12 +138,14 @@ defmodule Tzdata do
138138
iex> Tzdata.periods("Not existing")
139139
{:error, :not_found}
140140
"""
141-
@spec periods(Calendar.time_zone) :: {:ok, [time_zone_period]} | {:error, atom()}
141+
@spec periods(Calendar.time_zone()) :: {:ok, [time_zone_period]} | {:error, atom()}
142142
def periods(zone_name) do
143143
{tag, p} = Tzdata.ReleaseReader.periods_for_zone_or_link(zone_name)
144+
144145
case tag do
145146
:ok ->
146-
mapped_p = for {_, f_utc, f_wall, f_std, u_utc, u_wall, u_std, utc_off, std_off, zone_abbr} <- p do
147+
mapped_p =
148+
for {_, f_utc, f_wall, f_std, u_utc, u_wall, u_std, utc_off, std_off, zone_abbr} <- p do
147149
%{
148150
std_off: std_off,
149151
utc_off: utc_off,
@@ -152,8 +154,11 @@ defmodule Tzdata do
152154
zone_abbr: zone_abbr
153155
}
154156
end
157+
155158
{:ok, mapped_p}
156-
_ -> {:error, p}
159+
160+
_ ->
161+
{:error, p}
157162
end
158163
end
159164

@@ -191,15 +196,18 @@ defmodule Tzdata do
191196
iex> Tzdata.periods_for_time("Europe/Copenhagen", 63594816000, :wall)
192197
[]
193198
"""
194-
@spec periods_for_time(Calendar.time_zone, gregorian_seconds, :standard | :wall | :utc) :: [time_zone_period] | {:error, term}
199+
@spec periods_for_time(Calendar.time_zone(), gregorian_seconds, :standard | :wall | :utc) ::
200+
[time_zone_period] | {:error, term}
195201
def periods_for_time(zone_name, time_point, time_type) do
196202
case possible_periods_for_zone_and_time(zone_name, time_point, time_type) do
197203
{:ok, periods} ->
198204
match_fn = fn %{from: from, until: until} ->
199205
smaller_than_or_equals(Map.get(from, time_type), time_point) &&
200206
bigger_than(Map.get(until, time_type), time_point)
201207
end
208+
202209
do_consecutive_matching(periods, match_fn, [], false)
210+
203211
{:error, _} = error ->
204212
error
205213
end
@@ -210,49 +218,62 @@ defmodule Tzdata do
210218
# remaining list.
211219
defp do_consecutive_matching([], _fun, [], _did_last_match), do: []
212220
defp do_consecutive_matching([], _fun, matched, _did_last_match), do: matched
221+
213222
defp do_consecutive_matching(_list, _fun, matched, false) when matched != [] do
214223
# If there are matches and previous did not match then the matches are no
215224
# long consecutive. So we return the result.
216-
matched |> Enum.reverse
225+
matched |> Enum.reverse()
217226
end
218-
defp do_consecutive_matching([h|t], fun, matched, _did_last_match) do
227+
228+
defp do_consecutive_matching([h | t], fun, matched, _did_last_match) do
219229
if fun.(h) == true do
220-
do_consecutive_matching(t, fun, [h|matched], true)
230+
do_consecutive_matching(t, fun, [h | matched], true)
221231
else
222232
do_consecutive_matching(t, fun, matched, false)
223233
end
224234
end
225235

226236
# Use dynamic periods for points in time that are about 40 years into the future
227237
@years_in_the_future_where_precompiled_periods_are_used 40
228-
@point_from_which_to_use_dynamic_periods :calendar.datetime_to_gregorian_seconds {{(:calendar.universal_time|>elem(0)|>elem(0)) + @years_in_the_future_where_precompiled_periods_are_used, 1, 1}, {0, 0, 0}}
229-
defp possible_periods_for_zone_and_time(zone_name, time_point, time_type) when time_point >= @point_from_which_to_use_dynamic_periods do
238+
@point_from_which_to_use_dynamic_periods :calendar.datetime_to_gregorian_seconds(
239+
{{(:calendar.universal_time() |> elem(0) |> elem(0)) +
240+
@years_in_the_future_where_precompiled_periods_are_used,
241+
1, 1}, {0, 0, 0}}
242+
)
243+
defp possible_periods_for_zone_and_time(zone_name, time_point, time_type)
244+
when time_point >= @point_from_which_to_use_dynamic_periods do
230245
if Tzdata.FarFutureDynamicPeriods.zone_in_30_years_in_eternal_period?(zone_name) do
231246
periods(zone_name)
232247
else
233-
link_status = Tzdata.ReleaseReader.links |> Map.get(zone_name)
248+
link_status = Tzdata.ReleaseReader.links() |> Map.get(zone_name)
249+
234250
if link_status == nil do
235251
Tzdata.FarFutureDynamicPeriods.periods_for_point_in_time(time_point, zone_name)
236252
else
237253
possible_periods_for_zone_and_time(link_status, time_point, time_type)
238254
end
239255
end
240256
end
257+
241258
defp possible_periods_for_zone_and_time(zone_name, time_point, time_type) do
242-
{:ok, periods} = Tzdata.ReleaseReader.periods_for_zone_time_and_type(zone_name, time_point, time_type)
243-
mapped_periods = periods
244-
|> Enum.sort_by(fn {_, from_utc, _, _, _, _, _, _, _, _} -> -(from_utc |> Tzdata.ReleaseReader.delimiter_to_number) end)
245-
|> Enum.map(
246-
fn {_, f_utc, f_wall, f_std, u_utc, u_wall, u_std, utc_off, std_off, zone_abbr} ->
247-
%{
248-
std_off: std_off,
249-
utc_off: utc_off,
250-
from: %{utc: f_utc, wall: f_wall, standard: f_std},
251-
until: %{utc: u_utc, standard: u_std, wall: u_wall},
252-
zone_abbr: zone_abbr
253-
}
254-
end
255-
)
259+
{:ok, periods} =
260+
Tzdata.ReleaseReader.periods_for_zone_time_and_type(zone_name, time_point, time_type)
261+
262+
mapped_periods =
263+
periods
264+
|> Enum.sort_by(fn {_, from_utc, _, _, _, _, _, _, _, _} ->
265+
-(from_utc |> Tzdata.ReleaseReader.delimiter_to_number())
266+
end)
267+
|> Enum.map(fn {_, f_utc, f_wall, f_std, u_utc, u_wall, u_std, utc_off, std_off, zone_abbr} ->
268+
%{
269+
std_off: std_off,
270+
utc_off: utc_off,
271+
from: %{utc: f_utc, wall: f_wall, standard: f_std},
272+
until: %{utc: u_utc, standard: u_std, wall: u_wall},
273+
zone_abbr: zone_abbr
274+
}
275+
end)
276+
256277
{:ok, mapped_periods}
257278
end
258279

@@ -270,7 +291,7 @@ defmodule Tzdata do
270291
"""
271292
@spec leap_seconds_with_tai_diff() :: [%{date_time: :calendar.datetime(), tai_diff: integer}]
272293
def leap_seconds_with_tai_diff do
273-
leap_seconds_data = Tzdata.ReleaseReader.leap_sec_data
294+
leap_seconds_data = Tzdata.ReleaseReader.leap_sec_data()
274295
leap_seconds_data.leap_seconds
275296
end
276297

@@ -305,7 +326,7 @@ defmodule Tzdata do
305326
"""
306327
@spec leap_second_data_valid_until() :: :calendar.datetime()
307328
def leap_second_data_valid_until do
308-
leap_seconds_data = Tzdata.ReleaseReader.leap_sec_data
329+
leap_seconds_data = Tzdata.ReleaseReader.leap_sec_data()
309330
leap_seconds_data.valid_until
310331
end
311332

lib/tzdata/basic_data_map.ex

+21-14
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ defmodule Tzdata.BasicDataMap do
33

44
alias Tzdata.Parser
55
alias Tzdata.ParserOrganizer, as: Organizer
6+
67
@file_names ~w(africa antarctica asia australasia backward etcetera europe northamerica southamerica)s
78
def from_files_in_dir(dir_name) do
8-
Enum.map(@file_names, fn file_name -> {String.to_atom(file_name), Parser.read_file(file_name, dir_name)} end)
9+
Enum.map(@file_names, fn file_name ->
10+
{String.to_atom(file_name), Parser.read_file(file_name, dir_name)}
11+
end)
912
|> make_map
1013
end
1114

@@ -15,26 +18,30 @@ defmodule Tzdata.BasicDataMap do
1518
end
1619

1720
def make_map(all_files_read) do
18-
all_files_flattened = all_files_read |> Enum.map(fn {_name, read_file} -> read_file end) |> List.flatten
21+
all_files_flattened =
22+
all_files_read |> Enum.map(fn {_name, read_file} -> read_file end) |> List.flatten()
23+
1924
rules = Organizer.rules(all_files_flattened)
2025
zones = Organizer.zones(all_files_flattened)
2126
links = Organizer.links(all_files_flattened)
2227
zone_list = Organizer.zone_list(all_files_flattened)
2328
link_list = Organizer.link_list(all_files_flattened)
2429
zone_and_link_list = Organizer.zone_and_link_list(all_files_flattened)
2530

26-
by_group = all_files_read
27-
|> Enum.map(fn {name, file_read} -> {name, Organizer.zone_and_link_list(file_read)} end)
28-
|> Enum.into(Map.new)
31+
by_group =
32+
all_files_read
33+
|> Enum.map(fn {name, file_read} -> {name, Organizer.zone_and_link_list(file_read)} end)
34+
|> Enum.into(Map.new())
35+
2936
{:ok,
30-
%{rules: rules,
31-
zones: zones,
32-
links: links,
33-
zone_list: zone_list,
34-
link_list: link_list,
35-
zone_and_link_list: zone_and_link_list,
36-
by_group: by_group,
37-
}
38-
}
37+
%{
38+
rules: rules,
39+
zones: zones,
40+
links: links,
41+
zone_list: zone_list,
42+
link_list: link_list,
43+
zone_and_link_list: zone_and_link_list,
44+
by_group: by_group
45+
}}
3946
end
4047
end

lib/tzdata/data_builder.ex

+8-9
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ defmodule Tzdata.DataBuilder do
1616
File.rm_rf(tzdata_dir)
1717

1818
Logger.info(
19-
"Downloaded tzdata release from IANA is the same version as the version currently in use (#{
20-
current_version
21-
})."
19+
"Downloaded tzdata release from IANA is the same version as the version currently in use (#{current_version})."
2220
)
2321

2422
{:error, :downloaded_version_same_as_current_version}
@@ -45,8 +43,8 @@ defmodule Tzdata.DataBuilder do
4543

4644
map.zone_list
4745
|> Enum.each(fn zone_name ->
48-
insert_periods_for_zone(table, map, zone_name)
49-
end)
46+
insert_periods_for_zone(table, map, zone_name)
47+
end)
5048

5149
# remove temporary tzdata dir
5250
File.rm_rf(tzdata_dir)
@@ -65,7 +63,7 @@ defmodule Tzdata.DataBuilder do
6563
defp leap_sec_data(tzdata_dir), do: LeapSecParser.read_file(tzdata_dir)
6664

6765
def ets_file_name_for_release_version(release_version) do
68-
"#{release_dir()}/#{release_version}.v#{Tzdata.EtsHolder.file_version}.ets"
66+
"#{release_dir()}/#{release_version}.v#{Tzdata.EtsHolder.file_version()}.ets"
6967
end
7068

7169
def ets_table_name_for_release_version(release_version) do
@@ -79,10 +77,11 @@ defmodule Tzdata.DataBuilder do
7977
tuple_periods =
8078
periods
8179
|> Enum.map(fn period ->
82-
period_to_tuple(key, period)
83-
end)
80+
period_to_tuple(key, period)
81+
end)
8482

85-
tuple_periods |> Enum.each(fn tuple_period ->
83+
tuple_periods
84+
|> Enum.each(fn tuple_period ->
8685
:ets.insert(table, tuple_period)
8786
end)
8887
end

0 commit comments

Comments
 (0)