[Lugge] Re: formattazione tabella SQL

  • From: "Zingus J. Rinkle" <1999s039@xxxxxxxxxxxxxxxxxx>
  • To: lugge@xxxxxxxxxxxxx
  • Date: Fri, 8 Nov 2002 01:55:40 +0100

Sciupando l'imperdibile occasione di evitare una mia risposta,
Dixie disse:
> 
> >
> > >-) una per controllare i codici fiscali, se qualcuno sa come
> > >controllarne la coerenza,
> > >(mi han detto che le ultime cifre sono un digest del resto,
> > >ma non ne sono sicuro...)
> >
> > no, io sapevo che le ultime 5 (1 char + 3 int + 1 char) sono relative al
> > comune in cui sei nato, e al sesso; infatti ho molti amici che hanno D969*
> > come ultime cifre del CF. Cmq fare il check non è difficile, la menata è
> > appunto avere una lista di comuni aggiornata per verificarne l'esattezza;
> > il resto del codice si ricava facilmente da nome+cognome+data_di_nascita,
> > anche se esistono dei CF (ma sono davvero pochissimi) che non rispettano
> > appieno l'algoritmo (credo che sia perchè ogni tanto si sarebbero generati
> > dei doppioni)
> 
> Scusa se mi intrometto.
> L'ultima cifra è un check digit che serve a differenziare l'eventuale
> presenza di omonimia (stesso nome, cognome, sesso, data e comune di nascita)
> che effettivamente possono esistere.
> Le tre cifre precedenti identificano il comune e l'elenco si può trovare sul
> sito del ministero delle finanze.
> Esistono dei piccoli script in PHP che svolgono il controllo (basta fare una
> piccola ricerca in rete e ne troverete a bizzeffe).
Mhh... L'argomento suscita interesse, vedo.

Allora, ho fatto delle ricerche ed ecco il risultato:
http://www.olografix.org/isazi/dnfcrew/scritti/codicefiscale.html

Il linguaggio e` pure troppo colorito, ma i contenuti sono
abbastanza coerenti...

In sostanza risolve la diatriba in modo salomonico: nessuno di
voi ha ragione. :-) Il sesso viene ascritto al giorno del mese
di nascita, aggiungendo un 40 a capocchia per le femmine...
I penultimi 4 caratteri (una lettera e tre cifre) identificano
il comune di nascita.  L'ultima lettera e` una checksum. I casi
di omonimia non sono trattati, AFAIK, con buona pace dei Mario
Rossi da Roma. Il codice fiscale e` obsoleto, non y2k compliant,
e scomodo da calcolare sia per un umano che per una macchina.
Ed il fatto che in molte basi di dati esso venga usato come
chiave primaria, fa rabbrividire...

Ora il punto e`: il succitato documento e` ragionevolmente accurato?

Dato che a leggerlo e basta non lo capivo, indovinate cosa
ho fatto?  Il solito script del cavolo, bravi. In allegato,
al solito. In perl, al solito. Giratelo su di un po' di codici
fiscali noti, ed in caso di incongruenze fatemelo sapere...

NB: gestisce poche citta`: le principali. Non ho preso i codici
dal ministero, ma dall'articolo indicato...

