Skip to content

Commit 9363c12

Browse files
committed
Correct timezone generation
1 parent 5ccb26f commit 9363c12

File tree

3 files changed

+190
-191
lines changed

3 files changed

+190
-191
lines changed

lib/cldr/timezone.ex

Lines changed: 183 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -1,186 +1,183 @@
1-
defmodule Cldr.Timezone do
2-
@moduledoc """
3-
Functions to map between the CLDR short time zone code and the
4-
IANA timezone names.
5-
6-
The Unicode [locale](https://unicode.org/reports/tr35/#Locale)
7-
[extension U](https://unicode.org/reports/tr35/#u_Extension)
8-
allows the specification of the time zone requested for the provided locale.
9-
10-
This short timezone codes never change even if the IANA names change
11-
over time. Therefore these short codes are always stable between CLDR
12-
releases.
13-
14-
"""
15-
alias Cldr.Locale
16-
17-
@type short_zone :: String.t()
18-
19-
@type timezone :: %{
20-
aliases: [String.t(), ...],
21-
preferred: nil | short_zone(),
22-
territory: Locale.territory_code()
23-
}
24-
@unknown_zone "Etc/Unknown"
25-
26-
@timezones Cldr.Config.timezones()
27-
28-
@timezones_by_territory @timezones
29-
|> Enum.group_by(
30-
fn {_k, v} -> v.territory end,
31-
fn {k, v} -> Map.put(v, :short_zone, k) end
32-
)
33-
|> Enum.map(fn
34-
{nil, _} ->
35-
nil
36-
37-
{:UT = territory, v} ->
38-
{territory, Elixir.List.flatten(v)}
39-
40-
{k, v} ->
41-
case Cldr.validate_territory(k) do
42-
{:ok, territory} -> {territory, Elixir.List.flatten(v)}
43-
end
44-
end)
45-
|> Enum.reject(&is_nil/1)
46-
|> Map.new()
47-
48-
@territories_by_timezone @timezones_by_territory
49-
|> Enum.map(fn {territory, zones} ->
50-
Enum.map(zones, fn zone ->
51-
Enum.map(zone.aliases, fn aliass -> {aliass, territory} end)
52-
end)
53-
end)
54-
|> List.flatten()
55-
|> Enum.reject(fn {_zone, territory} -> territory == :UT end)
56-
|> Map.new()
57-
58-
@doc """
59-
Returns a mapping of CLDR short zone codes to
60-
IANA timezone names.
61-
62-
"""
63-
@spec timezones() :: %{(zone_name :: String.t()) => timezone()}
64-
def timezones do
65-
@timezones
66-
end
67-
68-
@doc false
69-
@deprecated "Use timezones_by_territory/0 instead"
70-
def timezones_for_territory do
71-
timezones_by_territory()
72-
end
73-
74-
@spec timezones_by_territory() ::
75-
unquote(Cldr.Type.timezones_by_territory(@timezones_by_territory))
76-
77-
@doc """
78-
Returns a mapping of territories to
79-
their known IANA timezone names.
80-
81-
"""
82-
@dialyzer {:nowarn_function, timezones_by_territory: 0}
83-
def timezones_by_territory do
84-
@timezones_by_territory
85-
end
86-
87-
@doc """
88-
Returns a mapping of time zone IDs to
89-
their known territory.
90-
91-
A time zone can only belong to one
92-
territory in CLDR.
93-
94-
"""
95-
def territories_by_timezone do
96-
@territories_by_timezone
97-
end
98-
99-
@doc false
100-
def timezones_for_territory(territory) do
101-
timezones_by_territory()
102-
|> Map.fetch(territory)
103-
end
104-
105-
@doc """
106-
Returns a list of IANA time zone names for
107-
a given CLDR short zone code, or `nil`.
108-
109-
The first time zone name in the list is
110-
the canonical time zone name.
111-
112-
### Examples
113-
114-
iex> Cldr.Timezone.get_short_zone("ausyd")
115-
%{
116-
preferred: nil,
117-
aliases: ["Australia/Sydney", "Australia/ACT", "Australia/Canberra", "Australia/NSW"],
118-
territory: :AU
119-
}
120-
121-
iex> Cldr.Timezone.get_short_zone("nope")
122-
nil
123-
124-
"""
125-
@spec get_short_zone(String.t(), String.t() | nil) :: map() | nil
126-
def get_short_zone(short_zone, default \\ nil) do
127-
Map.get(timezones(), short_zone, default)
128-
end
129-
130-
@doc false
131-
@deprecated "Use get_short_zone/1 instead"
132-
def get(short_zone) do
133-
get_short_zone(short_zone)
134-
end
135-
136-
@doc """
137-
Returns a `{:ok, list}` where list is a
138-
list of IANA timezone names for
139-
a given CLDR short zone code. If no such
140-
short code exists then `:error` is returned.
141-
142-
### Example
143-
144-
iex> Cldr.Timezone.fetch_short_zone("ausyd")
145-
{
146-
:ok,
147-
%{
148-
preferred: nil,
149-
aliases: ["Australia/Sydney", "Australia/ACT", "Australia/Canberra", "Australia/NSW"],
150-
territory: :AU
151-
}
152-
}
153-
154-
iex> Cldr.Timezone.fetch_short_zone("nope")
155-
:error
156-
157-
"""
158-
@spec fetch_short_zone(String.t()) :: {:ok, map()} | :error
159-
def fetch_short_zone(short_zone) do
160-
Map.fetch(timezones(), short_zone)
161-
end
162-
163-
@doc false
164-
@deprecated "Use fetch_short_zone/1 instead"
165-
def fetch(short_zone) do
166-
fetch_short_zone(short_zone)
167-
end
168-
169-
@doc false
170-
@deprecated "Use validate_short_zone/1 instead"
171-
def validate_timezone(short_zone) do
172-
validate_short_zone(short_zone)
173-
end
174-
175-
@doc false
176-
@spec validate_short_zone(String.t()) :: {:ok, String.t()} | {:error, String.t()}
177-
def validate_short_zone(short_zone) do
178-
case fetch(short_zone) do
179-
{:ok, %{aliases: [first_zone | _others]}} ->
180-
{:ok, first_zone}
181-
182-
:error ->
183-
{:error, @unknown_zone}
184-
end
185-
end
186-
end
1+
# defmodule Cldr.Timezone do
2+
# @moduledoc """
3+
# Functions to map between the CLDR short time zone code and the
4+
# IANA timezone names.
5+
#
6+
# The Unicode [locale](https://unicode.org/reports/tr35/#Locale)
7+
# [extension U](https://unicode.org/reports/tr35/#u_Extension)
8+
# allows the specification of the time zone requested for the provided locale.
9+
#
10+
# This short timezone codes never change even if the IANA names change
11+
# over time. Therefore these short codes are always stable between CLDR
12+
# releases.
13+
#
14+
# """
15+
# alias Cldr.Locale
16+
#
17+
# @type short_zone :: String.t()
18+
#
19+
# @type timezone :: %{
20+
# aliases: [String.t(), ...],
21+
# preferred: nil | short_zone(),
22+
# territory: Locale.territory_code()
23+
# }
24+
# @unknown_zone "Etc/Unknown"
25+
#
26+
# @timezones Cldr.Config.timezones()
27+
#
28+
# @timezones_by_territory @timezones
29+
# |> Enum.group_by(
30+
# fn {_k, v} -> v.territory end,
31+
# fn {k, v} -> Map.put(v, :short_zone, k) end
32+
# )
33+
# |> Enum.map(fn
34+
# {nil, _} ->
35+
# nil
36+
#
37+
# {k, v} ->
38+
# case Cldr.validate_territory(k) do
39+
# {:ok, territory} -> {territory, Elixir.List.flatten(v)}
40+
# end
41+
# end)
42+
# |> Enum.reject(&is_nil/1)
43+
# |> Map.new()
44+
#
45+
# @territories_by_timezone @timezones_by_territory
46+
# |> Enum.map(fn {territory, zones} ->
47+
# Enum.map(zones, fn zone ->
48+
# Enum.map(zone.aliases, fn aliass -> {aliass, territory} end)
49+
# end)
50+
# end)
51+
# |> List.flatten()
52+
# |> Enum.reject(fn {_zone, territory} -> territory == :UT end)
53+
# |> Map.new()
54+
#
55+
# @doc """
56+
# Returns a mapping of CLDR short zone codes to
57+
# IANA timezone names.
58+
#
59+
# """
60+
# @spec timezones() :: %{(zone_name :: String.t()) => timezone()}
61+
# def timezones do
62+
# @timezones
63+
# end
64+
#
65+
# @doc false
66+
# @deprecated "Use timezones_by_territory/0 instead"
67+
# def timezones_for_territory do
68+
# timezones_by_territory()
69+
# end
70+
#
71+
# @spec timezones_by_territory() ::
72+
# unquote(Cldr.Type.timezones_by_territory(@timezones_by_territory))
73+
#
74+
# @doc """
75+
# Returns a mapping of territories to
76+
# their known IANA timezone names.
77+
#
78+
# """
79+
# @dialyzer {:nowarn_function, timezones_by_territory: 0}
80+
# def timezones_by_territory do
81+
# @timezones_by_territory
82+
# end
83+
#
84+
# @doc """
85+
# Returns a mapping of time zone IDs to
86+
# their known territory.
87+
#
88+
# A time zone can only belong to one
89+
# territory in CLDR.
90+
#
91+
# """
92+
# def territories_by_timezone do
93+
# @territories_by_timezone
94+
# end
95+
#
96+
# @doc false
97+
# def timezones_for_territory(territory) do
98+
# timezones_by_territory()
99+
# |> Map.fetch(territory)
100+
# end
101+
#
102+
# @doc """
103+
# Returns a list of IANA time zone names for
104+
# a given CLDR short zone code, or `nil`.
105+
#
106+
# The first time zone name in the list is
107+
# the canonical time zone name.
108+
#
109+
# ### Examples
110+
#
111+
# iex> Cldr.Timezone.get_short_zone("ausyd")
112+
# %{
113+
# preferred: nil,
114+
# aliases: ["Australia/Sydney", "Australia/ACT", "Australia/Canberra", "Australia/NSW"],
115+
# territory: :AU
116+
# }
117+
#
118+
# iex> Cldr.Timezone.get_short_zone("nope")
119+
# nil
120+
#
121+
# """
122+
# @spec get_short_zone(String.t(), String.t() | nil) :: map() | nil
123+
# def get_short_zone(short_zone, default \\ nil) do
124+
# Map.get(timezones(), short_zone, default)
125+
# end
126+
#
127+
# @doc false
128+
# @deprecated "Use get_short_zone/1 instead"
129+
# def get(short_zone) do
130+
# get_short_zone(short_zone)
131+
# end
132+
#
133+
# @doc """
134+
# Returns a `{:ok, list}` where list is a
135+
# list of IANA timezone names for
136+
# a given CLDR short zone code. If no such
137+
# short code exists then `:error` is returned.
138+
#
139+
# ### Example
140+
#
141+
# iex> Cldr.Timezone.fetch_short_zone("ausyd")
142+
# {
143+
# :ok,
144+
# %{
145+
# preferred: nil,
146+
# aliases: ["Australia/Sydney", "Australia/ACT", "Australia/Canberra", "Australia/NSW"],
147+
# territory: :AU
148+
# }
149+
# }
150+
#
151+
# iex> Cldr.Timezone.fetch_short_zone("nope")
152+
# :error
153+
#
154+
# """
155+
# @spec fetch_short_zone(String.t()) :: {:ok, map()} | :error
156+
# def fetch_short_zone(short_zone) do
157+
# Map.fetch(timezones(), short_zone)
158+
# end
159+
#
160+
# @doc false
161+
# @deprecated "Use fetch_short_zone/1 instead"
162+
# def fetch(short_zone) do
163+
# fetch_short_zone(short_zone)
164+
# end
165+
#
166+
# @doc false
167+
# @deprecated "Use validate_short_zone/1 instead"
168+
# def validate_timezone(short_zone) do
169+
# validate_short_zone(short_zone)
170+
# end
171+
#
172+
# @doc false
173+
# @spec validate_short_zone(String.t()) :: {:ok, String.t()} | {:error, String.t()}
174+
# def validate_short_zone(short_zone) do
175+
# case fetch(short_zone) do
176+
# {:ok, %{aliases: [first_zone | _others]}} ->
177+
# {:ok, first_zone}
178+
#
179+
# :error ->
180+
# {:error, @unknown_zone}
181+
# end
182+
# end
183+
# end

