@@ -127,111 +127,3 @@ export function trim(haystack: string, needle: string): string {
127127 const trimmed = ltrim ( haystack , needle ) ;
128128 return rtrim ( trimmed , needle ) ;
129129}
130-
131- /**
132- * Checks if the provided string is a valid swiss IBAN number
133- * @param ibanNumber The provided IBAN number to check
134- * Must be in one of the following formats:
135- * - "CHXX XXXX XXXX XXXX XXXX X" with whitespaces
136- * - "CHXXXXXXXXXXXXXXXXXXX" without whitespaces
137- * @returns The result of the IBAN number check
138- */
139- export function isValidSwissIbanNumber ( ibanNumber : string ) : boolean {
140- // 1. Reject null, undefined or whitespace-only strings
141- if ( isNullOrWhitespace ( ibanNumber ) ) {
142- return false ;
143- }
144-
145- // 2. Define allowed strict formats
146- // - with spaces: "CHXX XXXX XXXX XXXX XXXX X"
147- const compactIbanNumberWithWhiteSpaces = new RegExp ( / ^ C H \d { 2 } (?: \d { 4 } ) { 4 } \d { 1 } $ / ) ;
148- // - without spaces: "CHXXXXXXXXXXXXXXXXXXX"
149- const compactIbanNumberWithoutWhiteSpaces = new RegExp ( / ^ C H \d { 19 } $ / ) ;
150-
151- // 3. Check if input matches one of the allowed formats
152- if ( ! compactIbanNumberWithWhiteSpaces . test ( ibanNumber ) && ! compactIbanNumberWithoutWhiteSpaces . test ( ibanNumber ) ) {
153- return false ;
154- }
155-
156- // 4. Remove all spaces to get a compact IBAN string
157- const compactIbanNumber = ibanNumber . replaceAll ( " " , "" ) ;
158-
159- // 5. Rearrange IBAN for checksum calculation
160- // - move first 4 characters (CH + 2 check digits) to the end
161- const rearrangedIban = compactIbanNumber . slice ( 4 ) + compactIbanNumber . slice ( 0 , 4 ) ;
162-
163- // 6. Replace letters with numbers (A=10, B=11, ..., Z=35)
164- const numericStr = rearrangedIban . replaceAll ( / [ A - Z ] / g, ( ch ) => ( ch . codePointAt ( 0 ) ! - 55 ) . toString ( ) ) ;
165-
166- // 7. Perform modulo 97 calculation to validate IBAN
167- let restOfCalculation = 0 ;
168- for ( const digit of numericStr ) {
169- restOfCalculation = ( restOfCalculation * 10 + Number ( digit ) ) % 97 ;
170- }
171-
172- // 8. IBAN is valid only if the remainder equals 1
173- return restOfCalculation === 1 ;
174- }
175-
176- /**
177- * Validation of social insurance number with checking the checksum
178- * Validation according to https://www.sozialversicherungsnummer.ch/aufbau-neu.htm
179- * @param socialInsuranceNumber The social insurance number to check
180- * Must be in one of the following formats:
181- * - "756.XXXX.XXXX.XX" with dots as separators
182- * - "756XXXXXXXXXX" with digits only
183- * @returns The result if the social insurance number is valid or not
184- */
185- export function isValidSwissSocialSecurityNumber ( socialInsuranceNumber : string ) : boolean {
186- // 1. Check if input is empty or only whitespace
187- if ( isNullOrWhitespace ( socialInsuranceNumber ) ) {
188- return false ;
189- }
190-
191- /**
192- * 2. Check if input matches accepted formats:
193- * - With dots: 756.XXXX.XXXX.XX
194- * - Without dots: 756XXXXXXXXXX
195- */
196- const socialInsuranceNumberWithDots = new RegExp ( / ^ 7 5 6 \. \d { 4 } \. \d { 4 } \. \d { 2 } $ / ) ;
197- const socialInsuranceNumberWithoutDots = new RegExp ( / ^ 7 5 6 \d { 10 } $ / ) ;
198-
199- if ( ! socialInsuranceNumberWithDots . test ( socialInsuranceNumber ) && ! socialInsuranceNumberWithoutDots . test ( socialInsuranceNumber ) ) {
200- return false ;
201- }
202-
203- // 3. Remove all dots → get a string of 13 digits
204- const compactNumber = socialInsuranceNumber . replaceAll ( "." , "" ) ;
205-
206- /**
207- * 4. Separate digits for checksum calculation
208- * - first 12 digits: used to calculate checksum
209- * - last digit: actual check digit
210- */
211- const digits = compactNumber . slice ( 0 , - 1 ) ;
212- const reversedDigits = [ ...digits ] . reverse ( ) . join ( "" ) ;
213- const reversedDigitsArray = [ ...reversedDigits ] ;
214-
215- /*
216- * 5. Calculate weighted sum for checksum
217- * - Even positions (after reversing) ×3
218- * - Odd positions ×1
219- */
220- let sum = 0 ;
221- for ( const [ i , element ] of reversedDigitsArray . entries ( ) ) {
222- sum += i % 2 === 0 ? Number ( element ) * 3 : Number ( element ) * 1 ;
223- }
224-
225- /*
226- * 6. Calculate expected check digit
227- * - Check digit = value to reach next multiple of 10
228- */
229- const checksum = ( 10 - ( sum % 10 ) ) % 10 ;
230- const checknumber = Number . parseInt ( compactNumber . slice ( - 1 ) ) ;
231-
232- /*
233- * 7. Compare calculated check digit with actual last digit
234- * - If equal → valid AHV number
235- */
236- return checksum === checknumber ;
237- }
0 commit comments