itu_codes 0.4.3 → 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -9,74 +9,114 @@ Country code lookup based on official ISO-3166-1 specifications:
9
9
  * [Country Codes - ISO 3166][3]
10
10
  * [list of alpha-2 country codes in XML format][4]
11
11
 
12
+ The main goal of this library is to closely match the latest official specifications from the ITU and the ISO relating to callign codes. If you find any discrepancies in the data, please let me know!
13
+
14
+ Some complicating factors when dealing with calling codes:
15
+ * In North America, 25 countries and territories follow the [North American Numbering Plan][5] and share the ITU code '1'.
16
+ * Russia and Kazakhstan share the ITU code '7'.
17
+ * The ITU does not use ISO 3166 alpha-2 codes to specify countries or regions in its documents.
18
+ * In general, each ITU code corresponds to exactly one ISO 3166 code. However, there are exceptions. For examples, the Australian External Territories have a single ITU code of '672', but have 4 distinct ISO 3166 codes (CC, CX, HM, NF).
19
+
20
+
12
21
  ## Usage:
13
22
 
14
- ItuCodes.valid_code? '8392813'
15
- # => false
23
+ ```ruby
24
+
25
+ # The following methods are provided:
26
+
27
+ # ItuCodes.country_for(full_or_partial_number)
28
+ # ItuCodes.find_by_itu_code(code)
29
+ # ItuCodes.find_by_name(country_name)
30
+ # ItuCodes.valid_code?(exact_itu_code)
31
+ # ItuCodes.parse_code(full_or_partial_number)
32
+ # ItuCodes.parse_number(full_or_partial_number)
33
+ # ItuCodes.iso2itu(iso_2_letter_country_code)
34
+ # ItuCodes.itu2iso(exact_itu_code)
35
+ # ItuCodes.compatriots?(full_or_partial_number1, full_or_partial_number2)
36
+
37
+
38
+ # Examples
39
+
40
+ # Any full or partial number will work
41
+ ItuCodes.country_for('33')
42
+ # => "France"
43
+
44
+ # Country names are returned EXACTLY as specified in ITU E.164 document
45
+ ItuCodes.country_for('18184442222')
46
+ # => "United States of America"
47
+
48
+ ItuCodes.country_for('7')
49
+ # => [ "Kazakhstan (Republic of)", "Russian Federation" ]
50
+
51
+ ItuCodes.find_by_itu_code '995'
52
+ # => "Georgia"
16
53
 
17
- ItuCodes.valid_code? '7'
18
- # => true
54
+ ItuCodes.find_by_itu_code '123123995'
55
+ # => nil
19
56
 
20
- ItuCodes.parse_code '1818'
21
- # => 1
57
+ # Name should match EXACTLY as specified in ITU E.164 document
58
+ # ItuCodes.iso2itu accepts 2 letter ISO 3166 codes
59
+ ItuCodes.find_by_name 'France'
60
+ # => "33"
22
61
 
23
- ItuCodes.parse_code '822'
24
- # => "82"
62
+ ItuCodes.find_by_name 'Erewhon'
63
+ # => nil
25
64
 
26
- ItuCodes.parse_code '4'
27
- # => nil
65
+ ItuCodes.valid_code? '8392813'
66
+ # => false
28
67
 
29
- ItuCodes.find_by_name 'France'
30
- # => "33"
68
+ ItuCodes.valid_code? '7'
69
+ # => true
31
70
 
32
- ItuCodes.find_by_itu_code '995'
33
- # => "Georgia"
71
+ ItuCodes.parse_code '18185558888'
72
+ # => 1
34
73
 
35
- ItuCodes.find_by_name 'Erewhon'
36
- # => nil
74
+ ItuCodes.parse_code '822'
75
+ # => "82"
37
76
 
38
- ItuCodes.find_by_itu_code '123123995'
39
- # => nil
77
+ ItuCodes.parse_code '4'
78
+ # => nil
40
79
 
41
- # Despite the same 1st digit,
42
- # these are for different
43
- # countries ...
44
- ItuCodes.compatriots? '822', '811'
45
- # => false
80
+ ItuCodes.parse_number '18185558888'
81
+ # => "8185558888"
46
82
 
47
- # ... but these are for
48
- # the same country ...
49
- ItuCodes.compatriots? '1984', '1985'
50
- # => true
83
+ # Convert from and to ISO 2-letter country codes:
84
+ ItuCodes.iso2itu('US')
85
+ # => "1"
51
86
 
52
- # ... and then there's the
53
- # North American 'situation' ...
54
- ItuCodes.compatriots? '1264', '1818'
55
- # => false
87
+ # Convert from and to ISO 2-letter country codes:
88
+ ItuCodes.itu2iso('1')
89
+ # => ["AS", "AI", "AG", "BS", "BB", "BM", "VG", "CA", "KY", "DM", "DO", "GD", "GU", "JM", "MS", "MP", "PR", "KN", "LC", "VC", "SX", "TT", "TC", "US", "VI"]
56
90
 
57
- # =====================================================
58
- # = Using 2-letter ISO country codes is most reliable =
59
- # =====================================================
91
+ # Mexico
92
+ # ISO 3361 code : MX
93
+ # ITU code : 52
94
+ ItuCodes.iso2itu('MX')
95
+ # => "52"
60
96
 
61
- # Convert from and to ISO 2-letter country codes:
62
- ItuCodes.iso2itu('US')
63
- # => "1"
97
+ ItuCodes.itu2iso('52')
98
+ # => "MX"
64
99
 
65
- # Convert from and to ISO 2-letter country codes:
66
- ItuCodes.itu2iso('1')
67
- # => ["AS", "AI", "AG", "BS", "BB", "BM", "VG", "CA", "KY", "DM", "DO", "GD", "GU", "JM", "MS", "MP", "PR", "KN", "LC", "VC", "SX", "TT", "TC", "US", "VI"]
100
+ # Despite the same 1st digit,
101
+ # these are for different
102
+ # countries ...
103
+ ItuCodes.compatriots? '822', '811'
104
+ # => false
68
105
 
69
- # Mexico
70
- # ISO 3361 code : MX
71
- # ITU code : 52
72
- ItuCodes.iso2itu('MX')
73
- # => "52"
106
+ # ... but these are for
107
+ # the same country ...
108
+ ItuCodes.compatriots? '1984', '1985'
109
+ # => true
74
110
 
75
- ItuCodes.itu2iso('52')
76
- # => "MX"
111
+ # ... and then there's the
112
+ # North American 'situation' ...
113
+ ItuCodes.compatriots? '1264', '1818'
114
+ # => false
77
115
 
116
+ ```
78
117
 
