Projektowanie stron WWW od podszewki

Artykuły na każdy temat

[PHP] Sprawdzenie poprawności numeru PESEL

Dodano 13.02.2012r. o 20:17
Nawiązując do ostatniej rozkminy w wirze wydarzeń chciałbym Wam przedstawić klasę napisaną w PHP, której celem jest walidacja numeru PESEL.

Kod jest zbudowany w taki sposób, aby łatwo można było go przenieść na inne języki. Nie krępujcie się i zmieniajcie dowoli, co Wam się żywnie podoba, aby wynikiem była jeszcze większa optymalizacja.
Kod:
<?php
// Dla czystości sumienia
set_time_limit(0);
$trafione_zatopione 0;

include './pesel.class.php';
$pesel = new pesel;

$black_hole get_time();

// Pozdro i poćwicz czyli mały test [3,1kk kombinacji -> i 310k prawidłowych (po równo dla obu płci czyli 155k dla kobiet i 155k dla mężczyzn)]
for($h 10100000$h <= 13199999; ++$h)
{
 $lotto fill_with_zeros($h11);

 if($pesel -> is_valid($lotto) === true)
 {
  $h += $pesel -> pesel[10];
  ++$trafione_zatopione;
  // Wycięte: date('d-m-Y', $pesel -> date)

  echo $lotto.' (Kto: '.($pesel -> get_gender() === true 'samica' 'samiec').', Pierwsze zalogowanie na świat: '.fill_with_zeros($pesel -> date[0], 2).'-'.fill_with_zeros($pesel -> date[1], 2).'-'.$pesel -> date[2].')<br>';
 }
 // Lub po prostu $pesel -> is_valid($lotto) dla samego "sprawdzenia wydajności"
}

// Lekkie przekłamanie?
echo 'Trafione: '.$trafione_zatopione.', Czas generowania: '.round((get_time() - $black_hole), 8).'s?';

/*
 * post scriptum:
 * 1) Używanie date() to bardzo głupi pomysł bo zaczynamy od 01-01-1970(?) kiedy daty PESELU zaczynają się od 01-01-1800
 * 2) Powyższy skrypt generuje prawidłowe PESEL'e dla dat pomiędzy 01-01-1900 i 31-01-1900
 * 3) Powyższy skrypt pakuje +20MB znaków do przęglądarki
 * 4) PHP w porównaniu do innych języków wysokiego poziomu jest bardzo niewydajny. Konsekwencje braku kompilacji muszą być.
 * 5) Przez pętle i inne fragmenty kodu "test sprawnościowy" będzie pokazywał wadliwe wyniki (najlepiej sprawdzać ile zajmuje wykonanie $pesel -> is_valid())
 * 6) Pełna nieskompresowana lista PESEL'i w sekwencji \d{11}\r\n zajmuję ~22GB -> [ciach]
 * 7) Umyślnie zapomniałem Smile
 */

function fill_with_zeros($bad_string$length)
{
 return str_pad($bad_string$length'0'STR_PAD_LEFT); // Where is a $good_string?
}

/*
function fill_with_zeros($bad_string, $length)
{
 // Liczymy długość
 $actual_length = strlen($bad_string);

 // Uzupełniamy jeżeli potrzeba
 if($actual_length < $length)
 {
  $bad_string = str_repeat('0', ($length - $actual_length)).$bad_string;
 }

 return $bad_string; // Where is a $good_string?
}
*/

function get_time()
{
 list($usec$sec) = explode(' 'microtime());

 return ((float)$usec + (float)$sec);
}

/* Dla przypomnienia:
 * Int32 -> Signed:
 * -2,147,483,648 do 2,147,483,647 -> od -(2^31) do (2^31) - 1
 * Int32 -> Unsigned
 * 0 do 4,294,967,295 -> 2^32 - 1
 * Int64 -> Signed
 * -9,223,372,036,854,775,808 do 9,223,372,036,854,775,807 -> od -(2^63) do (2^63) - 1
 * Int64 -> Unsigned
 * 0 do 18,446,744,073,709,551,615 -> (2^64) - 1
 */

/*-------------------------------------------+
 |                PHP_INT_MAX                |
 +---------------+---------------------------+
 |     32 bit    |          64 bit           |
 +---------------+---------------------------+
 | 2,147,483,647 | 9,223,372,036,854,775,807 |
 +---------------+---------------------------*/
?>
Plus źródło klasy:
Kod:
<?php
/**
 * @author: CapaciousCore
 * @version: 1.07
 */

class pesel
{
 public $pesel;
 public $date;
 private $weights = array(1379137913); // Zbędne jeżeli nie używamy opcji numer dwa w metodzie is_valid_check_sum()
 private $base_year;