mix/support/consolidate.ex

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -952,11 +952,13 @@ defmodule Cldr.Consolidate do
952952
)
953953

954954
Enum.map(timezones, fn
955-
%{alias: aliases, name: "ut" <> _rest = name, region: "", preferred: ""} ->
956-
{name, %{aliases: String.split(aliases, " "), territory: nil, preferred: nil}}
955+
%{alias: aliases, name: "ut" <> _rest = name, preferred: preferred} ->
956+
preferred = if preferred == "", do: nil, else: preferred
957+
{name, %{aliases: String.split(aliases, " "), territory: nil, preferred: preferred}}
957958

958-
%{alias: aliases, name: name, region: "", preferred: ""} when name in @zones_with_no_territory ->
959-
{name, %{aliases: String.split(aliases, " "), territory: nil, preferred: nil}}
959+
%{alias: aliases, name: name, preferred: preferred} when name in @zones_with_no_territory ->
960+
preferred = if preferred == "", do: nil, else: preferred
961+
{name, %{aliases: String.split(aliases, " "), territory: nil, preferred: preferred}}
960962

961963
%{alias: aliases, name: name, region: "", preferred: ""} ->
962964
region = String.slice(name, 0, 2) |> String.upcase() |> String.to_atom()

0 commit comments

Comments
 (0)