Na navigaci | Klávesové zkratky

Jak ověřit platné IČ a rodné číslo?

Víte, že rodné číslo nemusí být dělitelné 11? Že algoritmus ministerstva vnitra pro ověřování IČ je špatný? A že jej používá celá řada aplikací? A co na to Jan Tleskač?

Je užitečné, pokud aplikace (nejen webové) umí ověřit platnost různých identifikátorů, jako je třeba e-mail, rodné číslo, IČ a podobně. Naopak průseroidní je, když ověřovací algoritmus obsahuje chybu a digitální nepřítel pak tvrdošíjně odmítá vaše nacionále. Ukecat se nenechá, třísknout ho nemůžete.

Zrovna ohledně ověřování rodných čísel a IČ se obávám, že chybných bude většina implementací. Problém je v nedostatečném zdokumentování algoritmů, takže programátoři často spoléhají na neověřené informace. Jako skutečně kvalitní studnici vědění bych doporučil:

Hned si jej stáhněte!

Ověření rodného čísla

Začnu parafrází z pédéefka:

Do roku 1985 bylo přiděleno cca 1000 rodných čísel, která nejsou dělitelná 11. Není vyloučeno, že se v minimálním počtu vyskytly i po tomto roce.

Ale pozor, není to tím, že by úředníci na matrice byli trulanti! Dělitelnost jedenácti totiž bůh nikdy nesliboval. Algoritmus je ve skutečnosti následující:

  1. spočti zbytek po dělení prvních devíti číslic a čísla 11
  2. je-li zbytek 10, musí být poslední číslice 0
  3. jinak poslední číslice musí být rovna zbytku

Tedy 780123/3540 je korektní rodné číslo, ačkoliv není dělitelné jedenácti. No, nechtěl bych je mít, dovedu si představit ten všudypřítomný opruz 🙂

Implementace v PHP (gist):

function verifyRC($rc)
{
	// be liberal in what you receive
	if (!preg_match('#^\s*(\d\d)(\d\d)(\d\d)[ /]*(\d\d\d)(\d?)\s*$#', $rc, $matches)) {
		return false;
	}

	list(, $year, $month, $day, $ext, $c) = $matches;

	if ($c === '') {
		$year += $year < 54 ? 1900 : 1800;
	} else {
		// kontrolní číslice
		$mod = ($year . $month . $day . $ext) % 11;
		if ($mod === 10) $mod = 0;
		if ($mod !== (int) $c) {
			return false;
		}

		$year += $year < 54 ? 2000 : 1900;
	}

	// k měsíci může být připočteno 20, 50 nebo 70
	if ($month > 70 && $year > 2003) {
		$month -= 70;
	} elseif ($month > 50) {
		$month -= 50;
	} elseif ($month > 20 && $year > 2003) {
		$month -= 20;
	}

	// kontrola data
	if (!checkdate($month, $day, $year)) {
		return false;
	}

	return true;
}

Funkce se řídí heslem „buďte přísní v tom, co posíláte, a buďte velkorysí v tom, co přijímáte.“ Uživatel tak může zadat RČ i s lomítkem nebo mezerami.

Upozornění: např. 950101/123 je sice platné RČ osoby narozené v roce 1895, ale pravděpodobnější je, že chybí poslední číslice a číslo pak platné není.

Stejný systém rodných čísel používají i na Slovensku, takže kód mohou použít i bratia programátori.

Ověření IČ

Před lety jsem napsal webovou aplikaci pro jistou firmu, kde jsem použil ověřování platnosti IČO (tehdy ještě IČO, dnes už IČ). Vycházel jsem z algoritmu publikovaného na stránkách ministerstva vnitra. Jaké bylo překvapení, když si klient zkušebně zadal své vlastní IČO a aplikace mu oznámila, že je neplatné.

Dodnes toto IČO (25596641) používám k otestování aplikací, jestli také nepoužívají vadný algoritmus. A řeknu vám, většina neprojde.

