NAME

Business::PT::CodigoPostal - Validação de códigos postais portugueses: distrito, região e localidades

VERSION

version 0.02

SYNOPSIS

use Business::PT::CodigoPostal qw(validate_cp localidades asignado);

my $cp = validate_cp('1000-001');

if ($cp->{valid}) {
    print $cp->{distrito};   # Lisboa
    print $cp->{region};     # Continente
}
else {
    print $cp->{error};
}

my @l = localidades('2100-049');   # Coruche
asignado('9999-999');              # 0

# interface OO
my $cp = Business::PT::CodigoPostal->new(codigo => '4000-001');
$cp->distrito;   # Porto
$cp->insular;    # 0
$cp->set('9000-001');

DESCRIPTION

Valida códigos postais portugueses no formato NNNN-NNN e devolve o distrito, a região e as localidades correspondentes.

O prefixo não chega

Em Espanha os dois primeiros dígitos do código postal são o número da província, por definição administrativa. Em Portugal não: o código postal é uma divisão de distribuição e não respeita as fronteiras dos distritos. O prefixo de dois dígitos é ambíguo em 25 dos 79 casos --- 20 tanto é Lisboa como Santarém.

Com quatro dígitos restam 13 prefixos ambíguos em 750, e esses resolvem-se com o código completo. É por isso que este módulo traz tabelas em vez de uma regra.

NAME

Business::PT::CodigoPostal - Validação de códigos postais portugueses

SUBROUTINES/METHODS

codigo

O código postal guardado no objecto, já normalizado para NNNN-NNN.

my $codigo = $cp->codigo;

distrito

O nome do distrito, em português e com acentos: Bragança, Setúbal, Évora, Açores.

my $distrito = $cp->distrito;

region

A região logística: Continente, Açores ou Madeira. O arquipélago paga portes à parte, tal como as Baleares ou as Canárias em Espanha.

my $region = $cp->region;

distrito_code

O número do distrito dentro da norma ISO 3166-2, sem o prefixo do país: '11' para Lisboa, '13' para o Porto.

my $code = $cp->distrito_code;

iso_3166_2

O código ISO 3166-2 completo: 'PT-11', 'PT-13', 'PT-20' para os Açores e 'PT-30' para a Madeira.

Os 18 distritos são PT-01 a PT-18 por ordem alfabética; as duas regiões autónomas quebram a série.

my $iso = $cp->iso_3166_2;

error

A mensagem de erro quando o código não é válido; undef quando é.

print $cp->error unless $cp->valid;

strict

Controla se a entrada se normaliza. Ligado por omissão, isto é, não normaliza.

$cp->strict(0);

valid

1 se o código postal é válido, 0 se não.

my $ok = $cp->valid;

validate_cp

my $r = validate_cp('1000-001');
my $r = validate_cp('1000001', { strict => 0 });   # normaliza

Devolve sempre uma referência a hash, nunca lança excepção. Com valid a 1 traz codigo, cp4, distrito e region; com valid a 0 traz error e as restantes chaves não existem.

strict está ligado por omissão e não normaliza a entrada. A 0 aceita o código sem hífen ou com espaços, que é o que faz falta ao processar ficheiros.

Atenção ao alcance: nos 737 prefixos inequívocos basta o prefixo para saber o distrito, e o sufixo não é verificado --- tal como Business::ES::CodigoPostal valida a gama e não o código concreto. Nos 13 prefixos que ficam entre dois distritos o sufixo tem de constar, porque sem ele não há maneira de decidir; aí um sufixo desconhecido devolve não atribuído. Para perguntar se um código completo existe, use "asignado".

distritos

my @d = distritos;   # ('Aveiro', 'Açores', 'Beja', ... 'Viseu')

Os 18 distritos mais as duas regiões autónomas, por ordem alfabética. Serve para montar uma lista de escolha sem ter de a manter à parte.

localidades

my @l = localidades('2100-049');   # ('Coruche')

Localidades do código postal, ordenadas. Lista vazia se não constar.

Os dados vivem em Business::PT::CodigoPostal::Localidades e carregam-se só ao chamar aqui: validar um código ou resolver o distrito não lhes toca.

asignado

asignado('1000-001');   # 1
asignado('1000-999');   # 0

Certo se o código postal está atribuído a alguma localidade. É uma verificação mais estreita do que valid: um código pode ter um prefixo real e um sufixo que nunca foi atribuído.

_normalize

Limpa a entrada quando strict está a 0: tira tudo o que não seja dígito e volta a pôr o hífen.

new

my $cp = Business::PT::CodigoPostal->new(codigo => '1000-001');
my $cp = Business::PT::CodigoPostal->new({ codigo => '1000001', strict => 0 });

set

Fixa um novo código postal. Devolve 1 se for válido, 0 se não.

insular

Certo se o código postal fica nos Açores ou na Madeira, que pagam portes à parte.

localidades / asignado como métodos

Ambas as funções aceitam também um objecto:

$cp->localidades;
$cp->asignado;

AUTHOR

HDELGADO <hdelgado@cpan.org>

FONTE DOS DADOS

Distritos, códigos postais e localidades de GeoNames (ficheiro export/zip/PT.zip), sob licença Creative Commons Attribution 4.0: https://creativecommons.org/licenses/by/4.0/.

VER TAMBÉM

Business::ES::CodigoPostal para códigos postais espanhóis.

LICENÇA

Copyright 2026 HDELGADO.

Software livre nos mesmos termos que o Perl. Os dados de localidades mantêm a sua própria licença (CC BY 4.0).

AUTHOR

HDELGADO <hdelgado@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by HDELGADO.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.