11import type { Gender , GenerateOptions , GeneratedId , IdNumberStrategy } from '../national-id-generator.types' ;
2+ import { randIntFromInterval } from '@/utils/random' ;
23
34// ─── types re-exported for backwards compatibility ────────────────────────────
45
@@ -21,10 +22,6 @@ export interface BelgianSSIN extends GeneratedId {
2122
2223// ─── internal helpers ─────────────────────────────────────────────────────────
2324
24- function randomInt ( min : number , max : number ) : number {
25- return Math . floor ( Math . random ( ) * ( max - min + 1 ) ) + min ;
26- }
27-
2825function daysInMonth ( year : number , month : number ) : number {
2926 // month is 1-indexed (1–12); new Date(year, month, 0) gives the last day of that month
3027 return new Date ( year , month , 0 ) . getDate ( ) ;
@@ -41,7 +38,7 @@ function randomLeapYear(min: number, max: number): number {
4138 leapYears . push ( y ) ;
4239 }
4340 }
44- return leapYears [ Math . floor ( Math . random ( ) * leapYears . length ) ] ! ;
41+ return leapYears [ randIntFromInterval ( 0 , 0.999 ) * leapYears . length ] ! ;
4542}
4643
4744function computeChecksum ( yymmdd : string , serial : string , bornAfter2000 : boolean ) : string {
@@ -54,14 +51,14 @@ function computeChecksum(yymmdd: string, serial: string, bornAfter2000: boolean)
5451// ─── public API ───────────────────────────────────────────────────────────────
5552
5653export function generateBelgianSSIN ( opts : GenerateBelgianSSINOptions = { } ) : BelgianSSIN {
57- const gender : Gender = opts . gender ?? ( Math . random ( ) < 0.5 ? 'male' : 'female' ) ;
54+ const gender : Gender = opts . gender ?? ( randIntFromInterval ( 0 , 0.9 ) < 0.5 ? 'male' : 'female' ) ;
5855 const fictitious = opts . fictitious ?? false ;
5956
6057 const currentYear = new Date ( ) . getFullYear ( ) ;
6158 const needsLeapYear = opts . birthDay === 29 && opts . birthMonth === 2 && opts . birthYear === undefined ;
62- const fullYear = opts . birthYear ?? ( needsLeapYear ? randomLeapYear ( 1900 , currentYear ) : randomInt ( 1900 , currentYear ) ) ;
63- const month = opts . birthMonth ?? randomInt ( 1 , 12 ) ;
64- const day = opts . birthDay ?? randomInt ( 1 , daysInMonth ( fullYear , month ) ) ;
59+ const fullYear = opts . birthYear ?? ( needsLeapYear ? randomLeapYear ( 1900 , currentYear ) : randIntFromInterval ( 1900 , currentYear ) ) ;
60+ const month = opts . birthMonth ?? randIntFromInterval ( 1 , 12 ) ;
61+ const day = opts . birthDay ?? randIntFromInterval ( 1 , daysInMonth ( fullYear , month ) ) ;
6562 const birthDate = new Date ( fullYear , month - 1 , day ) ;
6663
6764 const yy = fullYear . toString ( ) . slice ( - 2 ) . padStart ( 2 , '0' ) ;
@@ -74,14 +71,14 @@ export function generateBelgianSSIN(opts: GenerateBelgianSSINOptions = {}): Belg
7471 if ( gender === 'male' ) {
7572 const minOdd = fictitious ? 901 : 1 ;
7673 const maxOdd = fictitious ? 999 : 899 ;
77- const oddNum = randomInt ( minOdd , maxOdd ) ;
74+ const oddNum = randIntFromInterval ( minOdd , maxOdd ) ;
7875 const oddValue = oddNum % 2 === 0 ? oddNum + 1 : oddNum ;
7976 serial = oddValue . toString ( ) . padStart ( 3 , '0' ) ;
8077 }
8178 else {
8279 const minEven = fictitious ? 900 : 2 ;
8380 const maxEven = fictitious ? 998 : 898 ;
84- const evenNum = randomInt ( minEven / 2 , maxEven / 2 ) ;
81+ const evenNum = randIntFromInterval ( minEven / 2 , maxEven / 2 ) ;
8582 serial = ( evenNum * 2 ) . toString ( ) . padStart ( 3 , '0' ) ;
8683 }
8784
0 commit comments