Takže, jak se ověřuje IČ? Například 69663963

  1. první až sedmou číslici vynásobíme čísly 8, 7, 6, 5, 4, 3, 2 a součiny sečteme:

    soucet = 6*8 + 9*7 + 6*6 + 6*5 + 3*4 + 9*3 + 6*2 = 228

  2. spočítáme zbytek po dělení jedenácti: zbytek = soucet % 11
  3. pro poslední osmou číslici c musí platit:
    • je-li zbytek 0, pak c = 1
    • je-li zbytek 1, pak c = 0
    • v ostatních případech je c = 11 - zbytek

Implementace v PHP:

function verifyIC($ic)
{
	// be liberal in what you receive
	$ic = preg_replace('#\s+#', '', $ic);

	// má požadovaný tvar?
	if (!preg_match('#^\d{8}$#', $ic)) {
		return false;
	}

	// kontrolní součet
	$a = 0;
	for ($i = 0; $i < 7; $i++) {
		$a += $ic[$i] * (8 - $i);
	}

	$a = $a % 11;
	if ($a === 0) {
		$c = 1;
	} elseif ($a === 1) {
		$c = 0;
	} else {
		$c = 11 - $a;
	}

	return (int) $ic[7] === $c;
}

Přepis do JavaScriptu už nechám na vás. Můžete ho pastnout do komentářů.

před 17 lety v rubrice PHP | blog píše David Grudl | nahoru

Mohlo by vás zajímat

