Spis treści:

Kategoria:HTMLJavaScript


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:

C1 + 3C2 + 7C3 + 9C4 + C5 + 3C6 + 7C7 + 9C8 + C9 + 3C10

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ć:

C1 + 3C2 + 7C3 + 9C4 + C5 + 3C6 + 7C7 + 9C8 + C9 + 3C10 + C11

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.

Warto wiedzieć, że w obiegu istnieją błędne numery PESEL. Według informacji MSWIA błędy pojawiają się w wielu miejscach - w dacie urodzenia, w numerze porządkowym (cyfry 7-9), w płci, a także w sumie kontrolnej. Weryfikację numeru PESEL należy traktować bardziej jako informację, a nie jak warunek konieczny skorzystania z naszej usługi, jakakolwiek by ona nie była.

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:

<html>
<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="peseltype="textonkeyup="ParsePesel('pesel');"/>
<span id="hasErrorstyle="color:Red;title="Nieprawidłowy numer PESEL">*</span></td></tr>
<tr><td>Rok:</td><td><input id="roktype="text"/></td></tr>
<tr><td>Miesiac:</td><td><input id="miesiactype="text"/></td></tr>
<tr><td>Dzień:</td><td><input id="dzientype="text"/></td></tr>
<tr><td>Płeć:</td><td><input id="plectype="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

, 2013-12-20

Komentarze:

Marcin (2014-03-04 13:21:54)
Tego szukałem, dzięki!
SLAJM (2014-06-12 13:33:12)
Bardzoo dzieki
Mariusz (2015-02-27 08:10:30)
Super, dzięki:)
urzędnik (2015-10-16 10:55:25)
dzięki, korzystam z tego w pracy,
Kamil (2016-02-25 12:11:28)
Siema, tu macie fajny generator: http://generatory.it/
uio (2016-10-21 18:16:02)
a gdzie kot
qqqq (2017-02-05 14:32:59)
Parsowanie daty może przysporzyć problemów ponieważ nie uwzględnia strefy czasowej. O ile skrypt nie komunikuje się z backendem to nie ma problemu, ale w przeciwnym wypadku urodzenia wyciągnięta na podstawie peselu zapisze się w bazie ze złą strefą czasową. Obiekt daty należałoby utworzyć jako:
Date(Date.UTC(rok, miesiac - 1, dzien))
Maciej (2018-03-06 14:17:50)
Genialne w swojej prostocie. Dzielnie się wiedza jest złotem, dziękuję!
Dodaj komentarz
Wyślij
Ostatnie komentarze
chcę dodać kolumnę, która będzie połączeniem dwóch innych istniejących już kolumn, jak powinien wyglądać scrypt?
Przydałyby się jeszcze 2 rzeczy do cz. 3 i byłoby superanckie.
1. Na starcie sortuje wg jakiejś kolumny i tam jest już strzałeczka. Widok takiej strzałeczki daje znać użytkownikowi, że taką tabele można sortować, a na razie pojawia się ona tylko po kliknięciu.
2. Uwzględnienie polskich znaków, bo np. przy sortowaniu Nazwisk i Imion jest to bardzo uciążliwe.
Ogólnie bardzo fajnie i prosto.
PS. Jest ten artykuł z jQuery już dostępny.
bardo ciekawe , można dzięki takim wpisom dostrzec wędkę..
Bardzo dziękuję za jasne tłumaczenie z dobrze dobranym przykładem!