Hint: "cfisc --man" vi sara` utile...

Quanto al check in una tavola pgsql...
Ne riparliamo un'altra volta. :-)

Buoni Codici,
Zingus

-- 
  _________  +-------------------------------------------------------+
\/   _____/ /  http://as0.da.ru                       icq: 164939262 |
ZJR _____/ |  mailto:zingus_at_fuckmicrosoft.com                     |
/\______/  +-------------------------------------- Zingus J. Rinkle -+
#!/usr/bin/perl

#########################################################################
#   Copyright (C) 2002  Zingus J. Rinkle                                #
#########################################################################

use warnings;
use Getopt::Long;
use Pod::Usage;

my $man  = 0;
my $help = 0;

GetOptions(
    'help|?' => sub { pod2usage(1) },
    man      => sub { pod2usage( -exitstatus => 0, -verbose => 2 ) }
  )
  or pod2usage(2);

sub cfisc {
    my ( $nome, $cognome, $nascita, $comune, $sesso ) = @_;
    my $cod = "";
    local $_;

    # TABELLA CODICI CITTÀ 
    %comuni = (
        'ANCONA'          => 'A271',
        'AOSTA'           => 'A326',
        'AREZZO'          => 'A390',
        'ASCOLI PICENO'   => 'A462',
        'ASTI'            => 'A479',
        'BARI'            => 'A662',
        'BERGAMO'         => 'A794',
        'BOLOGNA'         => 'A944',
        'BRESCIA'         => 'B157',
        'BUSTO ARSIZIO'   => 'B300',
        'CAGLIARI'        => 'B354',
        'CAMPOBASSO'      => 'B519',
        'CATANIA'         => 'C351',
        'CATANZARO'       => 'C352',
        'COMO'            => 'C933',
        'FERRARA'         => 'D584',
        'FIRENZE'         => 'D616',
        'GALLARATE'       => 'D869',
        'GENOVA'          => 'D969',
        'IMPERIA'         => 'E290',
        'LA SPEZIA'       => 'E469',
        'LECCE'           => 'E506',
        'MILANO'          => 'F205',
        'NAPOLI'          => 'F839',
        'PALERMO'         => 'F273',
        'PAVIA'           => 'G388',
        'PERUGIA'         => 'G478',
        'PESCARA'         => 'G482',
        'PISA'            => 'G702',
        'POTENZA'         => 'G942',
        'REGGIO CALABRIA' => 'G224',
        'ROMA'            => 'H501',
        'SIRACUSA'        => 'H754',
        'TORINO'          => 'I219',
        'TRENTO'          => 'L378',
        'TRIESTE'         => 'L424',
        'UDINE'           => 'L483',
        'VENEZIA'         => 'L736',
        'VERONA'          => 'L781'
    );

    # TABELLA VALORI CARATTERI PARI 
    %pari = (
        '0' => 0,
        '1' => 1,
        '2' => 2,
        '3' => 3,
        '4' => 4,
        '5' => 5,
        '6' => 6,
        '7' => 7,
        '8' => 8,
        '9' => 9,
        'A' => 0,
        'B' => 1,
        'C' => 2,
        'D' => 3,
        'E' => 4,
        'F' => 5,
        'G' => 6,
        'H' => 7,
        'I' => 8,
        'J' => 9,
        'K' => 10,
        'L' => 11,
        'M' => 12,
        'N' => 13,
        'O' => 14,
        'P' => 15,
        'Q' => 16,
        'R' => 17,
        'S' => 18,
        'T' => 19,
        'U' => 20,
        'V' => 21,
        'W' => 22,
        'X' => 23,
        'Y' => 24,
        'Z' => 25
    );

    # TABELLA VALORI CARATTERI DISPARI 
    %dispari = (
        '0' => 1,
        '1' => 0,
        '2' => 5,
        '3' => 7,
        '4' => 9,
        '5' => 13,
        '6' => 15,
        '7' => 17,
        '8' => 19,
        '9' => 21,
        'A' => 1,
        'B' => 0,
        'C' => 5,
        'D' => 7,
        'E' => 9,
        'F' => 13,
        'G' => 15,
        'H' => 17,
        'I' => 19,
        'J' => 21,
        'K' => 2,
        'L' => 4,
        'M' => 18,
        'N' => 20,
        'O' => 11,
        'P' => 3,
        'Q' => 6,
        'R' => 8,
        'S' => 12,
        'T' => 14,
        'U' => 16,
        'V' => 10,
        'W' => 22,
        'X' => 25,
        'Y' => 24,
        'Z' => 23
    );

    # TABELLA VALORI LETTERA DI CONTROLLO 
    %controllo = (
        0  => 'A',
        1  => 'B',
        2  => 'C',
        3  => 'D',
        4  => 'E',
        5  => 'F',
        6  => 'G',
        7  => 'H',
        8  => 'I',
        9  => 'J',
        10 => 'K',
        11 => 'L',
        12 => 'M',
        13 => 'N',
        14 => 'O',
        15 => 'P',
        16 => 'Q',
        17 => 'R',
        18 => 'S',
        19 => 'T',
        20 => 'U',
        21 => 'V',
        22 => 'W',
        23 => 'X',
        24 => 'Y',
        25 => 'Z'
    );

    @mesi = (
        'A',    ## Please see file perltidy.ERR
        'B', 'C', 'D', 'E', 'H', 'L', 'M', 'P', 'R', 'S', 'T'
    );
    %mons = (
        'gen' => 0,
        'feb' => 1,
        'mar' => 2,
        'apr' => 3,
        'mag' => 4,
        'giu' => 5,
        'lug' => 6,
        'ago' => 7,
        'set' => 8,
        'ott' => 9,
        'nov' => 10,
        'dic' => 11
    );

    # estraiamo le lettere notevoli dal nome e dal cognome
    my $i;
    for ( $cognome, $nome ) {
        my $abbrev;
        s/(.*)/\U$1/g;
        my @consonanti = /([^AEIOU])/g;
        if ( ( scalar @consonanti ) >= 4 and $i++ ) {
            $abbrev .= $consonanti[0] . $consonanti[2] . $consonanti[3];
        }
        else {
            $abbrev .= $consonanti[0] . $consonanti[1] . $consonanti[2];
        }
        $abbrev .= /([AEIOU])/ if length $abbrev < 3;    # prima_vocale
        $abbrev .= 'X' while length $abbrev < 3;
        $cod .= $abbrev;
    }

    # parsiamo, analizziamo ed elaboriamo data e sesso
    my ( $mday, $mon, $year ) =
      $nascita =~
/(\d{2})[\s\/-]*(\d{2}|gen|feb|mar|apr|mag|giu|lug|ago|set|ott|nov|dic)[\s\/-]*\d{2}(\d{2})/i;
    $mon = $mons{ lc $mon }
      if $mon =~ /[a-z]*/;
    my $d = $mday + ( ( $sesso =~ /F/i ) ? 40 : 0 );
    $cod .= $year . $mesi[$mon] . ( ( $d < 10 ) ? "0$d" : $d );

    # aggiungiamo il codice del comune
    $cod .= $comuni{ uc $comune };

    # elaboriamo l'improbabile checksum
    my $sum = 0;
    @cpari    = $cod =~ m/.(.)/g;
    @cdispari = $cod =~ m/(.)./g;
    push @cdispari, $cod =~ m/(.)$/g;

    for $c (@cpari) {
        $sum += $pari{$c};
    }
    for $c (@cdispari) {
        $sum += $dispari{$c};
    }
    $cod .= $controllo{ $sum % 26 };

    print $cod;
}
$\ = "\n";
pod2usage(2) if scalar @ARGV < 5;
cfisc @ARGV;

__END__

=head1 NAME

cfisc - calcola il codice fiscale di un privato cittadino
        dello stato italiano. Forse.

=head1 SYNOPSIS

cfisc NOME COGNOME DATA_DI_NASCITA COMUNE SESSO

=head1 ARGUMENTS

=head2 NOME e COGNOME

si spiegano da soli.

=head2 DATA_DI_NASCITA

Data in formati tipo: "20-02-2002","20/02/2002","20 feb 2002"
et similia...

=head2 COMUNE

Comune di nascita.

=head2 SESSO

`m' per maschio od `f' per femmina...

=head1 OPTIONS

=head2 -?,--help

        Aiuto online.

=head2 --man

        Manuale.

=head1 BUGS

Questo programma e` limitato, fatto male e probabilmente
non funziona :-(

Other related posts: