@@ -25,12 +25,18 @@ public function extract(string $id): Citizen
2525 throw new InvalidIdException ();
2626 }
2727
28- $ gender = $ this ->getGender ($ id );
29- $ dateOfBirth = $ this ->getDateOfBirth ($ id );
30-
3128 $ citizen = new Citizen ();
32- $ citizen ->setGender ($ gender );
33- $ citizen ->setDateOfBirth ($ dateOfBirth );
29+
30+ // BIS numbers: month + 20 = gender unknown, month + 40 = gender known
31+ // Regular NRN: always has gender
32+ if (!$ this ->isBisNumber ($ id ) || $ this ->isBisGenderKnown ($ id )) {
33+ $ citizen ->setGender ($ this ->getGender ($ id ));
34+ }
35+
36+ // Extract DOB if birthdate is known (month is not 00, 20, or 40)
37+ if (!$ this ->isBirthdateUnknown ($ id )) {
38+ $ citizen ->setDateOfBirth ($ this ->getDateOfBirth ($ id ));
39+ }
3440
3541 return $ citizen ;
3642 }
@@ -40,7 +46,31 @@ private function sanitize(string $id): string
4046 return str_replace (['- ' , ' ' , '. ' ], '' , $ id );
4147 }
4248
43- private function getGender (int $ id ): Gender
49+ private function isBisNumber (string $ id ): bool
50+ {
51+ $ month = (int ) substr ($ id , 2 , 2 );
52+
53+ return $ month > 12 ;
54+ }
55+
56+ private function isBisGenderKnown (string $ id ): bool
57+ {
58+ $ month = (int ) substr ($ id , 2 , 2 );
59+
60+ // Month + 40 means gender is known, month + 20 means gender is unknown
61+ return $ month >= 40 ;
62+ }
63+
64+ private function isBirthdateUnknown (string $ id ): bool
65+ {
66+ $ month = (int ) substr ($ id , 2 , 2 );
67+
68+ // For BIS numbers only: month 20 or 40 means birthdate is unknown
69+ // Regular NRN with month 00 still extracts DOB (defaults to January)
70+ return $ month === 20 || $ month === 40 ;
71+ }
72+
73+ private function getGender (string $ id ): Gender
4474 {
4575 return (substr ($ id , 6 , 3 ) % 2 ) ? Gender::Male : Gender::Female;
4676 }
@@ -54,6 +84,13 @@ private function getDateOfBirth(string $id): DateTime
5484 $ month = (int ) $ month ;
5585 $ day = (int ) $ day ;
5686
87+ // BIS numbers have 20 or 40 added to the month
88+ if ($ month >= 40 ) {
89+ $ month -= 40 ;
90+ } elseif ($ month >= 20 ) {
91+ $ month -= 20 ;
92+ }
93+
5794 // use first day or month if unknown
5895 $ month = $ month === 0 ? 1 : $ month ;
5996 $ day = $ day === 0 ? 1 : $ day ;
0 commit comments