File Coverage

blib/lib/Number/Phone/Country.pm
Criterion Covered Total %
statement 68 69 100.0
branch 31 32 96.8
condition 3 3 100.0
subroutine 12 13 100.0
pod 6 6 100.0
total 120 123 99.1


line stmt bran cond sub pod time code
1             package Number::Phone::Country;
2              
3 36     36   424630 use strict;
  36         134  
  36         1099  
4 36     36   24706 use Number::Phone::Country::Data;
  36         289  
  36         2080  
5              
6             # *_codes are global so we can mock in some tests
7 36     36   272 use vars qw($VERSION %idd_codes %prefix_codes);
  36         114  
  36         5829  
8             $VERSION = 1.97;
9             my $use_uk = 0;
10              
11             sub import {
12 137     137   70169 shift;
13 137         322 my $export = 1;
14 137         404 foreach my $param (@_) {
15 139 100       776 if(lc($param) eq 'noexport') { $export = 0; }
  136 100       337  
16 2         5 elsif(lc($param) eq 'uk') { $use_uk = 1; }
17 1         12 else { warn("Unknown param to ".__PACKAGE__." '$param' at ".join(' line ', (caller())[1,2])."\n"); }
18             }
19 137 100       29932 if($export) {
20 1         3 my $callpkg = caller(1);
21 36     36   256 no strict 'refs';
  36         104  
  36         37890  
22 1         24 warn("Exporting from Number::Phone::Country is deprecated at ".join(' line ', (caller())[1,2])."\n");
23 1         716 *{"$callpkg\::phone2country"} = \&{__PACKAGE__."\::phone2country"};
  1         68  
  1         4  
24             }
25             }
26              
27             sub phone2country {
28 5562     5562 1 12055 my ($phone) = @_;
29 5562         11926 return (phone2country_and_idd($phone))[0];
30             }
31              
32             our %NANP_areas = (
33             CA => do {
34             # see http://www.cnac.ca/co_codes/co_code_status.htm
35             # checked on 2023-03-03
36             # next check due 2023-09-01 (semi-annually)
37             my $canada = join('|', qw(
38             204 226 236 249 250 263 289
39             306 343 354 365 367 368 382
40             403 416 418 428 431 437 438 450 468 474
41             506 514 519 548 579 581 584 587
42             604 613 639 647 672 683
43             705 709 742 753 778 780 782
44             807 819 825 867 873 879
45             902 905
46             ));
47             # handful of non-geographic country-specific codes ...
48             # see https://en.wikipedia.org/wiki/Area_code_600
49             # checked on 2023-03-03
50             # next check due 2023-09-01 (semi-annually)
51             $canada = join('|', $canada, 600, 622, 633, 644, 655, 677, 688);
52             },
53             US => do {
54             # see https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes#United_States
55             # and https://www.allareacodes.com/area_code_listings_by_state.htm
56             # but the latter doesn't contain some overlays that are about to come into service
57             # NB for Hyder, Alaska, it shares three COs with Stewart, BC, and we can't tell which number is in which country,
58             # so those prefixes aren't listed here
59             # checked on 2023-03-03
60             # next check due 2023-09-01 (semi-annually)
61             my $usa = join('|', qw(
62             205 251 256 334 659 938
63             907
64             480 520 602 623 928
65             327 479 501 870
66             209 213 279 310 323 341 350 369 408 415 424 442 510 530 559 562 619 626 628 650 657 661 669 707 714 747 760 805 818 820 831 840 858 909 916 925 949 951
67             303 719 720 970 983
68             203 475 860 959
69             302
70             202 771
71             239 305 321 324 352 386 407 448 561 645 656 689 727 728 754 772 786 813 850 863 904 941 954
72             229 404 470 478 678 706 762 770 912 943
73             808
74             208 986
75             217 224 309 312 331 447 464 618 630 708 730 773 779 815 847 861 872
76             219 260 317 463 574 765 812 930
77             319 515 563 641 712
78             316 620 785 913
79             270 364 502 606 859
80             225 318 337 504 985
81             207
82             227 240 301 410 443 667
83             339 351 413 508 617 774 781 857 978
84             231 248 269 313 517 586 616 679 734 810 906 947 989
85             218 320 507 612 651 763 952
86             228 601 662 769
87             235 314 417 557 573 636 660 816 975
88             406
89             308 402 531
90             702 725 775
91             603
92             201 551 609 640 732 848 856 862 908 973
93             505 575
94             212 315 329 332 347 363 516 518 585 607 631 646 680 716 718 838 845 914 917 929 934
95             252 336 472 704 743 828 910 919 980 984
96             701
97             216 220 234 283 326 330 380 419 440 513 567 614 740 937
98             405 539 572 580 918
99             458 503 541 971
100             215 223 267 272 412 445 484 570 582 610 717 724 814 835 878
101             401
102             803 839 843 854 864
103             605
104             423 615 629 731 865 901 931
105             210 214 254 281 325 346 361 409 430 432 469 512 682 713 726 737 806 817 830 832 903 915 936 940 945 956 972 979
106             385 435 801
107             802
108             276 434 540 571 703 757 804 826 948
109             206 253 360 425 509 564
110             304 681
111             262 274 353 414 534 608 715 920
112             307
113             ));
114             # handful of non-geographic country-specific codes ...
115             # see https://en.wikipedia.org/wiki/Area_code_710
116             # checked on 2021-12-06
117             # next check due 2023-12-01 (bi-annually)
118             $usa = join('|', $usa, 710);
119             },
120             # see https://en.wikipedia.org/wiki/North_American_Numbering_Plan#Countries_and_territories
121             # checked on 2022-12-03
122             # next check due 2023-12-01 (annually)
123             AS => '684', # American Samoa
124             AI => '264', # Anguilla
125             AG => '268', # Antigua and Barbude
126             BS => '242', # Bahamas
127             BB => '246', # Barbados
128             BM => '441', # Bermuda
129             VG => '284', # British Virgin Islands
130             KY => '345', # Cayman Islands
131             DM => '767', # Dominica
132             DO => '809|829|849', # Dominican Republic
133             GD => '473', # Grenada
134             GU => '671', # Guam
135             JM => '876|658', # Jamaica
136             MS => '664', # Montserrat
137             MP => '670', # Northern Mariana Islands
138             PR => '787|939', # Puerto Rico
139             KN => '869', # Saint Kitts and Nevis
140             LC => '758', # Saint Lucia
141             VC => '784', # Saint Vincent and the Grenadines
142             SX => '721', # Sint Maarten
143             TT => '868', # Trinidad and Tobago
144             TC => '649', # Turks and Caicos Islands
145             VI => '340', # US Virgin Islands
146             );
147              
148             # private sub, returns list of NANP areas for the given ISO country code
149             sub _NANP_area_codes {
150             # uncoverable subroutine - only used in build scripts
151             # uncoverable statement
152 0     0   0 return split('\|', $NANP_areas{shift()});
153             }
154              
155             # private sub, returns list of NANP areas that *aren't* in the US or Canada
156             sub _non_US_CA_area_codes {
157             # uncoverable subroutine - only used in build scripts
158             return sort split('\|', join('|',
159 1     1   612 @NANP_areas{grep { $_ !~ /^(US|CA)$/ } keys %NANP_areas}
  25         115  
160             ));
161              
162             }
163              
164             sub phone2country_and_idd {
165 5571     5571 1 15790 my ($phone) = @_;
166 5571         11563 $phone =~ s/[^\+?\d+]//g;
167 5571 100       22766 $phone = '+1'.$phone unless(substr($phone, 0, 1) =~ /[1+]/);
168 5571         22550 $phone =~ s/\D//g;
169              
170             # deal with NANP insanity
171 5571 100       16249 if($phone =~ m!^1(\d{3})\d{7}$!) {
172 1485         4277 my $area = $1;
173 1485         7995 foreach my $country (keys %NANP_areas) {
174 28088 100       1205042 if($area =~ /^($NANP_areas{$country})$/x) {
175 772         8961 return ($country, 1);
176             }
177             }
178 713         5392 return ('NANP', 1);
179             } else {
180 4086         11255 my @prefixes = map { substr($phone, 0, $_) } reverse 1..length($phone);
  42376         80635  
181 4086         10214 foreach my $idd (@prefixes) {
182 35020 100       72685 if(exists $idd_codes{$idd}) {
183 4077         8284 my $country = $idd_codes{$idd};
184 4077 100       9656 if(ref($country) eq 'ARRAY'){
185 732         1824 foreach my $country_code (@$country) {
186 1010         2696 my $class = "Number\::Phone\::StubCountry\::" . $country_code;
187 1010         71113 eval "require $class";
188 1010 100       12162 if ($@) {
    100          
189 16         71 my $error = $@;
190             } elsif($class->new('+' . $phone)) {
191             return (
192 646 100 100     9972 (($country_code eq 'GB' && $use_uk) ? 'UK' : $country_code),
193             $idd
194             );
195             }
196             }
197 86         323 $country = @$country[0];
198             }
199 3431         6803 $country =~ s/.*:://;
200 3431         20355 return ($country, $idd);
201             }
202             }
203             }
204 9         54 return;
205             }
206              
207             sub country_code {
208 4150     4150 1 119629 my $country = shift;
209 4150 100       13720 $country = uc($country) if($country =~ /^[a-z]{2}$/i);
210              
211 4150 100       11513 my $data = $prefix_codes{$country} or return;
212              
213 4149         16941 return $$data[0];
214             }
215              
216             sub idd_code {
217 245     245 1 554 my $country = uc shift;
218              
219 245 100       771 my $data = $prefix_codes{$country} or return;
220              
221 244         1066 return $$data[1];
222             }
223              
224             sub idd_regex {
225 239     239 1 546 my $country = uc shift;
226              
227 239 50       730 my $data = $prefix_codes{$country} or return;
228              
229 239         545 return $$data[3];
230             }
231              
232             sub ndd_code {
233 240     240 1 150249 my $country = uc shift;
234              
235 240 100       791 my $data = $prefix_codes{$country} or return;
236              
237 239         876 return $$data[2];
238             }
239              
240             1;
241              
242             =head1 NAME
243              
244             Number::Phone::Country - Lookup country of phone number
245              
246             =head1 SYNOPSIS
247              
248             use Number::Phone::Country;
249              
250             #returns 'CA' for Canada
251             my $iso_country_code = phone2country("1 (604) 111-1111");
252              
253             or
254              
255             use Number::Phone::Country qw(noexport uk);
256              
257             my $iso_country_code = Number::Phone::Country::phone2country(...);
258              
259             or
260              
261             my ($iso_country_code, $idd) = Number::Phone::Country::phone2country_and_idd(...);
262              
263             =head1 DESCRIPTION
264              
265             This module looks up up the country based on a telephone number.
266             It uses the International Direct Dialing (IDD) prefix, and
267             lookups North American numbers using the Area Code, in accordance
268             with the North America Numbering Plan (NANP). It can also, given a
269             country, tell you the country code, and the prefixes you need to dial
270             when in that country to call outside your local area or to call another
271             country.
272              
273             Note that by default, phone2country is exported into your namespace. This
274             is deprecated and may be removed in a future version. You can turn that
275             off by passing the 'noexport' constant when you use the module.
276              
277             Also be aware that the ISO code for the United Kingdom is GB, not UK. If
278             you would prefer UK, pass the 'uk' constant.
279              
280             I have put in number ranges for Kosovo, which does not yet have an ISO country
281             code. I have used XK, as that is the de facto standard as used by numerous
282             international bodies such as the European Commission and the IMF. I previously
283             used KOS, as used by the UN Development Programme. This may change again in
284             the future.
285              
286             =head1 FUNCTIONS
287              
288             The following functions are available:
289              
290             =over 4
291              
292             =item country_code($country)
293              
294             Returns the international dialing prefix for this country - eg, for the UK
295             it returns 44, and for Canada it returns 1.
296              
297             =item idd_code($country)
298              
299             Returns one, of possibly multiple, International Direct Dialing prefixes for
300             the given ISO Alpha-2 country code. Returns nothing if the country code is not
301             recognised or not supported.
302              
303             The IDD prefix is needed to make a call B to another country.
304             For example, when calling the UK from the US, the caller must first dial the
305             IDD prefix 011 to setup an international call, followed by the country calling
306             code for the UK (44), followed by the UK national number.
307              
308             Many telephone systems allow the caller to dial a plus sign prefix
309             (+) in place of the IDD, in which case the system replaces the plus sign with
310             the correct IDD prefix for the caller's country.
311              
312             Some countries have more than one IDD code, allowing the caller to route their
313             calls through specific networks. C only returns one code. See
314             C if you need to match a number against known IDD prefixes for a
315             given country.
316              
317             =item idd_regex($country)
318              
319             Returns a regular expression that matches against known International Direct
320             Dialing prefixes for the given ISO Alpha-2 country code. Returns nothing if
321             the country code is not recognised or not supported.
322              
323             As an example, the regular expression for Australia (AU) will match a number of
324             IDD prefixes, including 0011, 0014, and 0015, making it possible to determine
325             that 001516502530000 could be a US number being dialled from Australia.
326              
327             Be aware that some numbers will match against IDD prefixes from multiple
328             countries. Other numbers will be valid national numbers for one country, and
329             valid international numbers when called for other countries. For example,
330             C<01143662111> is a valid national number for Sheffield, England. It could
331             also be a valid number in Austria:
332              
333             Calling from within the UK:
334              
335             Area code: 0114
336             Subscriber: 366 2111
337             National: 0114 366 2111
338             International: +441143662111
339              
340             Calling from a country that uses the NANP (North American Numbering Plan):
341              
342             IDD: 011
343             Country code: 43 (Austria)
344             Area code: 0662 (Salzburg)
345             Subscriber: 111
346             National: 0662 111
347             International: +43662111
348              
349             =item ndd_code($country)
350              
351             Returns the National Direct Dialing prefix for the given country. This is
352             the prefix used to make a call B from one city to
353             another. This prefix may not be necessary when calling another city in the
354             same vicinity. This is followed by the city or area code for the place you
355             are calling. For example, in the US, the NDD prefix is "1", so you must
356             dial 1 before the area code to place a long distance call within the
357             country.
358              
359             =item phone2country($phone)
360              
361             Returns the ISO country code (or XK for Kosovo) for a phone number.
362             eg, for +441234567890 it returns 'GB' (or 'UK' if you've told it to).
363              
364             =item phone2country_and_idd($phone)
365              
366             Returns a list containing the ISO country code and IDD prefix for the given
367             phone number. eg for +441234567890 it returns ('GB', 44).
368              
369             =back
370              
371             =head1 SEE ALSO
372              
373             L
374              
375             =head1 BUGS
376              
377             It has not been possible to maintain complete backwards compatibility with
378             the original 0.01 release. To fix a
379             bug, while still retaining the ability to look up plain un-adorned NANP
380             numbers without the +1 prefix, all non-NANP numbers *must* have their
381             leading + sign.
382              
383             Another incompatibility - it was previously assumed that any number not
384             assigned to some other country was in the US. This was incorrect for (eg)
385             800 numbers. These are now identified as being generic NANP numbers.
386              
387             Will go out of date every time the NANP has one of its code splits/overlays.
388             So that's about once a month then. I'll do my best to keep it up to date.
389              
390             =head1 WARNING
391              
392             The Yugoslavs keep changing their minds about what country they want to be
393             and what their ISO 3166 code and IDD prefix should be. YU? CS? RS? ME?
394             God knows. And then there's Kosovo ...
395              
396             =head1 AUTHOR
397              
398             now maintained by David Cantrell Edavid@cantrell.org.ukE
399              
400             originally by TJ Mather, Etjmather@maxmind.comE
401              
402             country/IDD/NDD contributions by Michael Schout, Emschout@gkg.netE
403              
404             Thanks to Shraga Bor-Sood for the updates in version 1.4.
405              
406             =head1 COPYRIGHT AND LICENSE
407              
408             Copyright 2003 by MaxMind LLC
409              
410             Copyright 2004 - 2023 David Cantrell
411              
412             This library is free software; you can redistribute it and/or modify
413             it under the same terms as Perl itself.
414              
415             =cut