Artykuły na każdy temat
[PHP] Sprawdzenie poprawności numeru PESEL
<?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($h, 11);
if($pesel -> is_valid($lotto) === true)
{
$h += 9 - $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
*/
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:
<?php
/**
* @author: CapaciousCore
* @version: 1.07
*/
class pesel
{
public $pesel;
public $date;
private $weights = array(1, 3, 7, 9, 1, 3, 7, 9, 1, 3); // 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] % 2 === 0);
}
private function is_valid_check_sum()
{
$sum = (10 - ((1 * $this -> pesel[0] + 3 * $this -> pesel[1] + 7 * $this -> pesel[2] + 9 * $this -> pesel[3] + 1 * $this -> pesel[4] + 3 * $this -> pesel[5] + 7 * $this -> pesel[6] + 9 * $this -> pesel[7] + 1 * $this -> pesel[8] + 3 * $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 === 1 || $month === 3 || $month === 5 || $month === 7 || $month === 8 || $month === 10 || $month === 12) && $day < 32)
{
$is_correct_date = true;
}
else if(($month === 4 || $month === 6 || $month === 9 || $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 > 0 && $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 % 4 === 0 && $year % 100 !== 0) || ($year % 400 === 0));
}
}
?>
Komentarze
Dodaj komentarz
Maciek M
http://generatory.it/