stdnum 1.10.0 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/no/fodselsnummer.js +2 -2
- package/lib/esm/no/fodselsnummer.js +2 -2
- package/package.json +5 -2
- package/src/ad/index.ts +1 -0
- package/src/ad/nrt.spec.ts +36 -0
- package/src/ad/nrt.ts +87 -0
- package/src/al/index.ts +1 -0
- package/src/al/nipt.spec.ts +43 -0
- package/src/al/nipt.ts +111 -0
- package/src/ar/cbu.spec.ts +28 -0
- package/src/ar/cbu.ts +96 -0
- package/src/ar/cuit.spec.ts +28 -0
- package/src/ar/cuit.ts +102 -0
- package/src/ar/dni.spec.ts +22 -0
- package/src/ar/dni.ts +72 -0
- package/src/ar/index.ts +3 -0
- package/src/at/businessid.spec.ts +34 -0
- package/src/at/businessid.ts +73 -0
- package/src/at/index.ts +4 -0
- package/src/at/tin.spec.ts +173 -0
- package/src/at/tin.ts +140 -0
- package/src/at/uid.spec.ts +44 -0
- package/src/at/uid.ts +84 -0
- package/src/at/vnr.spec.ts +38 -0
- package/src/at/vnr.ts +84 -0
- package/src/au/abn.spec.ts +28 -0
- package/src/au/abn.ts +78 -0
- package/src/au/acn.spec.ts +34 -0
- package/src/au/acn.ts +76 -0
- package/src/au/index.ts +3 -0
- package/src/au/tfn.spec.ts +28 -0
- package/src/au/tfn.ts +79 -0
- package/src/az/index.ts +2 -0
- package/src/az/pin.spec.ts +16 -0
- package/src/az/pin.ts +61 -0
- package/src/az/tin.spec.ts +28 -0
- package/src/az/tin.ts +64 -0
- package/src/ba/index.ts +1 -0
- package/src/ba/jmbg.spec.ts +28 -0
- package/src/ba/jmbg.ts +85 -0
- package/src/be/bis.spec.ts +184 -0
- package/src/be/bis.ts +85 -0
- package/src/be/index.ts +4 -0
- package/src/be/insz.spec.ts +51 -0
- package/src/be/insz.ts +55 -0
- package/src/be/nn.spec.ts +117 -0
- package/src/be/nn.ts +77 -0
- package/src/be/personIdentifierHelpers.spec.ts +254 -0
- package/src/be/personIdentifierHelpers.ts +130 -0
- package/src/be/vat.spec.ts +46 -0
- package/src/be/vat.ts +84 -0
- package/src/bg/egn.spec.ts +28 -0
- package/src/bg/egn.ts +75 -0
- package/src/bg/index.ts +3 -0
- package/src/bg/pnf.spec.ts +28 -0
- package/src/bg/pnf.ts +73 -0
- package/src/bg/vat.spec.ts +34 -0
- package/src/bg/vat.ts +120 -0
- package/src/br/cnpj.spec.ts +34 -0
- package/src/br/cnpj.ts +89 -0
- package/src/br/cpf.spec.ts +34 -0
- package/src/br/cpf.ts +87 -0
- package/src/br/index.ts +2 -0
- package/src/by/index.ts +1 -0
- package/src/by/unp.spec.ts +34 -0
- package/src/by/unp.ts +108 -0
- package/src/bz/index.ts +1 -0
- package/src/bz/tin.spec.ts +28 -0
- package/src/bz/tin.ts +67 -0
- package/src/ca/bn.spec.ts +40 -0
- package/src/ca/bn.ts +88 -0
- package/src/ca/gst.spec.ts +34 -0
- package/src/ca/gst.ts +70 -0
- package/src/ca/index.ts +5 -0
- package/src/ca/pst.spec.ts +28 -0
- package/src/ca/pst.ts +71 -0
- package/src/ca/qst.spec.ts +47 -0
- package/src/ca/qst.ts +88 -0
- package/src/ca/sin.spec.ts +34 -0
- package/src/ca/sin.ts +72 -0
- package/src/ch/index.ts +3 -0
- package/src/ch/ssn.spec.ts +50 -0
- package/src/ch/ssn.ts +74 -0
- package/src/ch/uid.spec.ts +34 -0
- package/src/ch/uid.ts +82 -0
- package/src/ch/vat.spec.ts +28 -0
- package/src/ch/vat.ts +83 -0
- package/src/cl/index.ts +2 -0
- package/src/cl/run.ts +13 -0
- package/src/cl/rut.spec.ts +50 -0
- package/src/cl/rut.ts +97 -0
- package/src/cn/index.ts +2 -0
- package/src/cn/ric.spec.ts +34 -0
- package/src/cn/ric.ts +86 -0
- package/src/cn/uscc.spec.ts +34 -0
- package/src/cn/uscc.ts +110 -0
- package/src/co/index.ts +1 -0
- package/src/co/nit.spec.ts +40 -0
- package/src/co/nit.ts +85 -0
- package/src/cr/cpf.spec.ts +34 -0
- package/src/cr/cpf.ts +93 -0
- package/src/cr/cpj.spec.ts +28 -0
- package/src/cr/cpj.ts +111 -0
- package/src/cr/cr.spec.ts +28 -0
- package/src/cr/cr.ts +75 -0
- package/src/cr/index.ts +3 -0
- package/src/cu/index.ts +1 -0
- package/src/cu/ni.spec.ts +34 -0
- package/src/cu/ni.ts +74 -0
- package/src/cy/index.ts +1 -0
- package/src/cy/vat.spec.ts +28 -0
- package/src/cy/vat.ts +98 -0
- package/src/cz/dic.spec.ts +28 -0
- package/src/cz/dic.ts +127 -0
- package/src/cz/index.ts +2 -0
- package/src/cz/rc.spec.ts +44 -0
- package/src/cz/rc.ts +95 -0
- package/src/de/idnr.spec.ts +34 -0
- package/src/de/idnr.ts +91 -0
- package/src/de/index.ts +6 -0
- package/src/de/passport.spec.ts +31 -0
- package/src/de/passport.ts +86 -0
- package/src/de/pwnr.spec.ts +62 -0
- package/src/de/pwnr.ts +190 -0
- package/src/de/stnr.spec.ts +85 -0
- package/src/de/stnr.ts +193 -0
- package/src/de/svnr.spec.ts +56 -0
- package/src/de/svnr.ts +158 -0
- package/src/de/vat.spec.ts +28 -0
- package/src/de/vat.ts +74 -0
- package/src/dk/cpr.spec.ts +34 -0
- package/src/dk/cpr.ts +129 -0
- package/src/dk/cvr.spec.ts +28 -0
- package/src/dk/cvr.ts +81 -0
- package/src/dk/index.ts +2 -0
- package/src/do/cedula.spec.ts +34 -0
- package/src/do/cedula.ts +67 -0
- package/src/do/index.ts +3 -0
- package/src/do/ncf.spec.ts +34 -0
- package/src/do/ncf.ts +133 -0
- package/src/do/rnc.spec.ts +40 -0
- package/src/do/rnc.ts +74 -0
- package/src/dz/index.ts +1 -0
- package/src/dz/nif.spec.ts +39 -0
- package/src/dz/nif.ts +80 -0
- package/src/ec/ci.spec.ts +28 -0
- package/src/ec/ci.ts +92 -0
- package/src/ec/index.ts +2 -0
- package/src/ec/ruc.spec.ts +37 -0
- package/src/ec/ruc.ts +117 -0
- package/src/ee/ik.spec.ts +28 -0
- package/src/ee/ik.ts +114 -0
- package/src/ee/index.ts +3 -0
- package/src/ee/kmkr.spec.ts +28 -0
- package/src/ee/kmkr.ts +76 -0
- package/src/ee/registrikood.spec.ts +28 -0
- package/src/ee/registrikood.ts +80 -0
- package/src/eg/index.ts +1 -0
- package/src/eg/tn.spec.ts +44 -0
- package/src/eg/tn.ts +96 -0
- package/src/es/cif.spec.ts +43 -0
- package/src/es/cif.ts +84 -0
- package/src/es/dni.spec.ts +28 -0
- package/src/es/dni.ts +83 -0
- package/src/es/index.ts +5 -0
- package/src/es/nie.spec.ts +28 -0
- package/src/es/nie.ts +79 -0
- package/src/es/nif.spec.ts +52 -0
- package/src/es/nif.ts +95 -0
- package/src/es/nss.spec.ts +28 -0
- package/src/es/nss.ts +132 -0
- package/src/exceptions.ts +66 -0
- package/src/fi/alv.spec.ts +28 -0
- package/src/fi/alv.ts +76 -0
- package/src/fi/hetu.spec.ts +37 -0
- package/src/fi/hetu.ts +108 -0
- package/src/fi/index.ts +3 -0
- package/src/fi/ytunnus.spec.ts +28 -0
- package/src/fi/ytunnus.ts +49 -0
- package/src/fo/index.ts +1 -0
- package/src/fo/vn.spec.ts +34 -0
- package/src/fo/vn.ts +71 -0
- package/src/fr/index.ts +5 -0
- package/src/fr/nif.spec.ts +34 -0
- package/src/fr/nif.ts +82 -0
- package/src/fr/nir.spec.ts +36 -0
- package/src/fr/nir.ts +98 -0
- package/src/fr/siren.spec.ts +28 -0
- package/src/fr/siren.ts +68 -0
- package/src/fr/siret.spec.ts +38 -0
- package/src/fr/siret.ts +79 -0
- package/src/fr/tva.spec.ts +40 -0
- package/src/fr/tva.ts +125 -0
- package/src/gb/index.ts +3 -0
- package/src/gb/nino-prefixes.ts +245 -0
- package/src/gb/nino.spec.ts +80 -0
- package/src/gb/nino.ts +80 -0
- package/src/gb/utr.spec.ts +28 -0
- package/src/gb/utr.ts +76 -0
- package/src/gb/vat.spec.ts +40 -0
- package/src/gb/vat.ts +112 -0
- package/src/gen/ean.spec.ts +34 -0
- package/src/gen/ean.ts +71 -0
- package/src/gen/index.ts +1 -0
- package/src/gh/index.ts +1 -0
- package/src/gh/tin.spec.ts +42 -0
- package/src/gh/tin.ts +93 -0
- package/src/gn/index.ts +1 -0
- package/src/gn/nifp.spec.ts +40 -0
- package/src/gn/nifp.ts +72 -0
- package/src/gr/amka.spec.ts +28 -0
- package/src/gr/amka.ts +76 -0
- package/src/gr/index.ts +2 -0
- package/src/gr/vat.spec.ts +34 -0
- package/src/gr/vat.ts +84 -0
- package/src/gt/cui.spec.ts +34 -0
- package/src/gt/cui.ts +110 -0
- package/src/gt/index.ts +2 -0
- package/src/gt/nit.spec.ts +34 -0
- package/src/gt/nit.ts +86 -0
- package/src/hk/hkid.spec.ts +52 -0
- package/src/hk/hkid.ts +90 -0
- package/src/hk/index.ts +1 -0
- package/src/hr/index.ts +1 -0
- package/src/hr/oib.spec.ts +28 -0
- package/src/hr/oib.ts +67 -0
- package/src/hu/anum.spec.ts +28 -0
- package/src/hu/anum.ts +71 -0
- package/src/hu/index.ts +1 -0
- package/src/id/index.ts +1 -0
- package/src/id/npwp.spec.ts +34 -0
- package/src/id/npwp.ts +116 -0
- package/src/ie/index.ts +2 -0
- package/src/ie/pps.spec.ts +58 -0
- package/src/ie/pps.ts +81 -0
- package/src/ie/vat.spec.ts +40 -0
- package/src/ie/vat.ts +99 -0
- package/src/il/hp.spec.ts +38 -0
- package/src/il/hp.ts +75 -0
- package/src/il/idnr.spec.ts +28 -0
- package/src/il/idnr.ts +70 -0
- package/src/il/index.ts +2 -0
- package/src/in/aadhaar.spec.ts +40 -0
- package/src/in/aadhaar.ts +85 -0
- package/src/in/epic.spec.ts +34 -0
- package/src/in/epic.ts +85 -0
- package/src/in/gstin.spec.ts +34 -0
- package/src/in/gstin.ts +156 -0
- package/src/in/index.ts +4 -0
- package/src/in/pan.spec.ts +40 -0
- package/src/in/pan.ts +93 -0
- package/src/index.ts +404 -0
- package/src/is/index.ts +2 -0
- package/src/is/kennitala.spec.ts +46 -0
- package/src/is/kennitala.ts +80 -0
- package/src/is/vsk.spec.ts +22 -0
- package/src/is/vsk.ts +60 -0
- package/src/it/aic.spec.ts +40 -0
- package/src/it/aic.ts +97 -0
- package/src/it/codicefiscale.spec.ts +28 -0
- package/src/it/codicefiscale.ts +167 -0
- package/src/it/index.ts +3 -0
- package/src/it/iva.spec.ts +28 -0
- package/src/it/iva.ts +65 -0
- package/src/jp/cn.spec.ts +28 -0
- package/src/jp/cn.ts +77 -0
- package/src/jp/index.ts +1 -0
- package/src/ke/index.ts +1 -0
- package/src/ke/pin.spec.ts +34 -0
- package/src/ke/pin.ts +77 -0
- package/src/kr/brn.spec.ts +28 -0
- package/src/kr/brn.ts +91 -0
- package/src/kr/index.ts +2 -0
- package/src/kr/rrn.spec.ts +34 -0
- package/src/kr/rrn.ts +104 -0
- package/src/li/index.ts +1 -0
- package/src/li/peid.spec.ts +22 -0
- package/src/li/peid.ts +71 -0
- package/src/lt/asmens.spec.ts +28 -0
- package/src/lt/asmens.ts +73 -0
- package/src/lt/index.ts +2 -0
- package/src/lt/pvm.spec.ts +34 -0
- package/src/lt/pvm.ts +75 -0
- package/src/lu/index.ts +1 -0
- package/src/lu/tva.spec.ts +28 -0
- package/src/lu/tva.ts +70 -0
- package/src/lv/index.ts +1 -0
- package/src/lv/pvn.spec.ts +44 -0
- package/src/lv/pvn.ts +102 -0
- package/src/ma/ice.spec.ts +39 -0
- package/src/ma/ice.ts +72 -0
- package/src/ma/ice9.spec.ts +28 -0
- package/src/ma/ice9.ts +62 -0
- package/src/ma/index.ts +2 -0
- package/src/mc/index.ts +1 -0
- package/src/mc/tva.spec.ts +28 -0
- package/src/mc/tva.ts +67 -0
- package/src/md/idno.spec.ts +28 -0
- package/src/md/idno.ts +78 -0
- package/src/md/index.ts +1 -0
- package/src/me/index.ts +2 -0
- package/src/me/jmbg.ts +17 -0
- package/src/me/pib.spec.ts +158 -0
- package/src/me/pib.ts +77 -0
- package/src/mk/edb.spec.ts +50 -0
- package/src/mk/edb.ts +88 -0
- package/src/mk/index.ts +2 -0
- package/src/mk/jmbg.ts +17 -0
- package/src/mt/index.ts +1 -0
- package/src/mt/vat.spec.ts +28 -0
- package/src/mt/vat.ts +69 -0
- package/src/mu/index.ts +1 -0
- package/src/mu/nid.spec.ts +34 -0
- package/src/mu/nid.ts +89 -0
- package/src/mx/banks.ts +658 -0
- package/src/mx/clabe.spec.ts +68 -0
- package/src/mx/clabe.ts +105 -0
- package/src/mx/curp.spec.ts +28 -0
- package/src/mx/curp.ts +261 -0
- package/src/mx/index.ts +3 -0
- package/src/mx/rfc.spec.ts +69 -0
- package/src/mx/rfc.ts +193 -0
- package/src/my/index.ts +1 -0
- package/src/my/nric.spec.ts +40 -0
- package/src/my/nric.ts +91 -0
- package/src/nl/bsn.spec.ts +68 -0
- package/src/nl/bsn.ts +81 -0
- package/src/nl/btw.spec.ts +40 -0
- package/src/nl/btw.ts +95 -0
- package/src/nl/index.ts +3 -0
- package/src/nl/onderwijsnummer.spec.ts +34 -0
- package/src/nl/onderwijsnummer.ts +77 -0
- package/src/no/fodselsnummer.spec.ts +56 -0
- package/src/no/fodselsnummer.ts +118 -0
- package/src/no/index.ts +4 -0
- package/src/no/kontonr.spec.ts +34 -0
- package/src/no/kontonr.ts +84 -0
- package/src/no/mva.spec.ts +28 -0
- package/src/no/mva.ts +80 -0
- package/src/no/orgnr.spec.ts +28 -0
- package/src/no/orgnr.ts +75 -0
- package/src/nz/bank.spec.ts +28 -0
- package/src/nz/bank.ts +238 -0
- package/src/nz/index.ts +2 -0
- package/src/nz/ird.spec.ts +34 -0
- package/src/nz/ird.ts +102 -0
- package/src/pe/ce.spec.ts +46 -0
- package/src/pe/ce.ts +61 -0
- package/src/pe/cui.spec.ts +28 -0
- package/src/pe/cui.ts +85 -0
- package/src/pe/index.ts +3 -0
- package/src/pe/ruc.spec.ts +46 -0
- package/src/pe/ruc.ts +84 -0
- package/src/pk/cnic.spec.ts +34 -0
- package/src/pk/cnic.ts +97 -0
- package/src/pk/index.ts +2 -0
- package/src/pk/ntn.spec.ts +22 -0
- package/src/pk/ntn.ts +65 -0
- package/src/pl/index.ts +3 -0
- package/src/pl/nip.spec.ts +34 -0
- package/src/pl/nip.ts +74 -0
- package/src/pl/pesel.spec.ts +34 -0
- package/src/pl/pesel.ts +97 -0
- package/src/pl/regon.spec.ts +52 -0
- package/src/pl/regon.ts +88 -0
- package/src/pt/cc.spec.ts +43 -0
- package/src/pt/cc.ts +74 -0
- package/src/pt/index.ts +3 -0
- package/src/pt/nif.spec.ts +28 -0
- package/src/pt/nif.ts +78 -0
- package/src/pt/nipc.ts +27 -0
- package/src/py/cedula.spec.ts +46 -0
- package/src/py/cedula.ts +73 -0
- package/src/py/index.ts +2 -0
- package/src/py/ruc.spec.ts +40 -0
- package/src/py/ruc.ts +93 -0
- package/src/ro/cif.spec.ts +40 -0
- package/src/ro/cif.ts +62 -0
- package/src/ro/cnp.spec.ts +50 -0
- package/src/ro/cnp.ts +158 -0
- package/src/ro/cui.spec.ts +28 -0
- package/src/ro/cui.ts +83 -0
- package/src/ro/index.ts +4 -0
- package/src/ro/onrc.spec.ts +28 -0
- package/src/ro/onrc.ts +109 -0
- package/src/rs/index.ts +2 -0
- package/src/rs/jmbg.ts +16 -0
- package/src/rs/pib.spec.ts +28 -0
- package/src/rs/pib.ts +69 -0
- package/src/ru/index.ts +1 -0
- package/src/ru/inn.spec.ts +32 -0
- package/src/ru/inn.ts +106 -0
- package/src/se/index.ts +3 -0
- package/src/se/orgnr.spec.ts +28 -0
- package/src/se/orgnr.ts +68 -0
- package/src/se/personnummer.spec.ts +45 -0
- package/src/se/personnummer.ts +143 -0
- package/src/se/vat.spec.ts +28 -0
- package/src/se/vat.ts +73 -0
- package/src/sg/index.ts +1 -0
- package/src/sg/uen.spec.ts +46 -0
- package/src/sg/uen.ts +209 -0
- package/src/si/ddv.spec.ts +28 -0
- package/src/si/ddv.ts +76 -0
- package/src/si/emso.spec.ts +15 -0
- package/src/si/emso.ts +27 -0
- package/src/si/index.ts +3 -0
- package/src/si/jmbg.ts +20 -0
- package/src/sk/dph.spec.ts +28 -0
- package/src/sk/dph.ts +71 -0
- package/src/sk/index.ts +2 -0
- package/src/sk/rc.ts +12 -0
- package/src/sm/coe.spec.ts +34 -0
- package/src/sm/coe.ts +80 -0
- package/src/sm/index.ts +1 -0
- package/src/sv/index.ts +1 -0
- package/src/sv/nit.spec.ts +34 -0
- package/src/sv/nit.ts +117 -0
- package/src/th/idnr.spec.ts +41 -0
- package/src/th/idnr.ts +80 -0
- package/src/th/index.ts +3 -0
- package/src/th/moa.spec.ts +62 -0
- package/src/th/moa.ts +85 -0
- package/src/th/tin.spec.ts +77 -0
- package/src/th/tin.ts +56 -0
- package/src/tn/index.ts +1 -0
- package/src/tn/mf.spec.ts +37 -0
- package/src/tn/mf.ts +169 -0
- package/src/tr/index.ts +2 -0
- package/src/tr/tckimlik.spec.ts +40 -0
- package/src/tr/tckimlik.ts +87 -0
- package/src/tr/vkn.spec.ts +28 -0
- package/src/tr/vkn.ts +87 -0
- package/src/tw/ban.spec.ts +28 -0
- package/src/tw/ban.ts +67 -0
- package/src/tw/index.ts +5 -0
- package/src/tw/natid.spec.ts +28 -0
- package/src/tw/natid.ts +105 -0
- package/src/tw/tax_code.spec.ts +34 -0
- package/src/tw/tax_code.ts +98 -0
- package/src/tw/ubn.spec.ts +28 -0
- package/src/tw/ubn.ts +80 -0
- package/src/tw/ui.spec.ts +38 -0
- package/src/tw/ui.ts +107 -0
- package/src/types.ts +82 -0
- package/src/ua/edrpou.spec.ts +28 -0
- package/src/ua/edrpou.ts +88 -0
- package/src/ua/index.ts +2 -0
- package/src/ua/rntrc.spec.ts +28 -0
- package/src/ua/rntrc.ts +77 -0
- package/src/us/ein.spec.ts +28 -0
- package/src/us/ein.ts +179 -0
- package/src/us/index.ts +2 -0
- package/src/us/ssn.spec.ts +28 -0
- package/src/us/ssn.ts +117 -0
- package/src/util/checksum.spec.ts +70 -0
- package/src/util/checksum.ts +258 -0
- package/src/util/index.ts +13 -0
- package/src/util/isValidDate.spec.ts +49 -0
- package/src/util/isValidDate.ts +87 -0
- package/src/util/iso7064.spec.ts +17 -0
- package/src/util/iso7064.ts +8 -0
- package/src/util/pymod.ts +8 -0
- package/src/util/strings/char.ts +18 -0
- package/src/util/strings/clean.spec.ts +15 -0
- package/src/util/strings/clean.ts +305 -0
- package/src/util/strings/format.ts +18 -0
- package/src/util/strings/index.ts +5 -0
- package/src/util/strings/reverseString.ts +3 -0
- package/src/util/strings/splitAt.spec.ts +15 -0
- package/src/util/strings/splitAt.ts +16 -0
- package/src/uy/cedula.spec.ts +28 -0
- package/src/uy/cedula.ts +74 -0
- package/src/uy/index.ts +3 -0
- package/src/uy/nie.spec.ts +28 -0
- package/src/uy/nie.ts +84 -0
- package/src/uy/rut.spec.ts +34 -0
- package/src/uy/rut.ts +99 -0
- package/src/ve/index.ts +1 -0
- package/src/ve/rif.spec.ts +38 -0
- package/src/ve/rif.ts +92 -0
- package/src/vn/index.ts +1 -0
- package/src/vn/mst.spec.ts +40 -0
- package/src/vn/mst.ts +100 -0
- package/src/za/idnr.spec.ts +28 -0
- package/src/za/idnr.ts +84 -0
- package/src/za/index.ts +2 -0
- package/src/za/tin.spec.ts +28 -0
- package/src/za/tin.ts +75 -0
package/src/ba/jmbg.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JMBG (Bosnia and Herzegovina Unique Master Citizen Number).
|
|
3
|
+
*
|
|
4
|
+
* Source
|
|
5
|
+
* https://en.wikipedia.org/wiki/Unique_Master_Citizen_Number#
|
|
6
|
+
*
|
|
7
|
+
* PERSON
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as exceptions from '../exceptions';
|
|
11
|
+
import { isValidDate, strings } from '../util';
|
|
12
|
+
import { Validator, ValidateReturn } from '../types';
|
|
13
|
+
import { weightedSum } from '../util/checksum';
|
|
14
|
+
|
|
15
|
+
function clean(input: string): ReturnType<typeof strings.cleanUnicode> {
|
|
16
|
+
return strings.cleanUnicode(input, ' -');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const impl: Validator = {
|
|
20
|
+
name: 'Bosnia Unique Master Citizen Number',
|
|
21
|
+
localName: 'Jedinstveni matični broj građana',
|
|
22
|
+
abbreviation: 'JMBG',
|
|
23
|
+
compact(input: string): string {
|
|
24
|
+
const [value, err] = clean(input);
|
|
25
|
+
|
|
26
|
+
if (err) {
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return value;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
format(input: string): string {
|
|
34
|
+
const [value] = clean(input);
|
|
35
|
+
|
|
36
|
+
return value;
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
validate(input: string): ValidateReturn {
|
|
40
|
+
const [value, error] = clean(input);
|
|
41
|
+
|
|
42
|
+
if (error) {
|
|
43
|
+
return { isValid: false, error };
|
|
44
|
+
}
|
|
45
|
+
if (value.length !== 13) {
|
|
46
|
+
return { isValid: false, error: new exceptions.InvalidLength() };
|
|
47
|
+
}
|
|
48
|
+
if (!strings.isdigits(value)) {
|
|
49
|
+
return { isValid: false, error: new exceptions.InvalidFormat() };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Question the format starts with this according to SI/EMSO
|
|
53
|
+
// -- DDMMYYY (year < 800 ? year+=2000 : year+=1000)
|
|
54
|
+
// Is this universal?
|
|
55
|
+
const [dd, mm, yyy] = strings.splitAt(value, 2, 4, 7);
|
|
56
|
+
const yyyy = `${parseInt(yyy, 10) < 800 ? '2' : '1'}${yyy}`;
|
|
57
|
+
|
|
58
|
+
if (!isValidDate(yyyy, mm, dd, true)) {
|
|
59
|
+
return { isValid: false, error: new exceptions.InvalidComponent() };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const [front, check] = strings.splitAt(value, 12);
|
|
63
|
+
|
|
64
|
+
const sum =
|
|
65
|
+
11 -
|
|
66
|
+
weightedSum(front, {
|
|
67
|
+
modulus: 11,
|
|
68
|
+
weights: [7, 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2],
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (String((sum % 11) % 10) !== check) {
|
|
72
|
+
return { isValid: false, error: new exceptions.InvalidChecksum() };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
isValid: true,
|
|
77
|
+
compact: value,
|
|
78
|
+
isIndividual: true,
|
|
79
|
+
isCompany: false,
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const { name, localName, abbreviation, validate, format, compact } =
|
|
85
|
+
impl;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { validate, format } from './bis';
|
|
2
|
+
import { InvalidLength, InvalidChecksum, InvalidFormat } from '../exceptions';
|
|
3
|
+
|
|
4
|
+
describe('be/bis', () => {
|
|
5
|
+
it('format:88 22 29-999.70', () => {
|
|
6
|
+
const result = format('88 02 29-999.70');
|
|
7
|
+
|
|
8
|
+
expect(result).toEqual('88022999970');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('validate:1', () => {
|
|
12
|
+
const result = validate('1');
|
|
13
|
+
|
|
14
|
+
expect(result.error).toBeInstanceOf(InvalidLength);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('validate:88022999990', () => {
|
|
18
|
+
// A number that validates for NN, should be invalid
|
|
19
|
+
const result = validate('88022999990');
|
|
20
|
+
|
|
21
|
+
expect(result.error).toBeInstanceOf(InvalidFormat);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('validate:88222999936', () => {
|
|
25
|
+
// A number with an offset of 20, should be valid assuming 19xx
|
|
26
|
+
const result = validate('88222999936');
|
|
27
|
+
|
|
28
|
+
expect(result.isValid && result.compact).toEqual('88222999936');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('validate:08222999934', () => {
|
|
32
|
+
// A number with an offset of 20, should be valid assuming 20xx
|
|
33
|
+
const result = validate('08222999934');
|
|
34
|
+
|
|
35
|
+
expect(result.isValid && result.compact).toEqual('08222999934');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('validate:88422999979', () => {
|
|
39
|
+
// A number with an offset of 40, should be valid assuming 19xx
|
|
40
|
+
const result = validate('88422999979');
|
|
41
|
+
|
|
42
|
+
expect(result.isValid && result.compact).toEqual('88422999979');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('validate:08422999977', () => {
|
|
46
|
+
// A number with an offset of 40, should be valid assuming 20xx
|
|
47
|
+
const result = validate('08422999977');
|
|
48
|
+
|
|
49
|
+
expect(result.isValid && result.compact).toEqual('08422999977');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('validate:96331699989', () => {
|
|
53
|
+
// A number with an offset of 20, should be invalid due to invalid month
|
|
54
|
+
const result = validate('96331699989');
|
|
55
|
+
|
|
56
|
+
expect(result.error).toBeInstanceOf(InvalidFormat);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('validate:08222999935', () => {
|
|
60
|
+
// A number with an offset of 20, should be invalid due to invalid checksum
|
|
61
|
+
const result = validate('08222999935');
|
|
62
|
+
|
|
63
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('validate:96531699935', () => {
|
|
67
|
+
// A number with an offset of 40, should be invalid due to invalid month
|
|
68
|
+
const result = validate('96531699935');
|
|
69
|
+
|
|
70
|
+
expect(result.error).toBeInstanceOf(InvalidFormat);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('validate:08451799971', () => {
|
|
74
|
+
// A number with an offset of 40, should be invalid due to invalid checksum
|
|
75
|
+
const result = validate('08451799971');
|
|
76
|
+
|
|
77
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('validate:92612099915', () => {
|
|
81
|
+
// A number with an offset of 60, should be invalid due to invalid month
|
|
82
|
+
const result = validate('92612099915');
|
|
83
|
+
|
|
84
|
+
expect(result.error).toBeInstanceOf(InvalidFormat);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('validate:99200199926', () => {
|
|
88
|
+
// A number with an unknown dob offset by 20, should be valid assuming 19xx
|
|
89
|
+
const result = validate('99200199926');
|
|
90
|
+
|
|
91
|
+
expect(result.isValid && result.compact).toEqual('99200199926');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('validate:01200199934', () => {
|
|
95
|
+
// A number with an unknown dob offset by 20, should be valid assuming 20xx
|
|
96
|
+
const result = validate('01200199934');
|
|
97
|
+
|
|
98
|
+
expect(result.isValid && result.compact).toEqual('01200199934');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('validate:01200199935', () => {
|
|
102
|
+
// A number with an unknown dob offset by 20, should be invalid by checksum
|
|
103
|
+
const result = validate('01200199935');
|
|
104
|
+
|
|
105
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('validate:99400199969', () => {
|
|
109
|
+
// A number with an unknown dob offset by 40, should be valid assuming 19xx
|
|
110
|
+
const result = validate('99400199969');
|
|
111
|
+
|
|
112
|
+
expect(result.isValid && result.compact).toEqual('99400199969');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('validate:01451599980', () => {
|
|
116
|
+
// A number with an unknown dob offset by 40, should be valid assuming 20xx
|
|
117
|
+
const result = validate('01451599980');
|
|
118
|
+
|
|
119
|
+
expect(result.isValid && result.compact).toEqual('01451599980');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('validate:01400199977', () => {
|
|
123
|
+
// A number with an unknown dob offset by 40, should be valid assuming 20xx
|
|
124
|
+
const result = validate('01400199977');
|
|
125
|
+
|
|
126
|
+
expect(result.isValid && result.compact).toEqual('01400199977');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('validate:01400199981', () => {
|
|
130
|
+
// A number with an unknown dob offset by 40, should be invalid by checksum
|
|
131
|
+
const result = validate('01400199981');
|
|
132
|
+
|
|
133
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('validate:00290199976', () => {
|
|
137
|
+
// A number that starts with 00 can be valid
|
|
138
|
+
const result = validate('00290199976');
|
|
139
|
+
|
|
140
|
+
expect(result.isValid && result.compact).toEqual('00290199976');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('validate:(unspecified date in current year, offset of 20)', () => {
|
|
144
|
+
const yy = new Date().getFullYear() % 100;
|
|
145
|
+
const baseNum = parseInt(`${yy}2000999`, 10);
|
|
146
|
+
const twoPrefixedBaseNumber = parseInt(`${2}${baseNum}`, 10);
|
|
147
|
+
const checksum = 97 - (twoPrefixedBaseNumber % 97);
|
|
148
|
+
const id = `${baseNum}${checksum}`;
|
|
149
|
+
|
|
150
|
+
const result = validate(id);
|
|
151
|
+
expect(result.isValid && result.compact).toEqual(id);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('validate:(unspecified date in current year, offset of 40)', () => {
|
|
155
|
+
const yy = new Date().getFullYear() % 100;
|
|
156
|
+
const baseNum = parseInt(`${yy}4000999`, 10);
|
|
157
|
+
const twoPrefixedBaseNumber = parseInt(`${2}${baseNum}`, 10);
|
|
158
|
+
const checksum = 97 - (twoPrefixedBaseNumber % 97);
|
|
159
|
+
const id = `${baseNum}${checksum}`;
|
|
160
|
+
|
|
161
|
+
const result = validate(id);
|
|
162
|
+
expect(result.isValid && result.compact).toEqual(id);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('validate:(unspecified date 100 years ago, offset of 20)', () => {
|
|
166
|
+
const yy = new Date().getFullYear() % 100;
|
|
167
|
+
const baseNum = parseInt(`${yy}2000999`, 10);
|
|
168
|
+
const checksum = 97 - (baseNum % 97);
|
|
169
|
+
const id = `${baseNum}${checksum}`;
|
|
170
|
+
|
|
171
|
+
const result = validate(id);
|
|
172
|
+
expect(result.isValid && result.compact).toEqual(id);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('validate:(unspecified date 100 years ago, offset of 40)', () => {
|
|
176
|
+
const yy = new Date().getFullYear() % 100;
|
|
177
|
+
const baseNum = parseInt(`${yy}4000999`, 10);
|
|
178
|
+
const checksum = 97 - (baseNum % 97);
|
|
179
|
+
const id = `${baseNum}${checksum}`;
|
|
180
|
+
|
|
181
|
+
const result = validate(id);
|
|
182
|
+
expect(result.isValid && result.compact).toEqual(id);
|
|
183
|
+
});
|
|
184
|
+
});
|
package/src/be/bis.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The BIS (Belgian Number for Foreigners) is an identifier for individuals such
|
|
3
|
+
* as cross-border workers who do not have a Belgian National Number. It has the
|
|
4
|
+
* same format as the Belgian National Number, but the month digits are increased
|
|
5
|
+
* by 40 if the sex of the person was known when the number was assigned and by
|
|
6
|
+
* 20 if not.
|
|
7
|
+
*
|
|
8
|
+
* Source
|
|
9
|
+
* https://fr.wikipedia.org/wiki/Numéro_de_registre_national (Numéro de sécurité sociale)
|
|
10
|
+
*
|
|
11
|
+
* PERSON
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import * as exceptions from '../exceptions';
|
|
15
|
+
import { strings } from '../util';
|
|
16
|
+
import {
|
|
17
|
+
validStructure,
|
|
18
|
+
validChecksum,
|
|
19
|
+
toDateArray,
|
|
20
|
+
} from './personIdentifierHelpers';
|
|
21
|
+
import { Validator, ValidateReturn } from '../types';
|
|
22
|
+
|
|
23
|
+
function clean(input: string): ReturnType<typeof strings.cleanUnicode> {
|
|
24
|
+
return strings.cleanUnicode(input, ' -.');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function toDob(firstSix: string): string {
|
|
28
|
+
const [y, m, d] = toDateArray(firstSix).map(s => parseInt(s, 10));
|
|
29
|
+
const adjustedDateArrays = [
|
|
30
|
+
[y, m - 20, d],
|
|
31
|
+
[y, m - 40, d],
|
|
32
|
+
];
|
|
33
|
+
// Allow 0 because a 0 month indicates an unknown DOB.
|
|
34
|
+
const dobArray =
|
|
35
|
+
adjustedDateArrays.find(ada => ada[1] >= 0 && ada[1] <= 12) || [];
|
|
36
|
+
return dobArray.map(n => `${n}`.padStart(2, '0')).join('');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const impl: Validator = {
|
|
40
|
+
name: 'Belgian Number for Foreigners',
|
|
41
|
+
localName: 'Numéro BIS',
|
|
42
|
+
abbreviation: 'BIS',
|
|
43
|
+
compact(input: string): string {
|
|
44
|
+
const [value, err] = clean(input);
|
|
45
|
+
|
|
46
|
+
if (err) {
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return value;
|
|
51
|
+
},
|
|
52
|
+
format(input: string): string {
|
|
53
|
+
const [value] = clean(input);
|
|
54
|
+
return value;
|
|
55
|
+
},
|
|
56
|
+
validate(input: string): ValidateReturn {
|
|
57
|
+
const number = impl.compact(input);
|
|
58
|
+
|
|
59
|
+
if (!strings.isdigits(number) || parseInt(number, 10) <= 0) {
|
|
60
|
+
return { isValid: false, error: new exceptions.InvalidFormat() };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (number.length !== 11) {
|
|
64
|
+
return { isValid: false, error: new exceptions.InvalidLength() };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!validStructure(number, toDob)) {
|
|
68
|
+
return { isValid: false, error: new exceptions.InvalidFormat() };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!validChecksum(number, toDob)) {
|
|
72
|
+
return { isValid: false, error: new exceptions.InvalidChecksum() };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
isValid: true,
|
|
77
|
+
compact: number,
|
|
78
|
+
isIndividual: true,
|
|
79
|
+
isCompany: false,
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const { name, localName, abbreviation, validate, format, compact } =
|
|
85
|
+
impl;
|
package/src/be/index.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { validate, format } from './insz';
|
|
2
|
+
import { InvalidLength, InvalidChecksum, InvalidFormat } from '../exceptions';
|
|
3
|
+
|
|
4
|
+
describe('be/insz', () => {
|
|
5
|
+
it('format:88 02 29-999.90', () => {
|
|
6
|
+
const result = format('88 02 29-999.90');
|
|
7
|
+
|
|
8
|
+
expect(result).toEqual('88022999990');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('validate:1', () => {
|
|
12
|
+
const result = validate('1');
|
|
13
|
+
|
|
14
|
+
expect(result.error).toBeInstanceOf(InvalidLength);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('validate:88022999990', () => {
|
|
18
|
+
// Valid only for NN, returns true
|
|
19
|
+
const result = validate('88022999990');
|
|
20
|
+
|
|
21
|
+
expect(result.isValid && result.compact).toEqual('88022999990');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('validate:88222999936', () => {
|
|
25
|
+
// Valid only for BIS, returns true
|
|
26
|
+
const result = validate('88222999936');
|
|
27
|
+
|
|
28
|
+
expect(result.isValid && result.compact).toEqual('88222999936');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('validate:88150199951', () => {
|
|
32
|
+
// Invalid Format for both
|
|
33
|
+
const result = validate('88150199951');
|
|
34
|
+
|
|
35
|
+
expect(result.error).toBeInstanceOf(InvalidFormat);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('validate:08222999935', () => {
|
|
39
|
+
// Invalid format for NN (month + 20), Invalid checksum for BIS
|
|
40
|
+
const result = validate('08222999935');
|
|
41
|
+
|
|
42
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('validate:20070199952', () => {
|
|
46
|
+
// Invalid checksum for NN, Invalid format for BIS
|
|
47
|
+
const result = validate('20070199952');
|
|
48
|
+
|
|
49
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
50
|
+
});
|
|
51
|
+
});
|
package/src/be/insz.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Belgian Social Security Identification Number is an 11 digit number.
|
|
3
|
+
* It can be either a National Register Number (NN, NISS) or BIS.
|
|
4
|
+
*
|
|
5
|
+
* Sources
|
|
6
|
+
* https://fr.wikipedia.org/wiki/Numéro_de_registre_national
|
|
7
|
+
* https://www2.deloitte.com/content/dam/Deloitte/be/Documents/tax/TaxAlerts/IndividualTaxAlerts/Social%20Security%20alert%20-%20BelgianIDpro%20-%2026%20Nov%202020.pdf
|
|
8
|
+
*
|
|
9
|
+
* PERSON
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { strings } from '../util';
|
|
13
|
+
import { validate as nnValidate } from './nn';
|
|
14
|
+
import { validate as bisValidate } from './bis';
|
|
15
|
+
import { Validator, ValidateReturn } from '../types';
|
|
16
|
+
|
|
17
|
+
function clean(input: string): ReturnType<typeof strings.cleanUnicode> {
|
|
18
|
+
return strings.cleanUnicode(input, ' -.');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const impl: Validator = {
|
|
22
|
+
name: 'Belgian Social Security Identification Number',
|
|
23
|
+
localName: 'Identificatienummer van de Sociale Zekerheid',
|
|
24
|
+
abbreviation: 'INSZ, NISS',
|
|
25
|
+
compact(input: string): string {
|
|
26
|
+
const [value, err] = clean(input);
|
|
27
|
+
|
|
28
|
+
if (err) {
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return value;
|
|
33
|
+
},
|
|
34
|
+
format(input: string): string {
|
|
35
|
+
const [value] = clean(input);
|
|
36
|
+
return value;
|
|
37
|
+
},
|
|
38
|
+
validate(input: string): ValidateReturn {
|
|
39
|
+
const results = [nnValidate(input), bisValidate(input)];
|
|
40
|
+
const validResult = results.find(r => r.isValid);
|
|
41
|
+
if (validResult) return validResult;
|
|
42
|
+
|
|
43
|
+
// The only case with two different error types is an invalid checksum and an
|
|
44
|
+
// invalid format. The identifier with the checksum error had correct
|
|
45
|
+
// formatting, so invalid checksum seems like the more descriptive error.
|
|
46
|
+
|
|
47
|
+
const checksumErrorResult = results.find(
|
|
48
|
+
r => r.error && r.error.name === 'InvalidChecksum',
|
|
49
|
+
);
|
|
50
|
+
return checksumErrorResult || results[0];
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const { name, localName, abbreviation, validate, format, compact } =
|
|
55
|
+
impl;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { validate, format } from './nn';
|
|
2
|
+
import { InvalidLength, InvalidChecksum, InvalidFormat } from '../exceptions';
|
|
3
|
+
|
|
4
|
+
describe('be/nn', () => {
|
|
5
|
+
it('format:88 02 29-999.90', () => {
|
|
6
|
+
const result = format('88 02 29-999.90');
|
|
7
|
+
|
|
8
|
+
expect(result).toEqual('88022999990');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('format:88022999990', () => {
|
|
12
|
+
const result = format('88022999990');
|
|
13
|
+
|
|
14
|
+
expect(result).toEqual('88022999990');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('validate:1', () => {
|
|
18
|
+
const result = validate('1');
|
|
19
|
+
|
|
20
|
+
expect(result.error).toBeInstanceOf(InvalidLength);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('validate:88022999990', () => {
|
|
24
|
+
const result = validate('88022999990');
|
|
25
|
+
|
|
26
|
+
expect(result.isValid && result.compact).toEqual('88022999990');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('validate:88022999991', () => {
|
|
30
|
+
const result = validate('88022999991');
|
|
31
|
+
|
|
32
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('validate:87022999991', () => {
|
|
36
|
+
const result = validate('87022999991');
|
|
37
|
+
|
|
38
|
+
expect(result.error).toBeInstanceOf(InvalidFormat);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test.each([
|
|
42
|
+
'88022999297',
|
|
43
|
+
'85073003328',
|
|
44
|
+
'20070199922',
|
|
45
|
+
'20070199951',
|
|
46
|
+
'80000099902',
|
|
47
|
+
'00000199938',
|
|
48
|
+
'99000099913',
|
|
49
|
+
])('validate:%s', value => {
|
|
50
|
+
const result = validate(value);
|
|
51
|
+
|
|
52
|
+
expect(result.isValid).toEqual(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('validate:20070199952', () => {
|
|
56
|
+
const result = validate('20070199952');
|
|
57
|
+
|
|
58
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('validate:80000099903', () => {
|
|
62
|
+
const result = validate('80000099903');
|
|
63
|
+
|
|
64
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('validate:00000199939', () => {
|
|
68
|
+
const result = validate('00000199939');
|
|
69
|
+
|
|
70
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('validate:99000099942', () => {
|
|
74
|
+
const result = validate('99000099942');
|
|
75
|
+
|
|
76
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('validate:40000100133', () => {
|
|
80
|
+
const result = validate('40000100133');
|
|
81
|
+
|
|
82
|
+
expect(result.isValid && result.compact).toEqual('40000100133');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('validate:00000199938', () => {
|
|
86
|
+
const result = validate('00000199938');
|
|
87
|
+
|
|
88
|
+
expect(result.isValid && result.compact).toEqual('00000199938');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('validate:40000095579', () => {
|
|
92
|
+
const result = validate('40000095579');
|
|
93
|
+
|
|
94
|
+
expect(result.isValid && result.compact).toEqual('40000095579');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('validate:(unspecified date in current year)', () => {
|
|
98
|
+
const yy = new Date().getFullYear() % 100;
|
|
99
|
+
const baseNum = parseInt(`${yy}0000999`, 10);
|
|
100
|
+
const twoPrefixedBaseNumber = parseInt(`${2}${baseNum}`, 10);
|
|
101
|
+
const checksum = 97 - (twoPrefixedBaseNumber % 97);
|
|
102
|
+
const id = `${baseNum}${checksum}`;
|
|
103
|
+
|
|
104
|
+
const result = validate(id);
|
|
105
|
+
expect(result.isValid && result.compact).toEqual(id);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('validate:(unspecified date 100 years ago)', () => {
|
|
109
|
+
const yy = new Date().getFullYear() % 100;
|
|
110
|
+
const baseNum = parseInt(`${yy}0000999`, 10);
|
|
111
|
+
const checksum = 97 - (baseNum % 97);
|
|
112
|
+
const id = `${baseNum}${checksum}`;
|
|
113
|
+
|
|
114
|
+
const result = validate(id);
|
|
115
|
+
expect(result.isValid && result.compact).toEqual(id);
|
|
116
|
+
});
|
|
117
|
+
});
|
package/src/be/nn.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NN, NISS, RRN (Belgian national number).
|
|
3
|
+
*
|
|
4
|
+
* The national registration number (Rijksregisternummer, Numéro de registre
|
|
5
|
+
* national, Nationalregisternummer) is a unique identification number of
|
|
6
|
+
* natural persons who are registered in Belgium.
|
|
7
|
+
*
|
|
8
|
+
* The number consists of 11 digits and includes the person's date of birth and
|
|
9
|
+
* gender. It encodes the date of birth in the first 6 digits in the format
|
|
10
|
+
* YYMMDD. The following 3 digits represent a counter of people born on the same
|
|
11
|
+
* date, seperated by sex (odd for male and even for females respectively). The
|
|
12
|
+
* final 2 digits form a check number based on the 9 preceding digits.
|
|
13
|
+
*
|
|
14
|
+
* Source
|
|
15
|
+
* https://nl.wikipedia.org/wiki/Rijksregisternummer
|
|
16
|
+
* https://fr.wikipedia.org/wiki/Numéro_de_registre_national
|
|
17
|
+
* https://www.ibz.rrn.fgov.be/fileadmin/user_upload/nl/rr/instructies/IT-lijst/IT000_Rijksregisternummer.pdf
|
|
18
|
+
*
|
|
19
|
+
* PERSON
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import * as exceptions from '../exceptions';
|
|
23
|
+
import { strings } from '../util';
|
|
24
|
+
import { validStructure, validChecksum } from './personIdentifierHelpers';
|
|
25
|
+
import { Validator, ValidateReturn } from '../types';
|
|
26
|
+
|
|
27
|
+
function clean(input: string): ReturnType<typeof strings.cleanUnicode> {
|
|
28
|
+
return strings.cleanUnicode(input, ' -.');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const impl: Validator = {
|
|
32
|
+
name: 'Belgian National Number',
|
|
33
|
+
localName: 'Numéro National',
|
|
34
|
+
abbreviation: 'NN, RN',
|
|
35
|
+
compact(input: string): string {
|
|
36
|
+
const [value, err] = clean(input);
|
|
37
|
+
|
|
38
|
+
if (err) {
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return value;
|
|
43
|
+
},
|
|
44
|
+
format(input: string): string {
|
|
45
|
+
const [value] = clean(input);
|
|
46
|
+
return value;
|
|
47
|
+
},
|
|
48
|
+
validate(input: string): ValidateReturn {
|
|
49
|
+
const value = impl.compact(input);
|
|
50
|
+
|
|
51
|
+
if (!strings.isdigits(value) || parseInt(value, 10) <= 0) {
|
|
52
|
+
return { isValid: false, error: new exceptions.InvalidFormat() };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (value.length !== 11) {
|
|
56
|
+
return { isValid: false, error: new exceptions.InvalidLength() };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!validStructure(value)) {
|
|
60
|
+
return { isValid: false, error: new exceptions.InvalidFormat() };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!validChecksum(value)) {
|
|
64
|
+
return { isValid: false, error: new exceptions.InvalidChecksum() };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
isValid: true,
|
|
69
|
+
compact: value,
|
|
70
|
+
isIndividual: true,
|
|
71
|
+
isCompany: false,
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const { name, localName, abbreviation, validate, format, compact } =
|
|
77
|
+
impl;
|