Skip to content

Commit fe089ca

Browse files
committed
Added Swiss standards function tryParseSwissIbanNumber
1 parent ef06d1b commit fe089ca

3 files changed

Lines changed: 58 additions & 49 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- `splitLines` string utility function
13-
- `formatSwissIbanNumber` swiss standard function
13+
- `tryParseSwissIbanNumber` swiss standard function
1414
- `trimStart`, `trimEnd` and `trim` string type utility functions
1515

1616
### Changed

src/lib/swissStandards.spec.ts

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isValidSwissIbanNumber, isValidSwissSocialInsuranceNumber, formatSwissIbanNumber } from "./swissStandards";
1+
import { isValidSwissIbanNumber, isValidSwissSocialInsuranceNumber, tryParseSwissIbanNumber } from "./swissStandards";
22

33
describe("Swiss standards test", () => {
44
test.each([
@@ -12,7 +12,7 @@ describe("Swiss standards test", () => {
1212
["ch93 0076 2011 6238 5295 7", false],
1313
["c93 0076 2011 6238 5295 7", false],
1414
["DE93 0076 2011 6238 5295 7", false],
15-
])("check if the swiss IBAN number is valid or not", (iBanNumberToCheck, expected) => {
15+
])("check if the Swiss IBAN number is valid or not", (iBanNumberToCheck, expected) => {
1616
expect(isValidSwissIbanNumber(iBanNumberToCheck)).toBe(expected);
1717
});
1818

@@ -25,7 +25,7 @@ describe("Swiss standards test", () => {
2525
["DE34 0076 2ABC 123D EF45 3", false],
2626
["CH34 0076 2ABC 123D EF45 \n6", false],
2727
["CH34 0076 2ABC 123D EF45 !", false],
28-
])("check if the siwss IBAN number with letters is valid or not", (iBanNumberToCheck, expected) => {
28+
])("check if the Swiss IBAN number with letters is valid or not", (iBanNumberToCheck, expected) => {
2929
expect(isValidSwissIbanNumber(iBanNumberToCheck)).toBe(expected);
3030
});
3131

@@ -45,18 +45,44 @@ describe("Swiss standards test", () => {
4545
});
4646

4747
test.each([
48-
[null as unknown as string, null, false],
49-
[undefined as unknown as string, undefined, false],
50-
["CH9300762011623852957", "CH93 0076 2011 6238 5295 7", true],
51-
["ch9300762011623852957", "CH93 0076 2011 6238 5295 7", true],
52-
["ch9301234567891011127", "CH93 0123 4567 8910 1112 7", false],
53-
["DE93 00 76 2011 62385295 7", "DE93 00 76 2011 62385295 7", false],
54-
["D 93 00 76 2011 62385295 7", "D 93 00 76 2011 62385295 7", false],
55-
["Ch 93 0076 20 1 162385 295 7", "CH93 0076 2011 6238 5295 7", true],
56-
])("Check if the IBAN number gets formatted correctly", (unformattedIbanNumber, expectedIbanNumber, expectedIsValid) => {
57-
const result = formatSwissIbanNumber(unformattedIbanNumber);
58-
59-
expect(result.ibanNumber).toBe(expectedIbanNumber);
60-
expect(result.isValidSwissIbanNumber).toBe(expectedIsValid);
48+
[null as unknown as string, { isValid: false, iban: undefined, ibanFormatted: undefined }],
49+
[undefined as unknown as string, { isValid: false, iban: undefined, ibanFormatted: undefined }],
50+
["", { isValid: false, iban: undefined, ibanFormatted: undefined }],
51+
["CH94 0076 2011 6238 5295 7", { isValid: false, iban: undefined, ibanFormatted: undefined }],
52+
["CH1000000ABC123DEF456", { isValid: false, iban: undefined, ibanFormatted: undefined }],
53+
[
54+
"CH9300762011623852957",
55+
{
56+
isValid: true,
57+
iban: "CH9300762011623852957",
58+
ibanFormatted: "CH93 0076 2011 6238 5295 7",
59+
},
60+
],
61+
[
62+
"CH3400762ABC123DEF456",
63+
{
64+
isValid: true,
65+
iban: "CH3400762ABC123DEF456",
66+
ibanFormatted: "CH34 0076 2ABC 123D EF45 6",
67+
},
68+
],
69+
[
70+
"CH93 0076 2011 6238 5295 7",
71+
{
72+
isValid: true,
73+
iban: "CH9300762011623852957",
74+
ibanFormatted: "CH93 0076 2011 6238 5295 7",
75+
},
76+
],
77+
[
78+
"CH34 0076 2ABC 123D EF45 6",
79+
{
80+
isValid: true,
81+
iban: "CH3400762ABC123DEF456",
82+
ibanFormatted: "CH34 0076 2ABC 123D EF45 6",
83+
},
84+
],
85+
])("check if the Swiss IBAN number gets parsed correctly", (unformattedSwissIbanNumber, expected) => {
86+
expect(tryParseSwissIbanNumber(unformattedSwissIbanNumber)).toEqual(expected);
6187
});
6288
});

src/lib/swissStandards.ts

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -109,41 +109,24 @@ export function isValidSwissSocialInsuranceNumber(socialInsuranceNumber: string)
109109
}
110110

111111
/**
112-
* Formats a Swiss IBAN number to the standard of "CHXX XXXX XXXX XXXX XXXX X"
113-
* @param unformattedIbanNumber the IBAN number to format
114-
* @returns a object containing the formatted IBAN number and a boolean indicating if the IBAN number was valid or not
112+
* Attempts to parse and validate a Swiss IBAN.
113+
* @param unformattedIbanNumber - The unformatted IBAN as a string
114+
* @returns The result object with the following properties:
115+
* @property {boolean} isValid - Indicates whether the IBAN is valid or not
116+
* @property {string} iban - The cleaned IBAN, only present if valid
117+
* @property {string} ibanFormatted - The formatted IBAN, only present if valid
115118
*/
116-
export function formatSwissIbanNumber(unformattedIbanNumber: string): {
117-
/**
118-
* The formatted IBAN number or the original input if the unformatted IBAN number was invalid
119-
*/
120-
ibanNumber: string;
121-
/**
122-
* The result if the IBAN number is valid or not
123-
*/
124-
isValidSwissIbanNumber: boolean;
125-
} {
126-
// 1. Check if the unformatted IBAN number is empty or only a whitespace
119+
export function tryParseSwissIbanNumber(unformattedIbanNumber?: string) {
127120
if (isNullOrWhitespace(unformattedIbanNumber)) {
128-
return { ibanNumber: unformattedIbanNumber, isValidSwissIbanNumber: false };
121+
return { isValid: false };
129122
}
130123

131-
// 2. Remove all non-alphanumeric characters and convert letters to uppercase
132-
const cleanedIbanNumber = unformattedIbanNumber.replaceAll(/[^A-Z0-9]/gi, "").toUpperCase();
133-
134-
// 3. Check if it is possible to format a new IBAN number
135-
if (!/^CH\d{19}$/.test(cleanedIbanNumber)) {
136-
return { ibanNumber: unformattedIbanNumber, isValidSwissIbanNumber: false };
137-
}
138-
139-
// 4. Format the cleaned IBAN number into groups of 4 characters separated by spaces
140-
const formattedIbanNumber = cleanedIbanNumber.replaceAll(/(.{4})/g, "$1 ").trim();
141-
142-
// 5. If the Swiss IBAN number is valid return the formatted IBAN number with the true status
143-
if (isValidSwissIbanNumber(formattedIbanNumber)) {
144-
return { ibanNumber: formattedIbanNumber, isValidSwissIbanNumber: true };
145-
}
124+
const iban = unformattedIbanNumber!.replaceAll(/[^A-Z0-9]/gi, "").toUpperCase();
125+
const isValid = isValidSwissIbanNumber(iban);
146126

147-
// 6. If the Swiss IBAN number is not valid return the formatted IBAN number with the false status
148-
return { ibanNumber: formattedIbanNumber, isValidSwissIbanNumber: false };
127+
return {
128+
isValid: isValid,
129+
iban: isValid ? iban : undefined,
130+
ibanFormatted: isValid ? iban.match(/.{1,4}/g)?.join(" ") : undefined,
131+
};
149132
}

0 commit comments

Comments
 (0)