Pobieranie daty urodzenia i płci z numeru PESEL - Javascript
Każdy obywatel w naszym pięknym kraju musi być ewidencjonowany. Jak dobrze wiemy imię i nazwisko nie są niepowtarzalne. Imieniem i nazwiskiem posługujemy się w kontaktach międzyludzkich. Dla aparatu państwowego jesteśmy numerkiem, który zwykło się nazywać numerem PESEL, od pierwszych liter systemu zwanego Powszechnym Elektronicznym Systemem Ewidencji Ludności. Tak prawdę mówiąc nie jest to jedyny numerek obywatela w sile wieku. Dostajemy potem także serię i numer dowodu osobistego, NIP, niektórzy otrzymają REGON. Co jakiś czas pojawiają się pomysły likwidacji niektórych numerków (np. rozliczając PIT w 2012 roku można już się posługiwać tylko numerem PESEL, NIP nie jest już do tego potrzebny), ale pewnie prędko to nie nastąpi.
Warto wiedzieć (większość pewnie o tym wie), że w numerze PESEL zaszyte są informacje o dacie urodzenia oraz o płci, a sam numer posiada sumę kontrolną służącą do weryfikacji poprawności. Pomyłka w jednej cyfrze nie będzie zatem groźna, bo może to zostać z łatwością wykryte. Ze względu na posób liczenia sumy kontrolnej nie będzie też groźne przestawienie dwóch sąsiednich cyfr.
Co znajduje się w numerze PESEL
Jak wspomniałem, w numerze PESEL znajduje się kilka informacji dodatkowych, które mogą nam się przydać. Są to:
- Rok urodzenia - pierwsze dwie cyfry z uwzględnieniem trzeciej cyfry
- Miesiąc urodzenia - trzecia i czwarta cyfra, po odliczeniu części związanej z rokiem
- Dzień urodzenia - piąta i szósta cyfra
- Płeć urodzenia - dziesiąta cyfra
Dokładniejszego wyjaśnienia wymaga trzecia cyfra, która jest współdzielona przez rok i miesiąc. Zastanówmy się, co oznaczałyby cyfry 21 na pierwszych dwóch miejscach. Automatycznie, choć już nie tak bardzo jak jeszcze kilka lat temu, przychodzi odpowiedź: 1921 rok. Co jednak zrobimy, gdy nastanie rok 2021? Trik polega na pożyczeniu części cyfry trzeciej. Wiemy, że miesięcy jest 12 i więcej nie będzie. Trzecia cyfra ma wobec tego mnóstwo wolnych, niezagospodarowanych wartości, tj. od 2 do 9. Nie wchodząc w filozoficzne rozważania:
- Jeżeli trzecia cyfra jest równa 0 lub 1, do roku dodajemy 1900
- Jeżeli trzecia cyfra jest równa 2 lub 3, do roku dodajemy 2000
- Jeżeli trzecia cyfra jest równa 4 lub 5, do roku dodajemy 2100
- Jeżeli trzecia cyfra jest równa 6 lub 7, do roku dodajemy 2200
- Jeżeli trzecia cyfra jest równa 8 lub 9, do roku dodajemy 1800
Co będziemy robić w roku 2300? Jest to pewien problem, ale mamy trochę czasu na znalezienie rozsądnego rozwiązania.
Dziesiątkę miesiąca można wydobyć w dużo łatwiejszy sposób. Jeżeli trzecia cyfra jest parzysta, wtedy będzie to 0 (miesiące 1-9), a jeżeli nieparzysta, wtedy będzie to 1 (miesiące 10-12). Wydaje się to proste.
Parzystość i nieparzystość przydaje się też do określenia płci obywatela. Jeżeli dziesiąta cyfra jest parzysta, będzie to kobieta, a jeżeli nieparzysta - mężczyzna.
Suma kontrolna
Wpisując w różne formularze kulkanaście cyfr łatwo się pomylić. Aby mocno ograniczyć ilość popełnianych błędów do różnych numerów wprowadza się sumy kontrolne. Mamy sumę kontrolną w numerach kont bankowych, ale mamy też w numerze PESEL. Jak się ją liczy? Każda kolejna cyfra numeru PESEL ma swoją wagę. Policzenie sumy kontrolnej sprowadza się zatem do zsumowania kolejnych iloczynów cyfry i wagi przypisanej tej cyfrze. Przypuśćmy, że Ci oznacza cyfrę na pozycji i. Suma kontrolna będzie liczona w następujący sposób:
Z tak otrzymanej sumy iloczynów należy uzyskać resztę z dzielenia przez 10. W wyniku takiej operacji otrzymamy cyfrę od 0 do 9. Nazwijmy ją sobie D. Następnie należy od liczby 10 odjąć D. Niech E będzie naszą różnicą E = 10 - D. Jeżeli otrzymamy 10, to sumą kontrolną wpisywaną na ostatniej pozycji numeru PESEL jest 0, jeżeli nie, wpisujemy wartość E.
Sposób jest nieco zagmatwany, ale istnieje metoda alternatywna. Nie będę przedstawiał matematycznego dowodu równoważności, ale sama weryfikacja wyraźnie się upraszcza. Jeżeli nie musimy wyliczać sumy kontrolnej, możemy wliczyć ją do sumy iloczynów nadając jej wagę 1. Wyrażenie przybierze następującą postać:
Po wyliczeniu wyrażenia wystarczy sprawdzić, czy reszta z dzielenia, czyli ostatnie cyfra, jest równa 0. Jeżeli jest - PESEL jest poprawny. Jeżeli nie - jest błędny.
Przykład wykorzystania danych PESEL na stronie HTML
Przykład będzie prosty. Umieszczę na stronie kilka pól do wpisywania danych osobowych: PESEL, rok urodzenia, miesiąc urodzenia, dzień urodzenia i płeć (M/K). Zadanie polega na tym, aby po wpisaniu i zweryfikowaniu numeru pesel automatycznie usupełniły się pozostałe pola. Przykład pokazany jest na poniższym listingu:
<head>
<script type="text/javascript">
function ParsePesel(id)
{
var s = document.getElementById(id).value;
//Sprawdź długość, musi być 11 znaków
if (SetError(s.length != 11))
return;
//Sprawdź, czy wszystkie znaki to cyfry
var aInt = new Array();
for (i=0;i<11; i++)
{
aInt[i] = parseInt(s.substring(i,i+1));
if (isNaN(aInt[i]))
{
SetError(1);
return;
}
}
//Sprawdź sumę kontrolną
var wagi = [1,3,7,9,1,3,7,9,1,3,1];
var sum=0;
for (i=0;i<11;i++)
sum+=wagi[i]*aInt[i];
if (SetError((sum%10)!=0))
return;
//Policz rok z uwzględnieniem XIX, XXI, XXII i XXIII wieku
var rok = 1900+aInt[0]*10+aInt[1];
if (aInt[2]>=2 && aInt[2]<8)
rok+=Math.floor(aInt[2]/2)*100;
if (aInt[2]>=8)
rok-=100;
var miesiac = (aInt[2]%2)*10+aInt[3];
var dzien = aInt[4]*10+aInt[5];
//Sprawdź poprawność daty urodzenia
if (SetError(!checkDate(dzien,miesiac,rok)))
return;
var plec = (aInt[9]%2==1)?"M":"K";
//Uzupełnij pola wchodzące w skład numeru PESEL
document.getElementById("rok").value = rok;
document.getElementById("miesiac").value = miesiac;
document.getElementById("dzien").value = dzien;
document.getElementById("plec").value = plec;
}
function SetError(c){
document.getElementById("hasError").style.visibility=(c?"visible":"hidden");
return c;
}
function checkDate(d,m,y)
{
var dt = new Date(y,m-1,d);
return dt.getDate()==d &&
dt.getMonth()==m-1 &&
dt.getFullYear()==y;
}
</script>
</head>
<body onload="ParsePesel('pesel');">
<table>
<tr><td>PESEL:</td><td><input id="pesel" type="text" onkeyup="ParsePesel('pesel');"/>
<span id="hasError" style="color:Red;" title="Nieprawidłowy numer PESEL">*</span></td></tr>
<tr><td>Rok:</td><td><input id="rok" type="text"/></td></tr>
<tr><td>Miesiac:</td><td><input id="miesiac" type="text"/></td></tr>
<tr><td>Dzień:</td><td><input id="dzien" type="text"/></td></tr>
<tr><td>Płeć:</td><td><input id="plec" type="text"/></td></tr>
</table>
</body>
</html>
Przykład działania aplikacji
Popatrzmy, w jaki sposób zachowuje się nasz skrypt i jak działa. Minimalnie przerobiona wersja (zaprezentowany przykład to cała strona HTML, my potrzebujemy umieścić ją w ramach innej) pokazana jest poniżej:
PESEL: | * |
Rok: | |
Miesiac: | |
Dzień: | |
Płeć: |
Objaśnienia i podsumowanie
Myślę, że kod nie wymaga większych wyjaśnień. Do sprawdzenia poprawności daty napisałem funkcję checkDate. Zaskakiwać może to, że od miesiąca odejmowana jest liczba 1. Jest to trochę dziwne, że dni numerowane są od 1 a miesiące od 0, ale tak już jest i trudno z tym polemizować. Do ustawiania czerwonej gwiazdki informującej o błędzie służy funkcja SetError. Jeżeli warunek przekazywany jako argument jest spełniony, czerwona gwiazdka pojawia się. Zwracana wartość logiczna służy tylko temu, aby zapis był bardziej zgrabny. Po wyświetleniu gwiazdki przebieg algorytmu jest zatrzymywamy (if(SetError(...)) return;), bo nie ma potrzeby sprawdzać dalej. Funkcja sprawdzająca numer PESEL wykonuje się po załadowaniu strony (onload, wersja na tej stronie nie obsługuje tego zdarzenia) oraz po wpisaniu lub usunięciu dowolnego znaku (onkeyup) w polu PESEL.
Mam nadzieję, że podane przeze mnie rozwiązanie będzie przydatne. Konkretne potrzeby z pewnością wymuszą drobne modyfikacje zaprezentowanego przykładu. Jest to tylko fundament, na którym można się oprzeć. W przypadku pytań i niejasności, błędów lub niedopatrzeń z mojej strony, proszę o ślad w postaci komentarza.
Kategoria:HTMLJavaScript
Komentarze:
Date(Date.UTC(rok, miesiac - 1, dzien))