79
118
  [1]: http://www.itu.int/pub/T-SP-E.164D-11-2011
80
119
  [2]: http://www.itu.int/dms_pub/itu-t/opb/sp/T-SP-E.164D-11-2011-PDF-E.pdf
81
120
  [3]: http://www.iso.org/iso/home/standards/country_codes
82
- [4]: http://www.iso.org/iso/home/standards/country_codes/country_names_and_code_elements_xml
121
+ [4]: http://www.iso.org/iso/home/standards/country_codes/country_names_and_code_elements_xml
122
+ [5]: http://www.nanpa.com
@@ -4,6 +4,90 @@
4
4
  # * http://www.itu.int/pub/T-SP-E.164D-11-2011
5
5
  # * vendor/itu/T-SP-E.164D-11-2011-PDF-E.pdf
6
6
 
7
+ American Samoa:
8
+ - '1684'
9
+ Anguilla:
10
+ - '1264'
11
+ Antigua and Barbuda:
12
+ - '1268'
13
+ Bahamas (Commonwealth of the):
14
+ - '1242'
15
+ Barbados:
16
+ - '1246'
17
+ Bermuda:
18
+ - '1441'
19
+ British Virgin Islands:
20
+ - '1284'
21
+ Canada:
22
+ - '1204'
23
+ - '1226'
24
+ - '1236'
25
+ - '1249'
26
+ - '1250'
27
+ - '1289'
28
+ - '1306'
29
+ - '1343'
30
+ - '1365'
31
+ - '1403'
32
+ - '1416'
33
+ - '1418'
34
+ - '1431'
35
+ - '1437'
36
+ - '1438'
37
+ - '1450'
38
+ - '1506'
39
+ - '1514'
40
+ - '1519'
41
+ - '1579'
42
+ - '1581'
43
+ - '1587'
44
+ - '1604'
45
+ - '1613'
46
+ - '1639'
47
+ - '1647'
48
+ - '1705'
49
+ - '1709'
50
+ - '1778'
51
+ - '1780'
52
+ - '1807'
53
+ - '1819'
54
+ - '1867'
55
+ - '1873'
56
+ - '1902'
57
+ - '1905'
58
+ Cayman Islands:
59
+ - '1345'
60
+ Dominica (Commonwealth of):
61
+ - '1767'
62
+ Dominican Republic:
63
+ - '1809'
64
+ - '1829'
65
+ - '1849'
66
+ Grenada:
67
+ - '1473'
68
+ Guam:
69
+ - '1671'
70
+ Jamaica:
71
+ - '1876'
72
+ Montserrat:
73
+ - '1664'
74
+ Northern Mariana Islands (Commonwealth of the):
75
+ - '1670'
76
+ Puerto Rico:
77
+ - '1787'
78
+ - '1939'
79
+ Saint Kitts and Nevis:
80
+ - '1869'
81
+ Saint Lucia:
82
+ - '1758'
83
+ Saint Vincent and the Grenadines:
84
+ - '1784'
85
+ Sint Maarten (Dutch part):
86
+ - '1721'
87
+ Trinidad and Tobago:
88
+ - '1868'
89
+ Turks and Caicos Islands:
90
+ - '1649'
7
91
  United States of America:
8
92
  - '1201'
9
93
  - '1202'
@@ -328,67 +412,5 @@ United States of America:
328
412
  - '1984'
329
413
  - '1985'
330
414
  - '1989'
331
- Canada:
332
- - '1204'
333
- - '1226'
334
- - '1236'
335
- - '1249'
336
- - '1250'
337
- - '1289'
338
- - '1306'
339
- - '1343'
340
- - '1365'
341
- - '1403'
342
- - '1416'
343
- - '1418'
344
- - '1431'
345
- - '1437'
346
- - '1438'
347
- - '1450'
348
- - '1506'
349
- - '1514'
350
- - '1519'
351
- - '1579'
352
- - '1581'
353
- - '1587'
354
- - '1604'
355
- - '1613'
356
- - '1639'
357
- - '1647'
358
- - '1705'
359
- - '1709'
360
- - '1778'
361
- - '1780'
362
- - '1807'
363
- - '1819'
364
- - '1867'
365
- - '1873'
366
- - '1902'
367
- - '1905'
368
- American Samoa: '1684'
369
- Anguilla: '1264'
370
- Antigua and Barbuda: '1268'
371
- Bahamas: '1242'
372
- Barbados: '1246'
373
- Bermuda: '1441'
374
- British Virgin Islands: '1284'
375
- Cayman Islands: '1345'
376
- Dominica: '1767'
377
- Dominican Republic:
378
- - '1809'
379
- - '1829'
380
- - '1849'
381
- Grenada: '1473'
382
- Guam: '1671'
383
- Jamaica: '1876'
384
- Montserrat: '1664'
385
- Northern Mariana Islands: '1670'
386
- Puerto Rico:
387
- - '1787'
388
- - '1939'
389
- Saint Kitts and Nevis: '1869'
390
- Saint Lucia: '1758'
391
- Saint Vincent and the Grenadines: '1784'
392
- Trinidad and Tobago: '1868'
393
- Turks and Caicos Islands: '1649'
394
- United States Virgin Islands: '1340'
415
+ United States Virgin Islands:
416
+ - '1340'
data/lib/itu_codes.rb CHANGED
@@ -1,24 +1,52 @@
1
- # to-do: deal with headache codes:
2
- # 1 --> Non-US need to be separated by area code
3
- # 7 --> Kazakhstan!
4
-
5
1
  require 'itu_codes/constants'
6
2
  require 'itu_codes/helpers'
7
3
 
8
- # TODO: add ability to search for common names (i.e. 'USA' or 'United States of America' for 'United States')
9
-
10
4
  module ItuCodes
11
5
  class << self
12
- def find_by_itu_code(code)
13
- returner = lookup(code)
14
6
 
15
- if returner.size <= 1
16
- returner.first
7
+ # number is a full or partial number
8
+ def country_for(number)
9
+ parsed = parse_code(number)
10
+
11
+ return if parsed.nil?
12
+
13
+ matching_countries = if north_american?(parsed)
14
+ north_american_codes.select do |k, v|
15
+ v.any? do |na_area_code|
16
+ na_area_code =~ /^#{number[0,4]}/
17
+ end
18
+ end.keys
19
+ elsif eurasian?(parsed)
20
+ temp = []
21
+ temp << "Kazakhstan (Republic of)" if kazakh?(number[0,2])
22
+ temp << "Russian Federation" if russian?(number[0,2])
23
+ temp
17
24
  else
18
- returner
25
+ country_codes[parsed]
26
+ end
27
+
28
+ if matching_countries.is_a?(Array) && matching_countries.length === 1
29
+ matching_countries.first
30
+ else
31
+ matching_countries
32
+ end
33
+ end
34
+
35
+ # Must pass a valid ITU code
36
+ def find_by_itu_code(code)
37
+ if valid_code?(code)
38
+ returner = country_for(code)
39
+
40
+ if returner.size <= 1
41
+ returner.first
42
+ else
43
+ returner
44
+ end
19
45
  end
20
46
  end
21
47
 
48
+ # Passed name must match exact name specified in ITU spec
49
+ # see: lib/data/assigned_country_codes.yml
22
50
  def find_by_name(name)
23
51
  matching = country_codes.select do |k, v|
24
52
  [*v].include? name
@@ -33,16 +61,17 @@ module ItuCodes
33
61
  end
34
62
  end
35
63
 
36
- # lookup by ISO 3166 country code
37
- # e.g. iso2itu('US')
64
+ # lookup by ISO 3166 alpha-2 country code
65
+ # e.g. find_by_iso_code('US')
38
66
  # see : http://www.iso.org/iso/country_codes.htm
39
67
  def iso2itu(iso_code)
40
68
  country_name = Helpers.country_name_lookup(iso_code)
41
69
  find_by_name(country_name)
42
70
  end
43
71
 
44
- def itu2iso(itu)
45
- name = find_by_itu_code(itu)
72
+ # number is a full or partial number
73
+ def itu2iso(number)
74
+ name = country_for(number)
46
75
 
47
76
  if name.is_a?(String)
48
77
  Helpers.country_code_lookup(name)
@@ -60,10 +89,6 @@ module ItuCodes
60
89
  country_codes.has_key?(some_code)
61
90
  end
62
91
 
63
- def north_american?(some_code)
64
- some_code[0,1] == '1'
65
- end
66
-
67
92
  # parse a destination code (probably with area code) to find the ITU code
68
93
  # ex: parse_code(1818) => 1
69
94
  def parse_code(some_number)
@@ -78,33 +103,62 @@ module ItuCodes
78
103
  # ex: parse_number(18184443322) => 8184443322
79
104
  def parse_number(some_number)
80
105
  country_code = parse_code(some_number)
