Number::Phone::PT - Validate Portuguese phone numbers


Number-Phone-PT documentation Contained in the Number-Phone-PT distribution.

Index


Code Index:

NAME

Top

Number::Phone::PT - Validate Portuguese phone numbers

SYNOPSIS

Top

  use Number::Phone::PT;

  $number = 258374162;

  print "$number is valid" if is_valid($number);

  print "$number belongs to a home" if is_residential($number);

  print "$number is a celular phone" if is_mobile($number);

  print "$number belongs to someone" if is_personal($number);
  # same thing as ( is_residential($number) or is_mobile($number) )

  print "$number is from " . area_of($number) if is_residential($number);

DESCRIPTION

Top

Validates Portuguese phone numbers. Does not check whether they exist or not; it just validates to see if they are well written.

Special numbers (as the emergency number 112, for instance), are currently not comtemplated.

PORTUGUESE PHONE NUMBERS

Top

There are three kinds of telephone numbers in Portugal (currently): residential, mobile and service numbers.

All of these numbers are composed of nine digits.

RESIDENTIAL NUMBERS

Residential numbers always start with the digit 2. The first few digits identify the region it belongs to. Here is the list (note that the function area_of may return accentuated words):

21 lisboa
22 porto
231 mealhada
232 viseu
233 figueira da foz
234 aveiro
235 arganil
236 pombal
238 seia
239 coimbra
241 abrantes
242 ponte de sor
243 santarem
244 leiria
245 portalegre
249 torres novas
251 valenca
252 vila nova de famalicao
253 braga
254 peso da regua
255 penafiel
256 sao joao da madeira
258 viana do castelo
259 vila real
261 torres vedras
263 caldas da rainha
265 setubal
266 evora
268 estremoz
269 santiago do cacem
271 guarda
272 castelo branco
273 braganca
274 proenca-a-nova
275 covilha
276 chaves
277 idanha-a-nova
278 mirandela
279 moncorvo
281 tavira
282 portimao
283 odemira
284 beja
285 moura
286 castro verde
289 faro
291 funchal, porto santo
292 corvo, faial, flores, horta, pico
295 angra do heroismo, graciosa, sao jorge, terceira
296 ponta delgada, sao miguel, santa maria

MOBILE NUMBERS

Mobile numbers always start with the digit 9. The first two digits identify the operator it belongs to. Here is the list:

91 Vodafone / Yorn
93 Optimus
96 TMN

SERVICE NUMBERS

Service numbers start with 707, 760, 800 or 808 (currently). Please refer to Portugal Telecom in order to know how they work, as they change from time to time.

707 numero unico
760 numero unico
800 numero gratis
808 chamada local

MESSAGE FROM THE AUTHOR

Top

If you're using this module, please drop me a line to my e-mail. Tell me what you're doing with it. Also, feel free to suggest new bugs^H^H^H^H^H features.

AUTHOR

Top

Jose Alves de Castro, <cog [at] cpan [dot] org<gt>

COPYRIGHT AND LICENSE

Top


Number-Phone-PT documentation Contained in the Number-Phone-PT distribution.
package Number::Phone::PT;

use 5.006;
use strict;
use warnings;

require Exporter;

our @ISA = qw(Exporter);

our %EXPORT_TAGS = ( 'all' => [ qw(
	is_valid is_residential is_mobile is_personal area_of
) ] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw(
	is_valid is_residential is_mobile is_personal area_of
);

our $VERSION = '0.05';

my %indicativos;
my %special;

BEGIN {
  %indicativos = (
    21  => 'lisboa',
    22  => 'porto',
    231 => 'mealhada',
    232 => 'viseu',
    233 => 'figueira da foz',
    234 => 'aveiro',
    235 => 'arganil',
    236 => 'pombal',
    238 => 'seia',
    239 => 'coimbra',
    241 => 'abrantes',
    242 => 'ponte de sôr',
    243 => 'santarém',
    244 => 'leiria',
    245 => 'portalegre',
    249 => 'torres novas',
    251 => 'valença',
    252 => 'vila nova de famalicão',
    253 => 'braga',
    254 => 'peso da régua',
    255 => 'penafiel',
    256 => 'são joão da madeira',
    258 => 'viana do castelo',
    259 => 'vila real',
    261 => 'torres vedras',
    262 => 'caldas da raínha',
    263 => 'vila franca de xira',
    265 => 'setúbal',
    266 => 'évora',
    268 => 'estremoz',
    269 => 'santiago do cacém',
    271 => 'guarda',
    272 => 'castelo branco',
    273 => 'bragança',
    274 => 'proença-a-nova',
    275 => 'covilhã',
    276 => 'chaves',
    277 => 'idanha-a-nova',
    278 => 'mirandela',
    279 => 'moncorvo',
    281 => 'tavira',
    282 => 'portimão',
    283 => 'odemira',
    284 => 'beja',
    285 => 'moura',
    286 => 'castro verde',
    289 => 'faro',
    291 => 'funchal, porto santo',
    292 => 'corvo, faial, flores, horta, pico',
    295 => 'angra do heroísmo, graciosa, são jorge, terceira',
    296 => 'ponta delgada, são miguel, santa maria',

    91  => 'rede móvel 91 (Vodafone / Yorn)',
    93  => 'rede móvel 93 (Optimus)',
    96  => 'rede móvel 96 (TMN)',

    707 => 'número único',
    760 => 'número único',
    800 => 'número grátis',
    808 => 'chamada local',
  );

  %special = (  # currently unused (yet)
    # Telefones úteis
    120		=> 'Chamadas Nacionais a Pagar no Destino',
    120		=> 'PT Multivozes',
    16200	=> 'Serviço a Clientes',
    12161	=> 'Despertar',
    1583	=> 'Telegramas Nacional',
    16208	=> 'Assistência Técnica',
    # Serviços de informações
    118		=> 'Serviço Informativo Nacional',
    12150	=> 'Meteorologia',
    12151	=> 'Horas',
    12153	=> 'Notícias',
    12157	=> 'Desporto',
    12158	=> 'Lotaria, Totobola e Totoloto',
    # Internacional
    171		=> 'Chamadas com Assistência',
    177		=> 'Listas Telefónicas Internacionais',
    179	=> 'Informações Gerais sobre o Serviço Telefónico Internacional',
    1582	=> 'Telegramas Internacional',
  );
}

sub is_valid {
  $_ = shift || return 0;
  unless (/^\d{9}$/) { return 0 }

  for my $ind (keys %indicativos) {
    /^$ind/ && return 1;
  }

  return 0
}

sub is_personal {
  is_mobile(@_) or is_residential(@_);
}

sub is_mobile {
  is_valid(@_) || return 0;
  $_ = shift || return 0;
  for my $ind (grep /^9/, keys %indicativos) {
    /^$ind/ && return 1;
  }
  return 0
}

sub is_residential {
  is_valid(@_) || return 0;
  $_ = shift || return 0;
  for my $ind (grep /^2/, keys %indicativos) {
    /^$ind/ && return 1;
  }
  return 0
}

sub area_of {
  is_valid(@_) || return 0;
  $_ = shift || return 0;
  for my $ind (grep /^2/, keys %indicativos) {
    /^$ind/ && return $indicativos{$ind};
  }
  return 0;
}

1;
__END__