CkIntl
Job: clean and check the values that cross borders — international phone numbers, IBANs and BIC/SWIFT codes — and mask the sensitive ones for display.
US numbers live in CkUS
CkIntl is for values that carry their country with them. US-only phone numbers
without a country code — (212) 555-0123 — plus SSNs, ZIPs and routing numbers
live in CkUS.
These three values arrive from forms and files in every shape people can type them:
spaces, dashes, dots, lower case, a bracketed zero in the middle. CkIntl turns each
one into its single official form, or rejects it. The standard signal applies: a value
that cannot be used answers "" (the empty string) — non-empty in, empty out means
rejected. The two …Mask methods are the exception: made for display, they never
return empty.
Quick look
using SafeCoder.CommonKit;
CkIntl.Phone("+49 (0)151 1234567"); // -> "+491511234567"
CkIntl.Iban("de44 5001 0517 5407 3249 31"); // -> "DE44500105175407324931"
CkIntl.Bic("deutdeff"); // -> "DEUTDEFF"
CkIntl.PhoneMask("+49 (0)151 1234567"); // -> "+********4567"
CkIntl.Phone("020 7946 0958", country: "GB"); // -> "+442079460958" (national, with its country)
CkIntl.CallingCode("+41 44 668 18 00"); // -> "41"
CkIntl.Phone("555-867-5309"); // -> "" (not international, no country — rejected)
CkIntl.IbanMatchesBic("DE44500105175407324931", "DEUTDEFF"); // -> true
CkIntl.InCallingCodes("+49 151 1234567", "+49", "+43"); // -> true
CkIntl.Explain("(212) 555-0123"); // -> "no international prefix: it must start with +, 00 or 011"
CkIntl.PostalCode("k1a0b1", "CA"); // -> "K1A 0B1"
CkIntl.PostalCode("12 34", length: 4); // -> "1234" (no country: a length is the rule)
Methods
Phone
The international phone number.
string Phone(
string? input = null,
string? country = null,
string? fallback = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw phone value. |
country |
string? |
null |
The country a national number belongs to, in any spelling CkCountry accepts: "GB", "gb", "UK", "United Kingdom". Ignored when the value declares its own country code. |
fallback |
string? |
null |
Backup value used when the result would be empty. It goes through the same cleaning and checks as input, with the same country; a fallback that is itself rejected answers "". |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says why, instead of answering "", when neither the value nor the fallback can be used. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
The value (or the fallback) is a valid international number |
The E.164 form: "+491511234567" |
The E.164 form: "+491511234567" |
It is a national number and country names a country the library has a calling code for |
The E.164 form: "+442079460958" |
The same |
Rejected: missing, oversized, national with no country, an unknown country, or structurally invalid |
Empty string | Throws CkIntlException — carries Input, Expected and Reason |
Structural only — it does not know each country's numbering plan.
Returns the number in E.164 form — the worldwide standard: a +, then the country
code, then the rest, digits only, 7 to 15 in total. Spaces, dots, dashes and
parentheses between the digits are fine; a bracketed trunk zero after the country code
(the (0) in +49 (0)151 …) is dropped, and so is a trailing extension like x12.
The value may say for itself that it is international — a +, the 00 / 011 exit
codes, or an RFC 3966 tel: URI, whose scheme and parameters are not part of the
number:
CkIntl.Phone("+1 212 555 0123"); // -> "+12125550123"
CkIntl.Phone("0049 151 1234567"); // -> "+491511234567" (00 exit code)
CkIntl.Phone("011 44 20 7946 0018"); // -> "+442079460018" (US exit code)
CkIntl.Phone("+49 151 1234567 x12"); // -> "+491511234567" (extension dropped)
CkIntl.Phone("tel:+41-44-668-18-00"); // -> "+41446681800"
CkIntl.Phone("TEL:+41446681800;ext=12"); // -> "+41446681800" (the parameters go too)
CkIntl.Phone("+0 123 4567"); // -> "" (a country code cannot start with 0)
A national number, with its country
A value with no country code of its own is rejected — unless you say which country it belongs to. Then the country's trunk prefix (the digit dialled at home and dropped abroad) comes off, and its calling code goes in front:
CkIntl.Phone("020 7946 0958", country: "GB"); // -> "+442079460958" (the trunk 0 comes off)
CkIntl.Phone("(212) 555-0142", country: "US"); // -> "+12125550142"
CkIntl.Phone("1 212 555 0142", country: "US"); // -> "+12125550142" (the leading 1 is the code)
CkIntl.Phone("06 12345678", country: "IT"); // -> "+390612345678" (Italy keeps its zero)
CkIntl.Phone("8 495 123-45-67", country: "RU"); // -> "+74951234567" (Russia's trunk is 8)
CkIntl.Phone("020 7946 0958"); // -> "" (national, and nothing says whose)
A declared code always wins
CkIntl.Phone("+44 20 7946 0958", country: "IT") is "+442079460958", not an
Italian number. A value that carries its own country code is read as it stands and
country is ignored — the same way a date that declares its own offset ignores
assumeZone.
Three things about the trunk prefixes are worth knowing:
- Italy keeps its leading zero. A Roman landline is
06 …at home and+39 06 …abroad, so nothing is stripped. Spain, Portugal, Denmark, Norway, Iceland, Greece, Poland, the Czech Republic, Latvia, Estonia, Malta, Cyprus, Monaco, Luxembourg, Hong Kong, Singapore and a dozen more have no trunk prefix either. - Russia and Kazakhstan dial
8, and Hungary dials06. Belarus writes8 017 …for+375 17 …— the0belongs to the prefix, so80comes off, or the0alone when the8was left out; Lithuania is moving from8to0and both are read. - The North American plan has no trunk prefix of its own, but a leading
1is the country code — it is read as that and never doubled.
An unknown country is its own rejection, and so is a country the library has no calling code for — Antarctica, Bouvet Island, Heard Island and McDonald Islands and the French Southern Territories have none of their own.
CallingCode
The country code at the front of a number.
string CallingCode(
string? input = null,
string? country = null,
int maxLength = CkSettings.MaxPhoneIntlInputLength,
string? fallback = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw phone value. |
country |
string? |
null |
The country a national number belongs to, as Phone takes it. |
maxLength |
int |
CkSettings.MaxPhoneIntlInputLength (32) |
Longest raw value read, capped at the class limit; below 1 counts as 1. |
fallback |
string? |
null |
A spare value, held to the same rules. |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says why, instead of answering "". |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
| Phone accepts the value and a known calling code opens it | The code as one to three digits: "41", "1", "590" |
The code |
| Rejected: whatever Phone rejects, with its reason — or a prefix that belongs to no country | Empty string | Throws CkIntlException — carries Input, Expected and Reason |
The code is the E.164 country code proper, never a longer area prefix.
CkIntl.CallingCode("+41 44 668 18 00"); // -> "41"
CkIntl.CallingCode("0049 151 1234567"); // -> "49"
CkIntl.CallingCode("+1 268 464 1234"); // -> "1" (Antigua shares the plan; it is not "1268")
CkIntl.CallingCode("020 7946 0958", country: "GB"); // -> "44"
CkIntl.CallingCode("+800 1234 5678"); // -> "" (freephone: no country owns it)
There is no PhoneCountry, on purpose
+1 is the United States, Canada and twenty-odd Caribbean islands; +7 is Russia
and Kazakhstan; +44 also covers Guernsey, the Isle of Man and Jersey; +590
covers Guadeloupe, Saint Barthélemy and Saint Martin. Turning a number back into
one country needs each country's numbering plan, which this library does not
carry. Ask the caller which country a number belongs to — and pass it to
Phone as country.
Iban
The international bank account number.
string Iban(
string? input = null,
string? fallback = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw value. |
fallback |
string? |
null |
Backup value used when the result would be empty. It goes through the same cleaning and checks as input; a fallback that is itself rejected answers "". |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says why, instead of answering "", when neither the value nor the fallback can be used. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
The value (or the fallback) is a valid IBAN |
The compact upper-case IBAN: "DE44500105175407324931" |
The compact upper-case IBAN: "DE44500105175407324931" |
| Rejected: missing, oversized, malformed, the wrong length for its country, or the check digits fail | Empty string | Throws CkIntlException — carries Input, Expected and Reason |
The check digits prove the number is internally consistent, not that the account exists.
An IBAN is the international bank account number — a two-letter country, two check
digits, then the account, up to 34 characters. Iban drops spaces and dashes,
upper-cases, checks the country against the official registry, holds the value to
that country's exact length (a German IBAN is always 22 characters), and verifies the
two check digits with the standard mod-97 test — an arithmetic check that catches
nearly every typo and swapped pair of digits.
CkIntl.Iban("de44 5001 0517 5407 3249 31"); // -> "DE44500105175407324931"
CkIntl.Iban("GB82-WEST-1234-5698-7654-32"); // -> "GB82WEST12345698765432"
CkIntl.Iban("DE44500105175407324932"); // -> "" (one digit off — checksum fails)
CkIntl.Iban("DE44 5001 0517 5407 3249"); // -> "" (wrong length for DE)
An IBAN is account data — treat the result as sensitive and never log or show it
unmasked. That is what IbanMask below is for.
Bic
The bank's identifier.
string Bic(
string? input = null,
string? fallback = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw value. |
fallback |
string? |
null |
Backup value used when the result would be empty. It goes through the same cleaning and checks as input; a fallback that is itself rejected answers "". |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says why, instead of answering "", when neither the value nor the fallback can be used. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
The value (or the fallback) is a valid BIC |
The 8- or 11-character code, upper-cased: "DEUTDEFF" |
The 8- or 11-character code, upper-cased: "DEUTDEFF" |
| Rejected: missing, oversized or malformed | Empty string | Throws CkIntlException — carries Input, Expected and Reason |
No check digit — this proves the shape, not that the bank exists.
A BIC (also called a SWIFT code) names the bank itself on an international transfer: four letters of bank code, a two-letter country, a two-character location, and an optional three-character branch — 8 or 11 characters in all, upper-cased.
CkIntl.Bic("deutdeff"); // -> "DEUTDEFF"
CkIntl.Bic("deutdeff500"); // -> "DEUTDEFF500" (the branch form)
CkIntl.Bic("DEUT DE FF"); // -> "DEUTDEFF" (spaces dropped)
CkIntl.Bic("DEUTDEFF5"); // -> "" (not 8 or 11 characters)
A BIC carries no check digit, so this proves the shape only, not that the bank
exists — and the two country letters are only held to being letters, not checked
against a country list. Pair the BIC with the account's Iban, whose country is.
The two masks, PhoneMask and IbanMask, share one contract. Each mask validates
its value first (with Phone or Iban), then hides every letter and digit but the
last keepLast (default 4, capped at 4) behind maskChar (default '*'). Unlike
everything else in this class, the masks never return empty: a missing or
invalid value comes back as a fully masked placeholder, so a screen or a log line
never shows a raw or blank value. The placeholders use a middling length on
purpose — eleven digits for a phone, twenty characters for an IBAN — so they
suggest no particular country. When you also need to know whether the value was
valid, call Phone or Iban and check for "".
PostalCode
A postal code, written the way its country writes it.
string PostalCode(
string? input = null,
string? country = null,
int length = 0,
string? fallback = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw value. |
country |
string? |
null |
The country, in any spelling CkCountry accepts: "CA", "Canada", "can". Null to judge by length alone. |
length |
int |
0 |
The exact number of letters and digits, for a country without a fixed shape or no country at all. A country's own rule always wins over it. |
fallback |
string? |
null |
A spare value, held to the same rules. |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says why, instead of answering "", when neither the value nor the fallback can be used. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
| The country has a fixed shape and the value fits it | The code as that country writes it: "K1A 0B1", "SW1A 1AA", "01310-100", "10115" |
The code |
| The country has no fixed shape, or none was given, and the value is the right length | The letters and digits alone, upper-cased: "11511", "AB12" |
The code |
| Rejected: missing, oversized, an unknown country, not the country's shape, the wrong length, characters beyond letters, digits, spaces and hyphens — or no country and no length | "" |
Throws CkIntlException — carries Input, Expected and Reason |
181 countries and territories have a fixed shape here — every one that has a postal
code system — Canada's letter rules included (D, F, I, O, Q and U never appear, W and Z
never lead) and every outward-code layout of the United Kingdom. The United States, its
territories and the freely associated states hand off to CkUS.Zip. Any
country outside the table takes three to ten letters and digits, or exactly length of
them; with no country at all, length is the rule. Spaces, hyphens and a printed country
prefix, "D-10115", "LV-1010", are understood. Shape only: a code of the right shape
may still name no real area.
Where a country prints letters in front of the digits, the value reads with them or without, and the answer always carries them:
CkIntl.PostalCode("k1a0b1", "CA"); // -> "K1A 0B1"
CkIntl.PostalCode("sw1a1aa", "United Kingdom"); // -> "SW1A 1AA"
CkIntl.PostalCode("D-10115", "DE"); // -> "10115"
CkIntl.PostalCode("500", "AD"); // -> "AD500" (Andorra prints "AD")
CkIntl.PostalCode("AZ 1000", "AZ"); // -> "AZ 1000"
CkIntl.PostalCode("2001", "MD"); // -> "MD-2001"
CkIntl.PostalCode("ky11001", "KY"); // -> "KY1-1001"
CkIntl.PostalCode("tkca1zz", "TC"); // -> "TKCA 1ZZ" (the one code the islands have)
CkIntl.PostalCode("D1A 0B1", "CA"); // -> "" (D never appears in a Canadian code)
CkIntl.PostalCode("12 34", length: 4); // -> "1234" (no country: the length is the rule)
CkIntl.PostalCode("1234"); // -> "" (nothing to judge by)
PhoneMask
The phone number, safe for display.
string PhoneMask(
string? input = null,
string? country = null,
int keepLast = CkSettings.DefaultMaskKeepLast,
char maskChar = '*'
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw phone value. |
country |
string? |
null |
The country a national number belongs to, as Phone takes it — so a national number masks as the E.164 number it means. |
keepLast |
int |
CkSettings.DefaultMaskKeepLast (4) |
How many trailing digits stay visible. Capped at CkSettings.MaxMaskKeepLast (4); negatives count as 0. |
maskChar |
char |
'*' |
The replacement character. Whitespace and control characters fall back to '*'. |
Returns
| When | You get |
|---|---|
| The value is valid | The masked number: "+********4567" |
| Missing or invalid | The fully masked placeholder: "+***********" — never empty, and it never throws |
The display never leaks and never goes blank.
The phone's leading + is neither a letter nor a digit, which is why it stays
visible. A valid number keeps its real length under the mask.
CkIntl.PhoneMask("+49 (0)151 1234567"); // -> "+********4567"
CkIntl.PhoneMask("nonsense"); // -> "+***********" (the placeholder)
CkIntl.PhoneMask(
input: "+491511234567",
keepLast: 2
); // -> "+**********67"
IbanMask
The account number, safe for display.
string IbanMask(
string? input = null,
int keepLast = CkSettings.DefaultMaskKeepLast,
char maskChar = '*'
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw value. |
keepLast |
int |
CkSettings.DefaultMaskKeepLast (4) |
How many trailing characters stay visible. Capped at CkSettings.MaxMaskKeepLast (4); negatives count as 0. |
maskChar |
char |
'*' |
The replacement character. Whitespace and control characters fall back to '*'. |
Returns
| When | You get |
|---|---|
| The value is valid | The masked value: "******************4931" |
| Missing or invalid | The fully masked placeholder: "********************" — never empty, and it never throws |
The display never leaks and never goes blank.
Works like PhoneMask above, with Iban doing the validating; here everything is
hidden, the two country letters included.
CkIntl.IbanMask("DE44 5001 0517 5407 3249 31"); // -> "******************4931"
CkIntl.IbanMask(null); // -> "********************"
IsPhone
An explicitly international number?
bool IsPhone(
string? input = null,
string? country = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw phone value. |
country |
string? |
null |
The country a national number belongs to, as Phone takes it. |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says why, instead of answering false, when the value is not an international number. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
+, 00, 011 or tel: in front, then a valid E.164 structure |
true |
true |
A national number, and a country whose calling code the library knows |
true |
true |
Rejected: a bare national number with no country, a country code starting with 0, too few or too many digits, letters |
false |
Throws CkIntlException — carries Input, Expected and Reason |
The yes-or-no form of Phone, reading country the same way. US numbers can
be judged here with country: "US", but CkUS also enforces the NANP's own
rules and is the better reader where every number is American.
CkIntl.IsPhone("+49 (0)151 1234567"); // -> true
CkIntl.IsPhone("(212) 555-0123"); // -> false (not international, no country)
CkIntl.IsPhone("(212) 555-0123", country: "US"); // -> true
IsIban
A valid IBAN?
bool IsIban(
string? input = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw value. |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says why, instead of answering false, when the value is not an IBAN. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
| A known country, that country's exact length, and check digits that pass the mod-97 test | true |
true |
| Rejected: an unknown country, the wrong length, failing check digits, junk | false |
Throws CkIntlException — carries Input, Expected and Reason |
The yes-or-no form of Iban; the check digits catch nearly every typo, as they do there.
CkIntl.IsIban("de44 5001 0517 5407 3249 31"); // -> true
CkIntl.IsIban("DE44500105175407324932"); // -> false (one digit off)
IsBic
A BIC of the right shape?
bool IsBic(
string? input = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw value. |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says why, instead of answering false, when the value is not a BIC. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
| Four letters, a two-letter country, a two-character location, an optional three-character branch | true |
true |
| Rejected: the wrong length, a digit where a letter belongs, junk | false |
Throws CkIntlException — carries Input, Expected and Reason |
The yes-or-no form of Bic. A BIC alone proves little — no check digit, no country list — so pair it with IbanMatchesBic.
CkIntl.IsBic("deutdeff500"); // -> true (the branch form)
CkIntl.IsBic("DEUTDEF"); // -> false (seven characters)
IsPostalCode
Is it a postal code of that country?
bool IsPostalCode(
string? input = null,
string? country = null,
int length = 0,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw value. |
country |
string? |
null |
The country, in any spelling; null to judge by length alone. |
length |
int |
0 |
The exact number of letters and digits when no country rule applies. |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says why, instead of answering false, when the value is not a postal code. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
| PostalCode would answer a code | true |
true |
It would answer "" |
false |
Throws CkIntlException — carries Input, Expected and Reason |
The yes-or-no form of PostalCode, under exactly its rules.
CkIntl.IsPostalCode("K1A 0B1", "CA"); // -> true
CkIntl.IsPostalCode("D1A 0B1", "CA"); // -> false
CkIntl.IsPostalCode("1234", length: 4); // -> true
SamePhone
The same line, whatever the spelling?
bool SamePhone(
string? a = null,
string? b = null,
string? country = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
a |
string? |
null |
The first value. |
b |
string? |
null |
The second value. |
country |
string? |
null |
The country a national value belongs to, applied to both sides — so a national number and its international spelling are one line. Ignored for a value that declares its own code. |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says which value is not an international number and why, instead of answering false. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
| Both are valid international numbers and the same one | true |
true |
| Both are valid, and differ | false |
false |
| Rejected: either is not an international number | false |
Throws CkIntlException — carries Input, Expected and Reason |
"+49 (0)151 1234567", "0049 151 1234567" and "+491511234567" are one line.
Extensions are dropped by the reader, as Phone drops them, so two extensions on
one line count as the same number. Two values that are not numbers are never the same.
CkIntl.SamePhone("+49 (0)151 1234567", "0049 151 1234567"); // -> true
CkIntl.SamePhone("+49 151 1234567", "0151 1234567"); // -> false (one is not international)
CkIntl.SamePhone("+49 151 1234567", "0151 1234567", country: "DE"); // -> true (now it is)
SameIban
The same account, whatever the spelling?
bool SameIban(
string? a = null,
string? b = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
a |
string? |
null |
The first value. |
b |
string? |
null |
The second value. |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says which value is not an IBAN and why, instead of answering false. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
| Both are valid IBANs and the same one | true |
true |
| Both are valid, and differ | false |
false |
| Rejected: either is not an IBAN | false |
Throws CkIntlException — carries Input, Expected and Reason |
"de44 5001 0517 5407 3249 31" and "DE44500105175407324931" are one account. For
reconciling bank details between a form and a record. Two values that fail their check
digits are two unknowns, never the same.
CkIntl.SameIban("de44 5001 0517 5407 3249 31", "DE44500105175407324931"); // -> true
IbanMatchesBic
Do the IBAN and the BIC agree on the country?
bool IbanMatchesBic(
string? iban = null,
string? bic = null,
bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
iban |
string? |
null |
The raw IBAN. |
bic |
string? |
null |
The raw BIC. |
throwIfInvalid |
bool |
CkSettings.DefaultThrowIfInvalid (false) |
Pass true to throw a CkIntlException that says which value cannot be used and why, instead of answering false. |
Returns
| When | Default | With throwIfInvalid: true |
|---|---|---|
| Both are valid and the IBAN's first two letters equal the BIC's fifth and sixth | true |
true |
| Both are valid, and the countries differ | false |
false |
| Rejected: either cannot be used | false |
Throws CkIntlException — carries Input, Expected and Reason |
The consistency check a payment form should run: a BIC alone proves little, and a mismatched pair is the commonest bank-detail typo. Countries only — whether the BIC's bank code matches the bank inside the IBAN would need a registry the library does not carry.
CkIntl.IbanMatchesBic("DE44500105175407324931", "DEUTDEFF"); // -> true
CkIntl.IbanMatchesBic("DE44500105175407324931", "BNPAFRPP"); // -> false (a French bank)
InCallingCodes
From one of these countries' numbering plans?
bool InCallingCodes(
string? input = null,
params IEnumerable<string?> codes
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw phone value. |
codes |
params IEnumerable<string?> |
— | The calling codes to accept, with or without +. Entries with no digits, or starting with 0, are skipped. |
Returns
| When | You get |
|---|---|
| The value is a valid international number whose digits start with a listed code | true |
| It is not international, no code matches, or the list is empty | false — an answer, not a failure; it never throws |
"Which countries' numbers we accept", the SMS-delivery rule. Calling codes are
prefix-free by design, so a prefix match is exact: "+49" matches every German number
and nothing else. No numbering-plan table is involved: "+1" means the whole North
American plan, and "+7" Russia and Kazakhstan alike, because they share it. A longer
entry such as "+1212" narrows the match to that area. A params list must be last, so
there is no throwIfInvalid; call Phone with it first when you need the exception.
CkIntl.InCallingCodes("+49 151 1234567", "+49", "43", "+41"); // -> true
CkIntl.InCallingCodes("+33 6 12 34 56 78", "+49", "43", "+41"); // -> false
IbanInCountries
A bank in one of these countries?
bool IbanInCountries(
string? input = null,
params IEnumerable<string?> countries
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw IBAN. |
countries |
params IEnumerable<string?> |
— | The countries to accept, in any form CkCountry reads: codes, names, aliases. Entries that are not recognised are skipped. |
Returns
| When | You get |
|---|---|
| The value is a valid IBAN and an entry names its country | true |
| It is not a valid IBAN, no entry matches, or the list is empty | false — an answer, not a failure; it never throws |
The SEPA-zone and "banks we can pay" check, with your list: the IBAN's first two letters
against each entry read the way CkCountry.Alpha2 reads a country,
so "Germany", "de" and "DEU" all name the same one. A params list must be last, so
there is no throwIfInvalid; call Iban with it first when you need the exception.
CkIntl.IbanInCountries("DE44500105175407324931", "DE", "France", "NLD"); // -> true
CkIntl.IbanInCountries("GB29 NWBK 6016 1331 9268 19", "DE", "France"); // -> false
Explain
Why not — in words, without an exception.
string Explain(
string? input = null,
string? what = nameof(Phone),
string? country = null,
int length = 0
)
| Parameter | Type | Default | What it does |
|---|---|---|---|
input |
string? |
null |
The raw value. |
what |
string? |
nameof(Phone) |
The reader to judge by: Phone, CallingCode, Iban, Bic or PostalCode, case-insensitive. |
country |
string? |
null |
For Phone and CallingCode: the country a national number belongs to. For PostalCode: the country, in any spelling. |
length |
int |
0 |
For PostalCode: the exact number of letters and digits when no country rule applies. |
Returns
| When | You get |
|---|---|
| The value passes the reader | "" |
| It does not | The reason, the same words the exception would carry — an answer, not a failure; it never throws |
The form-friendly twin of throwIfInvalid: the message to show beside the field,
without a try and catch. Every class with a reader has one, on the reader's own
rules, so the reason is exactly what the reader would say. what names the reader to judge by.
CkIntl.Explain("(212) 555-0123"); // -> "no international prefix: it must start with +, 00 or 011"
CkIntl.Explain("DEUTDEF", nameof(CkIntl.Bic)); // -> "not 8 or 11 characters"
CkIntl.Explain("(212) 555-0123", country: "US"); // -> "" (a country makes it readable)
The fallback
Phone, CallingCode, Iban, Bic and PostalCode each take a fallback — a spare
value used when the input is rejected. The fallback goes through the exact same cleaning and checking; a bad
fallback answers "" too. The masks take no fallback — their placeholder is the
fallback — and neither do the validators, whose answer is false.
CkIntl.Phone(
input: "n/a",
fallback: "+1 212 555 0123"
); // -> "+12125550123"
Good to know
- Non-empty in, empty out means rejected. That is the standard CommonKit signal —
check for
""where it matters. Neednullinstead? Wrap the call inCkText.NullIfEmpty(...)— see How it works. Phonenever guesses a country. No+,00,011ortel:at the front means rejection, unless you passcountryand say whose national number it is. US numbers like(212) 555-0123are also at home in CkUS'sPhone, which enforces the NANP's own rules on top.countryis ignored when the value declares its own code. A declared code always wins, and there is noPhoneCountryto go the other way — see CallingCode.- The checks are structural, not real-world.
Phonedoes not know each country's numbering plan, and an IBAN's check digits prove the number is internally consistent, not that the account exists. - Extensions are dropped, not returned.
x12,ext. 12or#12at the end disappears from the result; keep it separately if you need it. - The masks never return empty — by design. An invalid value looks exactly like a hidden valid one; a display has nothing to leak either way.
- A BIC alone proves little. No check digit, and its country letters are not
checked against a country list — validate the matching IBAN too, and run
IbanMatchesBicon the pair. - The validators answer
falsefor junk too.IsPhone,IsIban,IsBicand the pair checks answerfalseboth for "no" and for "not usable"; passthrowIfInvalid: truewhen the difference matters.InCallingCodesandIbanInCountriesnever take the flag. InCallingCodesknows no numbering plan. It matches the codes you list as prefixes of the E.164 digits, which is exact because calling codes are prefix-free; it cannot tell Russia from Kazakhstan on+7, and neither can anyone without a table.
If you want errors instead
Pass throwIfInvalid: true to Phone, CallingCode, Iban, Bic, PostalCode or any
validator but the two
params ones, and a value that cannot be used raises a CkIntlException (from SafeCoder.CommonKit.Exceptions) instead of
answering "" or false. The exception carries the Input, what was Expected and a short
Reason, flattened into a one-line message. The masks take no throwIfInvalid —
they always answer with a masked shape.
CkIntl.Iban(
input: "DE44500105175407324932",
throwIfInvalid: true
); // throws CkIntlException — "the check digits do not match"