Komentáře

  1. BlackSUN #1

    avatar

    Díky za osvětu i za poskytnutí uvedených kódů, myslím, že se budou nejednomu programátorovi hodit.

    před 17 lety
  2. Pobert #2

    avatar

    Podobné to je i u bankovních účtů.
    informace o algoritmu jsou na stránkách ČNB – příloha vyhlášky 62/2004:
    V tuzemském platebním styku musí být první část čísla účtu a základní část čísla účtu
    samostatně zajištěny pomocí modulo 11 s váhami uvedenými v následující tabulce:
    Algoritmus kontroly čísla ABCDEFGHIJ na modulo 11
    Číslice A B C D E F G H I J
    Váhy 6 3 7 9 10 5 8 4 2 1
    n 10 9 8 7 6 5 4 3 2 1
    kde n je pozice číslice v čísle účtu (počítáno zprava)
    Váhy jsou získány jako rozdíl n-té mocniny 2 a nejbližšího nižšího násobku 11.
    Váhy se k číslicím na jednotlivých pozicích čísla účtu přiřazují zprava. Číslo ABCDEFGHIJ je zajištěno pomocí
    modulo 11, pokud je součet S beze zbytku dělitelný 11, přičemž
    S = J *1 + I *2 + H *4 + G *8 + F*5 + E*10 + D*9 + C*7 + B*3 + A *6

    A IBAN má také kotrolní číslice (první 2 čísla za kódem země)

    před 17 lety
  3. peCan #3

    avatar

    Taky jsem kdysi řešil kontrolu RČ a datum narození z něho. Když se na to teď tak dívám, taky to šlo řešit jednodušeji;-)

    před 17 lety
  4. Adam Šnobl #4

    Velmi dobře! Kontrolu IČ jsem (v Javě) implementoval dobře, ale o té specialitě u rodného čísla jsem nevěděl. To budu muset přepsat. Díky za upozornění!

    před 17 lety
  5. Pavel Jaroš #5

    avatar

    I já mám rád Zeleného Raoula, ale na internetu by otázka správně měla znít: Co na to RH? 😉

    před 17 lety
  6. marek #6

    avatar

    osobně se setkávám ještě s jednou vadou na kráse… má web s koncovkou .name , často narazímu zadávání emailu :(

    před 17 lety
  7. mANY #7

    Zcela mimo téma: „Vycházel jsem z algoritmu publikovaného na stránkách ministerstva vnitra.“

    před 17 lety
  8. Shaman #8

    Díky za užitečný článek. Skutečně se mi teď hodí.

    před 17 lety
  9. Morty #9

    avatar

    Jen tak pro zajímavost jsem si vyhledal co je to IČ zač.. zajímavé 🙂
    Jinak rozhodně přínosný článek.

    před 17 lety
  10. Piki #10

    Koho tieto algoritmy na tvorbu čísiel a hlavne prečo napadajú?

    před 17 lety | reagoval [12] zirafka [13] LLook [22] Jan Tichý
  11. Jakub Hejda #11

    Tééééda. to, že rodné číslo nemusí být dělitelné 11 beze zbytku jsem věděl. Ale ty ostatní informace jsou pro mne naprosto nové. Děkuji !

    před 17 lety
  12. zirafka #12

    avatar

    #10 Piki, Jedna se o tzv. samoopravne kody. Uz nejakou dobu se o nich chystam napsat clanek. Takhle bych se do toho uz konecne mohla pustit (-:

    před 17 lety | reagoval [18] hvge
  13. LLook #13

    avatar

    Vždycky jsem si lámal hlavu nad tím, jak byl asi u rodných čísel vyřešen problém Y2K. Teď už to vidím, ve skutečnosti jsou rodná čísla náchylná akorát k problému Y2K54…

    #10 Piki, Kontrolní mechanizmy jsou potřeba. Třeba u čísla účtu – představ si situaci, že posíláš peníze na zahraniční účet (drahá operace, která trvá strášně dlouho) a překlepneš se. Nebo příkaz podáváš přímo v bance a překlepne se úřednice… Možností je spousta.

    před 17 lety
  14. Mormegil #14

    No, když už se tady šťourá do těch velice okrajových případů, tak to chce dělat to důsledně (a to nemluvím o tom ? 200 : 1900 v kódu 😉 ). Přečtěte si třeba článek na Wikipedii a dozvíte se, že platnými rodnými čísly jsou také např. 0531135099 či 0681186066.

    A taky by vás mohlo zajímat, že na to, jak vypadá RČ, má zákon poněkud jiný názor než ISVS – viz § 13, odstavec 3 zákona 302/2004 Sb. A teď babo raď, že?

    před 17 lety | reagoval [25] David Grudl [40] Ondra
  15. David V. #15

    Díky moc za článek.
    Jak jsem zjistil, tak také v naší aplikaci máme chybu … Grrr ☹

    před 17 lety
  16. tracy #16

    avatar

    Vtipné je, že podle toho dokumentu je validní i e-mailová adresa a@b (tedy 3 znaky)…

    před 17 lety | reagoval [24] LLook [35] rony
  17. marty #17

    avatar

    marty…
    proc script pro RC?
    ja to taky programoval loni… 🙂
    potreboval jsem to do knihy paleni, kde se eviduji RC pro potrebu celniku. A musel jsem nejak kontrolovat zda obsluha zadala spravne RC.. 🙂

    před 17 lety
  18. hvge #18

    #12 zirafko, V tomto pripade sa kod skor len kontroluje. Dufam ze tam ale potom spomenieš aj moj oblubeny Golayov kod (perfect binary Golay code), s ktoreho tabulkami a rucnym pocitanim som sa onehda trapil na skuske z teorie kodovania :)

    ..inak pekny clanok, dufam ze to RČ plati aj u nas na SVK:)

    před 17 lety
  19. HoP #19

    A víte, že IČ nemusí mít 8 číslic ale i méně?

    před 17 lety | reagoval [25] David Grudl
  20. pixy #20

    Tak jako jo, Davide, trulant dobrej. Ale co furunkl? Ha?!

    před 17 lety | reagoval [25] David Grudl
  21. DFly #21

    no, spravuji system ktery eviduje urctou (dost velkou) skupinu obyvatel CR, a take jsem se musel vyporadat s RC…
    To ze modulo 11 funguje az od 10ti mistnych rodnych cisel je jeden z problemu (nekde to mam presne, ale je to od roku cca 1950), nicmene i v techto novych RC jsou nekdy nesystemove problemy, napr RC (ktere jsem i osobne overoval z rodneho listu) ktere neprojde kontrolou %11, nebo shodna RC (vznikalo to v dobe kdy porodnice meli malo cisel a volali do jine v okrese, aby jim dali nejaka prebyvajici, ale nakonec i tato se pouzila a pod. pripady)
    Takze nakonec system musi mit nejaky jiny unikatni kod, a po osobnim overeni musi mit flag, kterej deaktivuje hlaseni automaticke kontroly.

    před 17 lety | reagoval [25] David Grudl
  22. Jan Tichý #22

    avatar

    #10 Piki, Jsou to algoritmy, které zabezpečují číslo proti nejčastějším chybám, ke kterým dochází. V tomto případě tedy proti překlepu v jedné číslici a proti prohození dvou sousedních číslic.

    před 17 lety
  23. venca #23

    hmm…velmi zajmavé

    před 17 lety
  24. LLook #24

    avatar

    #16 tracy, A ona snad není validní? Co když zítra ICANN nějaké instituci přidělí doménu B? Je fakt, že podle toho dokumentu by nějaké nevalidní adresy prošly (třeba .@.), ale zrovna a@b je OK.

    před 17 lety
  25. David Grudl #25

    avatar

    #14 Mormegile, to je velmi dobrá připomínka, ale šlo by to sdělit méně kokotsky. Kód jsem upravil.

    #19 HoPe, nevíme. Máš nějaký příklad? Nebo nejde jen o opomenutí levostranných nul?

    #20 pixy, furunkl se udělal našemu pejskovi na nose, takže u mě splněno na 100 %. Co ty a Arthur? 😉

    #21 DFly, řadu věcí by ti mohl osvětlit tento článek

    před 17 lety | reagoval [26] DFly [41] HoP
  26. DFly #26

    #25 Davide Grudle, ten system jsem delal nekdy pred osmi lety, a shanel jsem spoustu informaci pres kamene ustavy nasich uradu – na webu toho moc nebylo
    k rodnym cislum: v tom systemu jsou dve RC na ktere nefunguje %11 a nekonci nulou (nejspis se nekdo uklepl na stroji, nebo podobny omyl – ale je to v rodnem liste, tak to musim brat jako OK)
    a shody RC mam overene 4
    dokonce by se dle RC mela dat poznat i porodnice, nebo alespon kraj(okres) pro ktere byli urcita cisla prirazena, jenze ono diky tomu predavani prebytecnych cisel tam kde jich byl nedostatek se dal urcit jen kraj – zkusim jeste prohledat svoje archivy, nekde budu mit podklady, podle kterych jsem to delal
    nevim jak je to ted s rozdavanim cisel, jestli se berou z nejakeho predgenerovaneho zasobniku, nebo jestli jeste plati to rozhazovani cisel na porodnice
    ten system bezi stale, a obcas ho dohleduju

    před 17 lety
  27. Arthur Dent #27

    Myslím, že bys měl především napsat Ruby verzi, té by se dostalo v komunitě jistě velmi vřelého přivítání.

    PS: Prohlížel jsem psa, furunkl žádnej, trulanty dva.

    před 17 lety
  28. DFly #28

    Takze ted jsem na neco koukal, a prvni dve cisla za lomitkem by meli znacit cislo porodnice a treti poradi (zvlast kluci i holky diky +50), ale kolik je na tom pravdy nevim – mozna to platilo drive…
    a Praha se taky bude mozna odlisovat, v rodine jsem si neco overoval a ne vsechno sedi (mozna ted se uz porodnice maji jina cisla nez pred 30 lety)
    a jestli je v republice do 98 porodnic netusim (typnul bych ze vice)
    99 za lomitkem znaci cizince ktery nema klasicke cislo z matriky

    před 17 lety | reagoval [29] karel [33] Věroš [36] zajDee
  29. karel #29

    #28 DFly, Já a můj brácha jsme se narodili ve stejné porodnici a první dvě čísla za lomítkem máme úplně jiná.

    Jinak na základě tvého pravopisu, používání interpunkce a diakritiky se mi moc nechce věřit, že jsi před osmi lety dělal nějaký systém pro rodná čísla, tipoval bych Tě na pubertální věk.

    před 17 lety | reagoval [30] DFly [34] Věroš
  30. DFly #30

    #29 karle, hmm, kdyz si to myslis, ja ti to vymlouvat nebudu…

    před 17 lety
  31. Black Wolf #31

    avatar

    Pěkný a užitečný článek, obzvláště to IČ se mi teď docela hodilo a pomohlo mi.

    Ovšem v tom RČ si myslím že je malá chybička – projde tím rč které je teoreticky správné, ale datum narození je v budoucnosti. Myslím že by to projít nemělo, když se jeho potenciální nositel ještě nenarodil;)

    před 17 lety | reagoval [32] David Grudl
  32. David Grudl #32

    avatar

    #31 Blacku Wolfe, jasně, projde tím i RČ, které má datum narození v minulosti, ale stejně nebylo nikomu přiděleno. Algoritmus ověřuje pouze formální platnost a můžeš si ho sám jakkoliv vylepšít.

    před 17 lety
  33. Věroš #33

    avatar

    #28 DFly, „Oh no a special case!“

    Já nejsem cizinec a poslední dvojčíslí mi končí na 99. 🙂

    před 17 lety | reagoval [36] zajDee
  34. Věroš #34

    avatar

    #29 karle, Čísla za lomítkem můžou být způsobená tím že jste se narodili před 1993 a po 1993, kdy se měnily čísla u porodnic nebo spoustou jiných důvodů (bordel na matrice, moc dětí narozených v jeden den, apod.)

    před 17 lety
  35. rony #35

    avatar

    #16 tracy, jojo, na mojom serveri „b“ mam mailbox „a“ 🙂

    před 17 lety
  36. zajDee #36

    avatar

    #33 Věroši, Ale #28 DFly psal o prvním dvojčíslí za lomítkem, ne?:-)

    Mé rodné číslo naštěstí projde ověřením na modulo 11, ale dokážu si představit problém, kdy někdo dostane číslo, které je úplně mimo ověření modulo 11 i modulo 10.

    A to nemluvím o číslech ze starších let, než 1953…

    (Pamatuju si, že babička musela někdy před deseti lety dohledávat své správné rodné číslo přes několik matrik, měla v té době dvě – naštěstí potkala pracovité úředníky, takže se povedlo a dnes už má své správné rodné číslo s trojčíslím za lomítkem:-))

    před 17 lety | reagoval [39] Věroš
  37. Martin Bumba #37

    avatar

    Zdravím prosím už to někdo přepsal do JS potřeboval bych to v JS a moc se me to nechce prepisovat díky :).

    před 17 lety
  38. FiJi #38

    Ale pozor, není to tím, že by úředníci na matrice byli trulanti!
    Dělitelnost jedenácti totiž bůh nikdy nesliboval. Algoritmus je
    ve skutečnosti následující:
    spočti zbytek po dělení prvních devíti číslic a čísla 11
    je-li zbytek 10, musí být poslední číslice 0
    jinak poslední číslice musí být rovna zbytku

    Současný zákon dělitelnost 11 ale slibuje a i podle popisu na wikipedii to vypadá, že chyba je opravdu spíš v tom algoritmu.

    Možná by taky stálo za to doplnit do článku, kde se tam vzalo těch 20 a 70, to myslím taky není obecně známo…

    před 17 lety
  39. Věroš #39

    avatar

    #36 zajDee, Omlouvám se za překlep. – Samozřejmě poslední čtyřčíslí mi začíná 99.

    před 17 lety
  40. Ondra #40

    #14 Mormegile, Moje prababička se narodila v roce 1898 a teď ji nechtěl přijmout praktický lékař, protože novorozence pojišťovna hradí jen lékařům dětským.

    před 17 lety
  41. HoP #41

    #25 Davide Grudle, Příklad nemám, někdo mi o tom vyprávěl, bohužel sem tomu nevěnoval moc pozornost, protože to nebyla věc, která by mne nějak znepokojovala. Zkusím to zjistit.

    před 17 lety | reagoval [42] HoP
  42. HoP #42

    #41 HoPe, Tak jsem zkusil najít ten příklad a zjistil jsem, že měli v databázi pouze špatně zadané IČ, tzn. že jim vypadla jedna číslice… Takže se omlouvám za mystifikaci, IČ má skutečně 8 číslic, případě je doplněno nulami.

    před 17 lety
  43. Vlasta #43

    avatar

    Validace RC je zajimavy problem. Jen tak pro zajimavost, co se z RC da vycist.

    mesic + 50 = zana
    den + 50 = cizinec, zijici v CR

    Pro zadavani a validaci RC jsem udelal Reg vyraz, ktery zohlednuje i prestupny rok. Tak to vyzkousejte a dejte vedet, jak se vam to chova.

    regex = new Regex(@„^(((^\d?$)|(^\d{2}$)|(^\d{2}(0|1|5|6)$)|(^\d{2}(0|5)[1–9]$)|(^\d{2}(1|6)[0–2]$)|(^\d{2}(01|51)[01235678]$)|(^\d{2}(02|52)[smazáno]$)|(^\d{2}(03|53)[01235678]$)|(^\d{2}(04|54)[01235678]$)|(^\d{2}(05|55)[01235678]$)|(^\d{2}(06|56)[01235678]$)|(^\d{2}(07|57)[01235678]$)|(^\d{2}(08|58)[01235678]$)|(^\d{2}(09|59)[01235678]$)|(^\d{2}(10|60)[01235678]$)|(^\d{2}(11|61)[01235678]$)|(^\d{2}(12|62)[01235678]$)|(^\d{2}(010|020|030|040|050|060|070|080|090|100|110|120)[1–9]$)|(^\d{2}(015|025|035|045|055|065|075|085|095|105|115|125)[1–9]$)|(^\d{2}(510|520|530|540|550|560|570|580|590|600|610|620)[1–9]$)|(^\d{2}(515|525|535|545|555|565|575|585|595|605|615|625)[1–9]$)|(^\d{2}(011|021|031|041|051|061|071|081|091|101|111|121)[0–9]$)|(^\d{2}(016|026|036|046|056|066|076|086|096|106|116|126)[0–9]$)|(^\d{2}(511|521|531|541|551|561|571|581|591|601|611|621)[0–9]$)|(^\d{2}(516|526|536|546|556|566|576|586|596|606|616|626)[0–9]$)|(^\d{2}(012|032|042|052|062|072|082|092|102|112|122)[0–9]$)|(^\d{2}(017|037|047|057|067|077|087|097|107|117|127)[0–9]$)|(^\d{2}(512|532|542|552|562|572|582|592|602|612|622)[0–9]$)|(^\d{2}(517|537|547|557|567|577|587|597|607|617|627)[0–9]$)|(^\d{2}(013|033|053|073|083|103|123)[smazáno]$)|(^\d{2}(018|038|058|078|088|108|128)[smazáno]$)|(^\d{2}(513|533|553|573|583|603|623)[smazáno]$)|(^\d{2}(518|538|558|578|588|608|628)[smazáno]$)|(^\d{2}(043|063|093|113)[smazáno]$)|(^\d{2}(048|068|098|118)[smazáno]$)|(^\d{2}(543|563|593|613)[smazáno]$)|(^\d{2}(548|568|598|618)[smazáno]$)|(^\d{2}(022|027|522|527)[0–8]$)|(^(00022|00027|00522|00527|04022|04027|04522|04527|08022|08027|08522|08527)[0–9]$)|(^(12022|12027|12522|12527|16022|16027|16522|16527)[0–9]$)|(^(20022|20027|20522|20527|24022|24027|24522|24527|28022|28027|28522|28527)[0–9]$)|(^(32022|32027|32522|32527|36022|36027|36522|36527)[0–9]$)|(^(40022|40027|40522|40527|44022|44027|44522|44527|48022|48027|48522|48527)[0–9]$)|(^(52022|52027|52522|52527|56022|56027|56522|56527)[0–9]$)|(^(60022|60027|60522|60527|64022|64027|64522|64527|68022|68027|68522|68527)[0–9]$)|(^(72022|72027|72522|72527|76022|76027|76522|76527)[0–9]$)|(^(80022|80027|80522|80527|84022|84027|84522|84527|88022|88027|88522|88527)[0–9]$)|(^(92022|92027|92522|92527|96022|96027|96522|96527)[0–9]$))|(^\d{6}[0–9]{1,4}))$“);

    před 17 lety
  44. David Grudl #44

    avatar

    Přepis do JavaScriptu mi poslal Filip Oščádal

    function testICO(x)
    {
      try
      {
        var a = 0;
        if(x.length == 0) return true;
        if(x.length != 8) throw 1;
        var b = x.split('');
        var c = 0;
        for(var i = 0; i < 7; i++) a += (parseInt(b[i]) * (8 - i));
        a = a % 11;
        c = 11 - a;
        if(a == 1) c = 0;
        if(a == 0) c = 1;
        if(a == 10) c = 1;
        if(parseInt(b[ 7]) != c) throw(1);
      }
      catch(e)
      {
        alert('Zadaný údaj není korektní!');
        return false;
      }
      return true;
    }
    function testRC(x, age)
    {
      if(!age) age = 0;
      try
      {
        if(x.length == 0) return true;
        if(x.length < 9) throw 1;
        var year = parseInt(x.substr(0, 2), 10);
        var month = parseInt(x.substr(2, 2), 10);
        var day = parseInt( x.substr(4, 2), 10);
        var ext = parseInt(x.substr(6, 3), 10);
        if((x.length == 9) && (year < 54)) return true;
        var c = 0;
        if(x.length == 10) c = parseInt(x.substr(9, 1));
        var m = parseInt( x.substr(0, 9)) % 11;
        if(m == 10) m = 0;
        if(m != c) throw 1;
        year += (year < 54) ? 2000 : 1900;
        if((month > 70) && (year > 2003)) month -= 70;
        else if (month > 50) month -= 50;
        else if ((month > 20) && (year > 2003)) month -= 20;
        var d = new Date();
        if((year + age) > d.getFullYear()) throw 1;
        if(month == 0) throw 1;
        if(month > 12) throw 1;
        if(day == 0) throw 1;
        if(day > 31) throw 1;
      }
      catch(e)
      {
        alert('Zadaný údaj není korektní!');
        return false;
      }
      return true;
    }
    function testDIC(x)
    {
      try
      {
        if(x.length == 0) return true;
        var id = x.substr(0, 2).toUpperCase();
        x = x.substr(2);
        if((id == 'CZ') || (id == 'SK'))
        {
          if(x.length < 8) throw 1;
          if(x.length > 11) throw 1;
          if(x.length == 8)
          {
            return testICO(x);
          }
          else
          {
            return testRC(x, 18);
          }
          throw 1;
        }
        alert('Není možné zkontrolovat DIČ mimo Českou a Slovenskou republiku!');
        return true;
      }
      catch(e)
      {
        alert('Zadaný údaj není korektní!');
        return false;
      }
    }

    …to be continued

    před 17 lety
  45. David Grudl #45

    avatar

    (pokračování řešení od Filipa Oščádala)

    • jako správnou hodnotu skript bere i prázdnou hodnotu (viz. modře označené řádky), test na prázdnou hodnotu by mělo dělat PHP
    • test rodného čísla lze podmínit i na věk osoby (testuje se jen rok, pro přesnost by bylo nutné porovnávat čas v sekundách)
    • test na validitu data je jen přibližný (netestuje se přestupný rok a 30./31. den v měsíci)

    příklad použití:

    <input onblur="if(!testRC(this.value)) this.focus();"
      name="rc" size="10" value="" maxlength="10" type="text">
    
    <input onblur="if(!testICO(this.value)) this.focus();"
      name="ico" size="8" value="" maxlength="8" type="text">
    
    <input onblur="if(!testDIC(this.value)) this.focus();"
      onclick="if(this.value.length < 2) this.value = 'CZ';"
      name="dic" size="13" value="" maxlength="13" type="text">

    (test DIČ využívá testů IČO a RČ)

    před 17 lety
  46. Marian Cerny #46

    avatar

    Pri overovani RC to nie je uplne dotiahnute. Ak je RC 9 miestne a rok < 54, mala by este nasledovat kontrola datumu pomocou checkdate().

    před 17 lety
  47. Peca #47

    avatar

    Nevím, jestli si to tu někdo ještě přečte, ale kdyby náhodou… Asi ten algoritmus pořád není správně, nebo existují firmy s IČ, která nejsou správně vygenerovaná. Např. tohle: 72343976 (http://wwwinfo.mfcr.cz/…es_subjx.cgi?…)

    před 17 lety

Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.


phpFashion © 2004, 2024 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.