81
- some_number.gsub(/^#{country_code}/) unless country_code.nil?
106
+ some_number[country_code.length,some_number.length] unless country_code.nil?
82
107
  end
83
108
 
84
109
  def compatriots?(some, other)
85
- both_valid = ! ( parse_code(some).nil? or parse_code(other).nil? )
110
+ both_valid = ! ( parse_code(some).nil? || parse_code(other).nil? )
86
111
 
87
112
  if north_american?(some) && north_american?(other)
88
- both_valid && !(lookup(some) & lookup(other)).empty?
113
+ both_valid && !([*country_for(some)] & [*country_for(other)]).empty?
114
+ elsif eurasian?(some) && eurasian?(other)
115
+ both_valid && !([*country_for(some)] & [*country_for(other)]).empty?
89
116
  else
90
117
  some = parse_code(some)
91
118
  other = parse_code(other)
92
- both_valid && lookup(some) == lookup(other)
119
+ both_valid && some === other
93
120
  end
94
121
  end
95
122
 
123
+ def north_american?(some_code)
124
+ some_code[0,1] == '1'
125
+ end
126
+
127
+ def eurasian?(some_code)
128
+ some_code[0,1] == '7'
129
+ end
130
+
96
131
  def american?(some_code)
97
- # for non-US North American codes, parse_code will return a 4 digit code
98
- # for US, '1' will be returned
99
- countries = lookup(some_code[0,4]) || []
100
- countries.include?('United States of America')
132
+ [* country_for(some_code) ].include?('United States of America')
101
133
  end
102
134
 
103
135
  def canadian?(some_code)
104
- countries = lookup(some_code[0,4])
105
- north_american?(some_code) && (countries.include?('Canada'))
136
+ [* country_for(some_code) ].include?('Canada')
106
137
  end
107
138
 
139
+ # Russian codes start with 7
140
+ # and are not codes defined for Kazakhstan
141
+ def russian?(some_code)
142
+ if some_code.length < 2
143
+ eurasian?(some_code)
144
+ else
145
+ eurasian?(some_code) && !kazakh?(some_code)
146
+ end
147
+ end
148
+
149
+ # Kazakhstan country code will start with either 76 or 77
150
+ # see: http://www.itu.int/oth/T020200006F/en
151
+ # http://www.itu.int/dms_pub/itu-t/oth/02/02/T020200006F0001PDFE.pdf
152
+ # NOTE: apparently, some numbers are still jointly used by Kazakhstan and Russia
153
+ # 7000-0009, 7100-7199, 7200-7299, 7800-7809, 7881-7899
154
+ # ItuCodes reports these as Russian codes for the time being
155
+ def kazakh?(some_code)
156
+ if some_code.length < 2
157
+ eurasian?(some_code)
158
+ else
159
+ %(77 76).include?(some_code[0,2])
160
+ end
161
+ end
108
162
 
109
163
  private
110
164
 
@@ -112,19 +166,12 @@ module ItuCodes
112
166
  Constants::NORTH_AMERICAN_AREA_CODES
113
167
  end
114
168
 
115
- def country_codes
116
- Constants::ASSIGNED_COUNTRY_CODES
169
+ def eurasian_codes
170
+ Constants::NORTH_AMERICAN_AREA_CODES
117
171
  end
118
172
 
119
- def lookup(code)
120
- cleaned = clean(code)
121
- matching_countries = country_codes[cleaned] || []
122
-
123
- matching_north_americans = north_american_codes.select do |k, v|
124
- [*v].include?(code)
125
- end || {}
126
-
127
- [*matching_countries] + matching_north_americans.keys.compact
173
+ def country_codes
174
+ Constants::ASSIGNED_COUNTRY_CODES
128
175
  end
129
176
 
130
177
  # converts input to string, then strips any non-numeric characters
@@ -2,7 +2,8 @@ require 'yaml'
2
2
 
3
3
  module ItuCodes
4
4
  module Constants
5
- ASSIGNED_COUNTRY_CODES = YAML.load_file(File.expand_path(File.dirname(__FILE__)) + '/../data/assigned_country_codes.yml')
6
- NORTH_AMERICAN_AREA_CODES = YAML.load_file(File.expand_path(File.dirname(__FILE__)) + '/../data/north_american_area_codes.yml')
5
+ base_path = File.expand_path(File.dirname(__FILE__))
6
+ ASSIGNED_COUNTRY_CODES = YAML.load_file base_path + '/../data/assigned_country_codes.yml'
7
+ NORTH_AMERICAN_AREA_CODES = YAML.load_file base_path + '/../data/north_american_area_codes.yml'
7
8
  end
8
9
  end
@@ -1,3 +1,3 @@
1
1
  module ItuCodes
2
- VERSION = "0.4.3"
2
+ VERSION = "0.4.7"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itu_codes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.4.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-17 00:00:00.000000000 Z
12
+ date: 2013-03-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake