Skip to content

Commit

Permalink
Merge pull request #89 from mikeraynham/idd_regex
Browse files Browse the repository at this point in the history
Expose libphonenumber IDD prefix regular expressions
  • Loading branch information
DrHyde committed Jul 10, 2018
2 parents 6a0ba2a + f579c69 commit 39f8a36
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 25 deletions.
39 changes: 30 additions & 9 deletions build-data.country-mapping
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ my %prefix_codes = ();
TERRITORY: foreach my $territory (@territories) {
my $IDD_country_code = ''.$territory->find('@countryCode');
my $national_code = ''.$territory->find('@nationalPrefix');
my $international_rx = ''.$territory->find('@internationalPrefix');
my $international_code = ''.$territory->find('@preferredInternationalPrefix') ||
''.$territory->find('@internationalPrefix');
$international_rx;
my $ISO_country_code = ''.$territory->find('@id');
if($ISO_country_code !~ /^..$/) {
warn("skipping 'country' $ISO_country_code (+$IDD_country_code)\n");
Expand All @@ -45,6 +46,20 @@ TERRITORY: foreach my $territory (@territories) {
exit(1);
}
}

my $idd_rx = eval { qr/\A $international_rx /xms };
if ($@ || !$idd_rx) {
warn("For $ISO_country_code found invalid idd regex $international_rx\n$@\n");
exit(1);
}
elsif (length $international_code) {
if ($international_code !~ $idd_rx) {
warn("idd regex $idd_rx for $ISO_country_code does not match" .
"against its idd code $international_code. Exiting.\n");
exit(1);
}
}

if($national_code && $national_code !~ /^\d+$/) {
warn("For $ISO_country_code found ndd code $national_code\n");
exit(1);
Expand All @@ -59,8 +74,9 @@ TERRITORY: foreach my $territory (@territories) {
}
$prefix_codes{$ISO_country_code} = [
$IDD_country_code,
(length($international_code) ? $international_code : undef),
(length($national_code) ? $national_code : undef),
(length($international_code) ? $international_code : undef),
(length($national_code) ? $national_code : undef),
(length($international_rx) ? $international_rx : undef),
];
}

Expand Down Expand Up @@ -105,6 +121,11 @@ foreach my $ISO_code (sort keys %prefix_codes) {
? "'$_'"
: 'undef'
} $prefix_codes{$ISO_code}->[1], $prefix_codes{$ISO_code}->[2]).
', ' .
(defined $prefix_codes{$ISO_code}->[3]
? 'qr/\A ' . $prefix_codes{$ISO_code}->[3] . ' /xms'
: 'undef'
).
"],\n";
}
print $module_fh q{
Expand Down Expand Up @@ -249,10 +270,10 @@ foreach my $tuple (
# countries that don't exist in libphonenumber
# FIXME unchecked
print $module_fh q{
$Number::Phone::Country::prefix_codes{VA} = ['379', '00', undef];
$Number::Phone::Country::prefix_codes{BV} = ['47', '00', undef];
$Number::Phone::Country::prefix_codes{GS} = ['500', '00', undef];
$Number::Phone::Country::prefix_codes{TF} = ['596', '00', '0' ];
$Number::Phone::Country::prefix_codes{AQ} = ['672', undef, undef];
$Number::Phone::Country::prefix_codes{PN} = ['872', undef, undef];
$Number::Phone::Country::prefix_codes{VA} = ['379', '00', undef, qr/\A 00 /xms];
$Number::Phone::Country::prefix_codes{BV} = ['47', '00', undef, qr/\A 00 /xms];
$Number::Phone::Country::prefix_codes{GS} = ['500', '00', undef, qr/\A 00 /xms];
$Number::Phone::Country::prefix_codes{TF} = ['596', '00', '0', qr/\A 00 /xms];
$Number::Phone::Country::prefix_codes{AQ} = ['672', undef, undef, undef];
$Number::Phone::Country::prefix_codes{PN} = ['872', undef, undef, undef];
};
62 changes: 57 additions & 5 deletions lib/Number/Phone/Country.pm
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ sub idd_code {
return $$data[1];
}

sub idd_regex {
my $country = uc shift;

my $data = $prefix_codes{$country} or return;

return $$data[3];
}

sub ndd_code {
my $country = uc shift;

Expand Down Expand Up @@ -224,11 +232,55 @@ it returns 44, and for Canada it returns 1.
=item idd_code($country)
Returns the International Direct Dialing prefix for the given country.
This is the prefix needed to make a call B<from a country> to another
country. This is followed by the country code for the country you are
calling. For example, when calling another country from the US, you must
dial 011.
Returns one, of possibly multiple, International Direct Dialing prefixes for
the given ISO Alpha-2 country code. Returns nothing if the country code is not
recognised or not supported.
The IDD prefix is needed to make a call B<from a country> to another country.
For example, when calling the UK from the US, the caller must first dial the
IDD prefix 011 to setup an international call, followed by the country calling
code for the UK (44), followed by the UK national number.
Many telephone systems allow the caller to dial a plus sign prefix
(+) in place of the IDD, in which case the system replaces the plus sign with
the correct IDD prefix for the caller's country.
Some countries have more than one IDD code, allowing the caller to route their
calls through specific networks. C<idd_code> only returns one code. See
C<idd_regex> if you need to match a number against known IDD prefixes for a
given country.
=item idd_regex($country)
Returns a regular expression that matches against known International Direct
Dialing prefixes for the given ISO Alpha-2 country code. Returns nothing if
the country code is not recognised or not supported.
As an example, the regular expression for Australia (AU) will match a number of
IDD prefixes, including 0011, 0014, and 0015, making it possible to determine
that 001516502530000 could be a US number being dialled from Australia.
Be aware that some numbers will match against IDD prefixes from multiple
countries. Other numbers will be valid national numbers for one country, and
valid international numbers when called for other countries. For example,
C<01143662111> is a valid national number for Sheffield, England. It could
also be a valid number in Austria:
Calling from within the UK:
Area code: 0114
Subscriber: 366 2111
National: 0114 366 2111
International: +441143662111
Calling from a country that uses the NANP (North American Numbering Plan):
IDD: 011
Country code: 43 (Austria)
Area code: 0662 (Salzburg)
Subscriber: 111
National: 0662 111
International: +43662111
=item ndd_code($country)
Expand Down
40 changes: 29 additions & 11 deletions t/number-phone-country-prefix.t
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ while (<DATA>) {
next if /^\s*#/;
next if /^\s*$/;

my ($country, $prefix, $idd, $ndd) = split /:/;
my ($country, $prefix, $idds, $ndd) = split /:/;
my ($idd, @other_idds) = split /;/, $idds;

$idd = undef unless length $idd;
$ndd = undef unless length $ndd;
Expand All @@ -31,13 +32,30 @@ while (<DATA>) {
is Number::Phone::Country::idd_code($country), $idd,
"$country idd prefix";

my $idd_re = Number::Phone::Country::idd_regex($country);

if (defined $idd) {
like $idd, qr/ $idd_re \z /xms,
"$country idd regex with preferred idd $idd";

like $_, qr/ $idd_re \z /xms,
"$country idd regex with other idd $_"
for @other_idds;
}
else {
is $idd_re, undef, "$country idd regex not available";
}

is Number::Phone::Country::ndd_code($country), $ndd,
"$country ndd prefix";
}

__END__
# data format is:
# ISO code:CC:IDD:NDD
# ...where IDD is the preferred IDD (as returned by idd_code), followed by zero
# or more alternative IDDs separated by semi-colons. The alternative IDDs
# lists are to test the idd regex, and are not complete.
AD:376:00:
AE:971:00:0
AF:93:00:0
Expand All @@ -51,7 +69,7 @@ AQ:672::
AR:54:00:0
AS:1:011:1
AT:43:00:0
AU:61:0011:0
AU:61:0011;0014;0015;0019:0
AW:297:00:
AZ:994:00:0
BA:387:00:0
Expand All @@ -66,7 +84,7 @@ BJ:229:00:
BM:1:011:1
BN:673:00:
BO:591:00:0
BR:55:0012:0
BR:55:0012;0014;0015;0021;0031;0041;0043:0
BS:1:011:1
BT:975:00:
BV:47:00:
Expand All @@ -84,7 +102,7 @@ CK:682:00:
CL:56:00:
CM:237:00:
CN:86:00:0
CO:57:009:0
CO:57:009;005;007:0
CR:506:00:
CU:53:119:0
CV:238:0:
Expand Down Expand Up @@ -129,14 +147,14 @@ GT:502:00:
GU:1:011:1
GW:245:00:
GY:592:001:
HK:852:00:
HK:852:00;001;002:
HN:504:00:
HR:385:00:0
HT:509:00:
HU:36:00:06
ID:62:001:0
ID:62:001;007;008;009:0
IE:353:00:0
IL:972:00:0
IL:972:00;012;013;014:0
IN:91:00:0
IO:246:00:
IQ:964:00:0
Expand All @@ -148,12 +166,12 @@ JO:962:00:0
JP:81:010:0
KE:254:000:0
KG:996:00:0
KH:855:001:0
KH:855:001;007:0
KI:686:00:
KM:269:00:
KN:1:011:1
KP:850:00:0
KR:82:001:0
KR:82:001;002;005;009:0
KW:965:00:
KY:1:011:1
KZ:7:810:8
Expand Down Expand Up @@ -228,7 +246,7 @@ SB:677:00:
SC:248:00:
SD:249:00:0
SE:46:00:0
SG:65:000:
SG:65:000;001;002;008:
SH:290:00:
SI:386:00:0
SJ:47:00:
Expand Down Expand Up @@ -257,7 +275,7 @@ TO:676:00:
TR:90:00:0
TT:1:011:1
TV:688:00:
TW:886:002:0
TW:886:002;005;006;007;009:0
TZ:255:000:0
UA:380:00:0
UG:256:000:0
Expand Down

0 comments on commit 39f8a36

Please sign in to comment.