Validation and parsing utilities every Egyptian developer ends up rewriting:
the national ID number (الرقم القومي), Egyptian phone numbers, and Arabic
text normalization for search. Zero dependencies. Targets netstandard2.0
and net8.0.
dotnet add package EgyptId.NetOr clone and reference the src/EgyptId project directly.
using EgyptId;
// --- National ID ---
var id = NationalId.TryParse("29508150100010");
if (id.IsValid)
{
Console.WriteLine(id.BirthDate); // 8/15/1995
Console.WriteLine(id.Gender); // Male
Console.WriteLine(id.GovernorateNameAr); // القاهرة
Console.WriteLine(id.GetAge()); // 31
}
// --- Phone numbers ---
EgyptianPhone.Normalize("01012345678"); // "+201012345678"
EgyptianPhone.Normalize("00201012345678"); // "+201012345678"
EgyptianPhone.Normalize("٠١٠١٢٣٤٥٦٧٨"); // "+201012345678" (Arabic digits work too)
EgyptianPhone.GetCarrier("01112345678"); // PhoneCarrier.Etisalat
EgyptianPhone.GetAreaName("0227950000"); // "Cairo / Giza"
EgyptianPhone.GetAreaName("0131234567"); // "Benha" (area 013 — a landline, not a mobile)
EgyptianPhone.FormatLocal("+201012345678"); // "01012345678" (trunk form, handy for display/dialing)
// --- Arabic search normalization ---
ArabicText.EqualsNormalized("أحمد", "احمد"); // true
ArabicText.ContainsNormalized("أهلاً وسهلاً", "اهلا"); // true| Member | Description |
|---|---|
TryParse(string) → NationalIdInfo |
Validates and decodes. Never returns null — check IsValid. |
IsValidNationalId(string) → bool |
Quick validity check. |
NationalIdInfo exposes: Number, IsValid, InvalidReason,
BirthDate, Gender (Male/Female), GovernorateCode,
GovernorateNameEn, GovernorateNameAr, CheckDigit, and
GetAge(DateTime? onDate = null).
Layout decoded: [century][YY][MM][DD][governorate][serial][check],
where century digit 2 = 1900s and 3 = 2000s, and an odd serial digit
means male / even means female. Arabic-Indic digits (٠-٩) are accepted.
The 14th digit is officially described by the civil registry as an
optional digit, and its calculation algorithm is not publicly published.
Many snippets online claim an algorithm, but none is authoritative — so
this library deliberately does not enforce the check digit. It validates
structure, real calendar date, and governorate code, and exposes the digit
as NationalIdInfo.CheckDigit for completeness. Honest validation beats a
confident-looking wrong one.
| Member | Description |
|---|---|
Normalize(string) → string? |
Any form → +20.... Accepts local (010...), trunk (0020...), national (2010...), international (+2010...), spaces/dashes, Arabic-Indic digits. Null when unrecognizable. |
FormatLocal(string) → string? |
Local trunk form: "01012345678" for mobiles, "0227950000" for landlines. Null when unrecognizable. |
IsValidMobile(string) → bool |
11-digit mobile on a known prefix. |
GetCarrier(string) → PhoneCarrier? |
Vodafone (010), Etisalat (011), Orange (012), WE (015). |
GetCarrierName(PhoneCarrier) → string |
Display name ("Etisalat e&", …). |
IsValidLandline(string) → bool |
Known area code, sane length — including Benha (013), whose numbers start with 1 but are landlines. |
GetAreaName(string, bool english = true) → string? |
e.g. "Cairo / Giza" / "القاهرة / الجيزة", "Benha" / "بنها". |
GetPhoneType(string) → PhoneType |
Mobile, Landline, or Unknown. |
| Member | Description |
|---|---|
Normalize(string) → string? |
Unifies أإآ→ا, ة→ه, ى→ي, ؤ→و, ئ→ي; strips diacritics and tatweel; collapses whitespace. |
EqualsNormalized(a, b) → bool |
Comparison after normalization. |
ContainsNormalized(text, term) → bool |
Substring search after normalization. |
dotnet build EgyptId.sln
dotnet test EgyptId.slnCI runs build + tests on every push and pull request.
MIT — see LICENSE.