 public function is_valid($pesel)
 {
  // Zbędne jeżeli ma się własną walidację
  if(preg_match('#^\d{11}$#'$pesel) === 0)
  {
   return false;
  }
  else
  {
   // Aby nie rzutować za każdym razem przy operacjach
   for($h 0$h 11; ++$h)
   {
    $this -> pesel[$h] = (int)$pesel[$h];
   }
  }

  // Walidacja PESEL'u bez sprawdzania daty nie ma sensu!
  return ($this -> is_valid_check_sum() === true && $this -> is_valid_date() === true);
 }

 public function get_gender()
 {
  // Przy założeniu, że podany PESEL jest poprawny (true oznacza kobietę, false oznacza mężczyznę)
  return ($this -> pesel[9] % === 0);
 }

 private function is_valid_check_sum()
 {
  $sum = (10 - (($this -> pesel[0] + $this -> pesel[1] + $this -> pesel[2] + $this -> pesel[3] + $this -> pesel[4] + $this -> pesel[5] + $this -> pesel[6] + $this -> pesel[7] + $this -> pesel[8] + $this -> pesel[9]) % 10)) % 10;

  /* Lub opcja numer dwa (szkoda CPU?)
  for($h = 0; $h < 10; $h++)
  {
   $sum += $this -> weights[$h] * $this -> pesel[$h];
  }

  $sum = 10 - $sum % 10;
  */

  return ($sum === $this -> pesel[10]);
 }

 private function is_valid_date()
 {
  $month $this -> get_birth_month();

  return ($this -> is_valid_month($month) === true && $this -> is_valid_day($month) === true);
 }

 private function is_valid_day($month)
 {
  $day $this -> get_birth_day();
  $year $this -> get_birth_year(); // Jeżeli ma służyć także wyświetlaniu daty to musi się ten zapis znaleźć tutaj
  $is_correct_date false;

  if($day 0)
  {
   if(($month === || $month === || $month === || $month === || $month === || $month === 10 || $month === 12) && $day 32)
   {
    $is_correct_date true;
   }
   else if(($month === || $month === || $month === || $month === 11) && $day 31)
   {
    $is_correct_date true;
   }
   else
   {
    $leap_year $this -> is_leap_year($year);

    if($leap_year === true)
    {
     if($day 30)
     {
      $is_correct_date true;
     }
    }
    else
    {
     if($day 29)
     {
      $is_correct_date true;
     }
    }
   }
  }

  if($is_correct_date === true)
  {
   // Wycięte (patrz index.php:30)
   // $this -> date = strtotime($day.'-'.$month.'-'.$year); // !ISO 8601 - Czy to najszybsza/najoptymalniejsza metoda?
   $this -> date = array($day$month$year);
  }

  return $is_correct_date;

  /* Lub
  $day = $this -> get_birth_day();
  $year = $this -> get_birth_year();

  return checkdate($month, $day, $year); // Ciekawe dlaczego nie taka (logiczniejsza) kolejność: $day, $month, $year? (Amerykański styl?)
  */
 }

 private function is_valid_month($month)
 {
  return ($month && $month 13);
 }

 private function get_birth_day()
 {
  return 10 $this -> pesel[4] + $this -> pesel[5];
 }

 private function get_birth_month()
 {
  $month 10 $this -> pesel[2] + $this -> pesel[3];

  if($month 80 && $month 93)
  {
   $month -= 80;
   $this -> base_year 1800;
  }
  else if($month 20 && $month 33)
  {
   $month -= 20;
   $this -> base_year 2000;
  }
  else if($month 40 && $month 53)
  {
   $month -= 40;
   $this -> base_year 2100;
  }
  else if($month 60 && $month 73)
  {
   $month -= 60;
   $this -> base_year 2200;
  }
  else
  {
   $this -> base_year 1900;
  }

  return $month;
 }

 private function get_birth_year()
 {
  return $this -> base_year 10 $this -> pesel[0] + $this -> pesel[1];
 }

 private function is_leap_year($year)
 {
  return (($year === && $year 100 !== 0) || ($year 400 === 0));
 }
}
?>

Komentarze

Publikowane komentarze są prywatnymi opiniami użytkowników serwisu. Serwis nie ponosi odpowiedzialności za treść opinii. W trosce o zachowanie poziomu dyskusji wszystkie komentarze podlegają akceptacji przed ich publikacją dlatego proszę cierpliwie czekać aż komentarz zostanie opublikowany.

Maciek M

Dodano 29.02.2016r. o 10:27
Polecam do testowania:
http://generatory.it/

CapaciousCore

Dodano 13.02.2012r. o 20:39
Proponuję także przeczytać ten wpis.

Dodaj komentarz

Zostaw komentarz jeżeli możesz! Nie bądź przysłowiowym botem! Nie bądź obojętny! Ciebie to nic nie kosztuje, a mi sprawi uśmiech na twarzy.
Zezwolono używać: BBCode
Zabroniono używać:
znaczników HTML

(Wymagany)

(Wymagany, niepublikowany)

(Nie wymagana)

Token:

Obrazek dla bota

(Przepisz tylko cyfry!)

(Wymagana)