Multiverse 2.0.46
dotnet add package Multiverse --version 2.0.46
NuGet\Install-Package Multiverse -Version 2.0.46
<PackageReference Include="Multiverse" Version="2.0.46" />
<PackageVersion Include="Multiverse" Version="2.0.46" />
<PackageReference Include="Multiverse" />
paket add Multiverse --version 2.0.46
#r "nuget: Multiverse, 2.0.46"
#:package Multiverse@2.0.46
#addin nuget:?package=Multiverse&version=2.0.46
#tool nuget:?package=Multiverse&version=2.0.46
Multiverse
Multiverse is a lightweight, zero-dependency .NET library that provides a comprehensive, standards-compliant dataset of countries, currencies, and languages from around the globe — making it an essential building block for internationalization (i18n) and localization (l10n) in any .NET application.
Country is the central entity. Each country carries its own Currency object and OfficialLanguages list, so a single lookup gives you everything you need — no cross-referencing required.
Table of Contents
- Features
- Supported Frameworks
- Installation
- Quick Start
- Countries
- Currencies
- Languages
- Holidays
- Time Zones
- Extended Country Data
- Exception Handling
- Best Practices
- API Reference Summary
- Testing
- Release Notes
- Contributing
- License
Features
| Capability | Standard | Coverage |
|---|---|---|
| Countries | ISO 3166-1 (alpha-2, alpha-3, numeric) + E.164 calling codes | 250 countries & territories with capitals, regions, sub-regions, demonyms, TLDs, currencies, official languages, holidays, time zones & flag emojis |
| Extended Country Data | Geographic, political & transport metadata | Population, area, capital coordinates, bordering countries, driving side, speed units, independence dates, UN membership, landlocked status for all 250 countries |
| Currencies | ISO 4217 (code, numeric) | 150+ world currencies with decimal places (minor units) and reverse country lookup |
| Languages | ISO 639-1 & ISO 639-2 (alpha-2, alpha-3) | 475+ languages with native names, scripts & text direction (LTR/RTL) |
| Holidays | Fixed-date public holidays | Public, national, religious, bank & observance holidays for 190+ countries |
| Movable Holidays | Date-varies-by-year holidays | Easter, Thanksgiving, and other movable holidays for 40+ countries |
| Time Zones | IANA Time Zone Database | UTC offsets, DST support, and country-to-zone mapping for 250 countries & territories |
| Electrical Systems | Plug types, voltage & frequency | Electrical system data for all 250 countries |
| Emergency Numbers | Emergency telephone numbers | Police, fire, ambulance numbers for all 250 countries |
| Phone Formats | International phone formatting | Calling codes, trunk prefixes, phone number lengths for all 250 countries |
| Locale & Formatting | Date, number & measurement formats | Date format, number separators, measurement systems, postal code formats for all 250 countries |
| Translations | Country name translations | Country names in 10+ languages for all 250 countries |
| Subdivisions | ISO 3166-2 | States, provinces, regions for 50+ countries |
- Country-centric design — each
Countrycarries itsCurrencyandOfficialLanguages; one lookup gives you everything - Fast lookups — pre-built dictionary maps for O(1) retrieval by code, name, or number
- Case-insensitive — all lookups normalize input automatically
- Null-safe —
OrDefaultvariants returnnullinstead of throwing - Zero dependencies — no third-party packages required
- Immutable data — all entries are
readonlysingletons; thread-safe by design - Cross-platform — targets
net9.0,net8.0,net7.0,net6.0,netstandard2.0, andnet462
Supported Frameworks
| Target | Supported Versions |
|---|---|
| .NET | 6.0, 7.0, 8.0, 9.0 |
| .NET Standard | 2.0 |
| .NET Framework | 4.6.2 |
Any runtime that implements .NET Standard 2.0 or higher is supported (including .NET Core 2.0+, Mono 5.4+, Xamarin, Unity, and MAUI).
Installation
Package Manager Console
Install-Package Multiverse
.NET CLI
dotnet add package Multiverse
PackageReference
<PackageReference Include="Multiverse" Version="2.0.40" />
Quick Start
using Multiverse.Globalization.Countries;
using Multiverse.Globalization.Currencies;
using Multiverse.Globalization.Languages;
// Country — the single source of truth
var pakistan = Country.GetCountry("PK");
Console.WriteLine($"{pakistan.Flag} {pakistan.Name}"); // 🇵🇰 Pakistan
Console.WriteLine($"Capital: {pakistan.Capital}"); // Capital: Islamabad
Console.WriteLine($"Region: {pakistan.Region}"); // Region: Asia
Console.WriteLine($"Sub-Region: {pakistan.SubRegion}"); // Sub-Region: Southern Asia
Console.WriteLine($"Demonym: {pakistan.Demonym}"); // Demonym: Pakistani
Console.WriteLine($"TLD: {pakistan.TLD}"); // TLD: .pk
Console.WriteLine($"Calling Code: {pakistan.CallingCode}"); // Calling Code: +92
// Extended data — geographic, political, transport
Console.WriteLine($"Population: {pakistan.Population:N0}"); // Population: 231,402,117
Console.WriteLine($"UN Member: {pakistan.IsUnMember}"); // UN Member: True
Console.WriteLine($"Drives on: {pakistan.DrivingSide}"); // Drives on: Left
// Currency — accessed directly from the country
Console.WriteLine($"Currency: {pakistan.Currency!.Name}"); // Currency: Pakistan Rupee
Console.WriteLine($" Code: {pakistan.CurrencyCode}"); // Code: PKR
Console.WriteLine($" Symbol: {pakistan.Currency.Symbol}"); // Symbol: ₨
// Official Languages — accessed directly from the country
foreach (var lang in pakistan.OfficialLanguages)
Console.WriteLine($" Language: {lang.Name} ({lang.Alpha2Code})");
// Language: Urdu (ur)
// Language: English (en)
// Standalone currency & language lookups still work
var eur = Currency.GetCurrency("EUR");
Console.WriteLine($"{eur.Name} {eur.Symbol}"); // Euro €
var french = Language.GetLanguage("fr");
Console.WriteLine($"{french.Name} ({french.Alpha2Code})"); // French (fr)
Countries
Namespace: Multiverse.Globalization.Countries
The Country class is the central entity of Multiverse. Each country object provides access to 250 countries and territories based on ISO 3166-1, and carries its own Currency and OfficialLanguages — so a single lookup gives you everything about a country.
Country Properties
| Property | Type | Description | Example |
|---|---|---|---|
Name |
string |
Official country name | "Pakistan" |
Alpha2Code |
string |
ISO 3166-1 alpha-2 (2-letter code) | "PK" |
Alpha3Code |
string |
ISO 3166-1 alpha-3 (3-letter code) | "PAK" |
NumericCode |
string |
ISO 3166-1 numeric (3-digit code) | "586" |
CallingCode |
string |
International dialing code (E.164) | "+92" |
Capital |
string |
Capital city name | "Islamabad" |
Region |
string |
Geographic region / continent | "Asia" |
SubRegion |
string |
UN M49 sub-region | "Southern Asia" |
Demonym |
string |
What residents of the country are called | "Pakistani" |
TLD |
string |
Country-code top-level domain | ".pk" |
Currency |
Currency? |
Full currency object (nullable for territories with no currency) | CurrencyHelper.PakistanRupee |
CurrencyCode |
string |
ISO 4217 code derived from Currency (empty if no currency) |
"PKR" |
OfficialLanguages |
IReadOnlyList<Language> |
Official languages of the country | [Urdu, English] |
Holidays |
IReadOnlyList<Holiday> |
Public holidays observed in the country | [Pakistan Day, Independence Day, ...] |
TimeZones |
IReadOnlyList<CountryTimeZone> |
IANA time zones observed in the country | [Asia/Karachi (UTC+05:00)] |
HasMultipleTimeZones |
bool |
Whether the country spans more than one time zone | false |
Flag |
string |
Unicode flag emoji (computed from Alpha2Code) | 🇵🇰 |
Population |
long |
Approximate population count | 231402117 |
AreaInSquareKilometers |
double |
Total area in square kilometers | 881912.0 |
CapitalCoordinates |
GeoCoordinate? |
Latitude/longitude of the capital city | (33.6844, 73.0479) |
BorderingCountries |
IReadOnlyList<string> |
Alpha-2 codes of bordering countries | ["AF","CN","IN","IR"] |
IsLandlocked |
bool |
Whether the country has no coastline | false |
IsUnMember |
bool |
Whether the country is a UN member | true |
IndependenceDate |
DateTime? |
Date of independence (null for territories) | 1947-08-14 |
DrivingSide |
DrivingSide |
Which side of the road vehicles drive on | DrivingSide.Left |
SpeedUnit |
string |
Speed unit used in the country | "km/h" |
AlternativeTlds |
IReadOnlyList<string> |
Alternative country-code TLDs | [".uk"] (for GB) |
ElectricalSystem |
ElectricalSystem? |
Plug types, voltage & frequency | 230V, 50Hz, [C, D] |
EmergencyNumbers |
IReadOnlyList<string> |
Emergency telephone numbers | ["15","115","1122"] |
PhoneFormat |
PhoneFormat? |
Phone number format information | +92, 0, [10] |
Locale |
CountryLocale? |
Locale & formatting conventions | dd/MM/yyyy, Metric |
Translations |
IReadOnlyDictionary<string, string> |
Country name in multiple languages | {"fr":"Pakistan","es":"Pakistán"} |
Subdivisions |
IReadOnlyList<Subdivision> |
ISO 3166-2 administrative subdivisions | [Punjab, Sindh, ...] |
MovableHolidays |
IReadOnlyList<MovableHoliday> |
Movable holidays (dates vary by year) | [Shab-e-Meraj, ...] |
Accessing a Country's Currency
Every country carries a full Currency object — no need for a separate lookup:
var japan = Country.GetCountry("JP");
// Access the Currency object directly
Currency yen = japan.Currency!;
Console.WriteLine(yen.Name); // Yen
Console.WriteLine(yen.Code); // JPY
Console.WriteLine(yen.Symbol); // ¥
Console.WriteLine(yen.Number); // 392
// Or use the convenience CurrencyCode property
Console.WriteLine(japan.CurrencyCode); // JPY
// Some territories have no official currency
var antarctica = CountryHelper.Antarctica;
Console.WriteLine(antarctica.Currency is null); // True
Console.WriteLine(antarctica.CurrencyCode); // (empty string)
Accessing a Country's Official Languages
Each country carries its official languages as a IReadOnlyList<Language>:
var switzerland = Country.GetCountry("CH");
Console.WriteLine($"{switzerland.Name} has {switzerland.OfficialLanguages.Count} languages:");
foreach (var lang in switzerland.OfficialLanguages)
Console.WriteLine($" {lang.Name} ({lang.Alpha2Code}/{lang.Alpha3Code})");
// Switzerland has 3 languages:
// German (de/ger)
// French (fr/fre)
// Italian (it/ita)
// Countries with one official language
var france = Country.GetCountry("FR");
Console.WriteLine($"{france.Name}: {france.OfficialLanguages[0].Name}"); // France: French
// Antarctica has no official languages
var aq = CountryHelper.Antarctica;
Console.WriteLine(aq.OfficialLanguages.Count); // 0
Accessing a Country's Holidays
Each country carries its public holidays as an IReadOnlyList<Holiday>:
var usa = Country.GetCountry("US");
Console.WriteLine($"{usa.Name} has {usa.Holidays.Count} holidays:");
foreach (var holiday in usa.Holidays)
Console.WriteLine($" {holiday.Name} — {holiday.Month:D2}/{holiday.Day:D2} ({holiday.Type})");
// United States of America has 10 holidays:
// New Year's Day — 01/01 (Public)
// Martin Luther King Jr. Day — 01/20 (Public)
// ...
// Independence Day — 07/04 (National)
// Christmas Day — 12/25 (Religious)
// Filter by type
var nationalHolidays = usa.GetHolidaysByType(HolidayType.National);
Console.WriteLine($"National holidays: {nationalHolidays.Count}"); // 1 (Independence Day)
// Check if a date is a holiday
bool isHoliday = usa.IsPublicHoliday(new DateTime(2026, 7, 4)); // true
bool isNotHoliday = usa.IsPublicHoliday(new DateTime(2026, 3, 15)); // false
// Get the holiday on a given date
var holiday = usa.GetHolidayOnDate(new DateTime(2026, 7, 4));
Console.WriteLine(holiday?.Name); // Independence Day
// Countries with no holiday data return an empty list
var none = CountryHelper.None;
Console.WriteLine(none.Holidays.Count); // 0
Accessing a Country's Time Zones
Each country carries its IANA time zones as an IReadOnlyList<CountryTimeZone>:
var usa = Country.GetCountry("US");
Console.WriteLine($"{usa.Name} has {usa.TimeZones.Count} time zones:");
foreach (var tz in usa.TimeZones)
Console.WriteLine($" {tz.IanaId} — {tz.UtcOffsetString}{(tz.ObservesDst ? " (DST)" : "")}");
// United States of America has 7 time zones:
// America/New_York — UTC-05:00 (DST)
// America/Chicago — UTC-06:00 (DST)
// America/Denver — UTC-07:00 (DST)
// America/Los_Angeles — UTC-08:00 (DST)
// America/Anchorage — UTC-09:00 (DST)
// Pacific/Honolulu — UTC-10:00
// America/Phoenix — UTC-07:00
// Single-zone countries
var pakistan = Country.GetCountry("PK");
Console.WriteLine($"{pakistan.Name}: {pakistan.GetPrimaryTimeZone()}");
// Pakistan: Asia/Karachi (UTC+05:00)
// Check if country spans multiple zones
Console.WriteLine(usa.HasMultipleTimeZones); // True
Console.WriteLine(pakistan.HasMultipleTimeZones); // False
// Get zones that observe DST
var dstZones = usa.GetTimeZonesWithDst();
Console.WriteLine($"{dstZones.Count} zones observe DST"); // 5 zones observe DST
// Get distinct UTC offsets
var offsets = usa.GetUtcOffsets();
Console.WriteLine($"{offsets.Count} distinct offsets"); // 6 distinct offsets
Lookup Country by Identifier
An identifier can be any of: alpha-2 code, alpha-3 code, numeric code, or the full country name.
// Strict lookup — throws CountryNotFoundException if not found
Country usa = Country.GetCountry("US");
Country uk = Country.GetCountry("GBR");
Country pk = Country.GetCountry("586");
Country fr = Country.GetCountry("France");
// Safe lookup — returns null if not found
Country? country = Country.GetCountryOrDefault("XX"); // null
Validate a Country Identifier
bool valid = Country.IsValid("US"); // true
bool valid2 = Country.IsValid("USA"); // true
bool valid3 = Country.IsValid("840"); // true
bool invalid = Country.IsValid("XYZ"); // false
bool empty = Country.IsValid(""); // false
bool caseOk = Country.IsValid("us"); // true (case-insensitive)
Get All Countries
List<Country> countries = Country.GetAll();
foreach (var c in countries)
{
Console.WriteLine($"{c.Flag} {c.Alpha2Code} - {c.Name} ({c.CurrencyCode})");
}
Direct Access via CountryHelper
For compile-time access without string lookups, use CountryHelper fields directly:
var pakistan = CountryHelper.Pakistan;
Console.WriteLine(pakistan.Alpha2Code); // PK
Console.WriteLine(pakistan.Alpha3Code); // PAK
Console.WriteLine(pakistan.NumericCode); // 586
Console.WriteLine(pakistan.CallingCode); // +92
Console.WriteLine(pakistan.Capital); // Islamabad
Console.WriteLine(pakistan.Region); // Asia
Console.WriteLine(pakistan.SubRegion); // Southern Asia
Console.WriteLine(pakistan.Demonym); // Pakistani
Console.WriteLine(pakistan.TLD); // .pk
Console.WriteLine(pakistan.CurrencyCode); // PKR
Console.WriteLine(pakistan.Currency!.Name); // Pakistan Rupee
Console.WriteLine(pakistan.Currency.Symbol); // ₨
Console.WriteLine(pakistan.OfficialLanguages[0].Name); // Urdu
Console.WriteLine(pakistan.OfficialLanguages[1].Name); // English
Console.WriteLine(pakistan.Holidays.Count); // 6
Console.WriteLine(pakistan.TimeZones[0].IanaId); // Asia/Karachi
Console.WriteLine(pakistan.TimeZones[0].UtcOffsetString); // UTC+05:00
Console.WriteLine(pakistan.HasMultipleTimeZones); // False
Console.WriteLine(pakistan.Flag); // 🇵🇰
var none = CountryHelper.None; // Empty sentinel value
Currencies
Namespace: Multiverse.Globalization.Currencies
The Currency class provides access to 150+ world currencies based on the ISO 4217 standard.
Tip: You can also reach a country's currency directly via
Country.Currency— see Accessing a Country's Currency.
Currency Properties
| Property | Type | Description | Example |
|---|---|---|---|
Name |
string |
Currency name | "US Dollar" |
Code |
string |
ISO 4217 alphabetic code | "USD" |
Number |
int |
ISO 4217 numeric code | 840 |
Symbol |
string |
Currency symbol | "$" |
DecimalPlaces |
int |
Minor units (decimal places) | 2 (most currencies), 0 (JPY), 3 (KWD) |
Lookup Currency by Identifier
An identifier (string) can be the ISO code or the full currency name.
// Strict lookup — throws CurrencyNotFoundException if not found
Currency usd = Currency.GetCurrency("USD");
Currency eur = Currency.GetCurrency("Euro");
Console.WriteLine($"{usd.Code} - {usd.Name} ({usd.Symbol})"); // USD - US Dollar ($)
// Safe lookup — returns null if not found
Currency? unknown = Currency.GetCurrencyOrDefault("XYZ"); // null
Lookup Currency by Numeric Code
// Strict lookup
Currency gbp = Currency.GetCurrency(826);
Console.WriteLine(gbp.Name); // Pound Sterling
// Safe lookup
Currency? missing = Currency.GetCurrencyOrDefault(9999); // null
Validate a Currency Identifier
// By code or name
bool valid = Currency.IsValid("USD"); // true
bool valid2 = Currency.IsValid("Euro"); // true
bool valid3 = Currency.IsValid("usd"); // true (case-insensitive)
bool invalid = Currency.IsValid("FAKE"); // false
// By numeric code
bool validNum = Currency.IsValid(840); // true
bool invalidNum = Currency.IsValid(9999); // false
Get All Currencies
List<Currency> currencies = Currency.GetAll();
foreach (var c in currencies)
{
Console.WriteLine($"{c.Code} ({c.Number}) - {c.Name} {c.Symbol}");
}
Direct Access via CurrencyHelper
var pkr = CurrencyHelper.PakistanRupee;
Console.WriteLine($"{pkr.Code} - {pkr.Symbol}"); // PKR - ₨
var inr = CurrencyHelper.IndianRupee;
Console.WriteLine($"{inr.Code} - {inr.Symbol}"); // INR - ₹
Languages
Namespace: Multiverse.Globalization.Languages
The Language class provides access to 475+ languages based on the ISO 639-1 (alpha-2) and ISO 639-2 (alpha-3) standards.
Tip: You can also reach a country's official languages directly via
Country.OfficialLanguages— see Accessing a Country's Official Languages.
Language Properties
| Property | Type | Description | Example |
|---|---|---|---|
Name |
string |
Language name (may include alternates) | "Spanish; Castilian" |
Alpha2Code |
string |
ISO 639-1 code (2-letter, may be empty) | "es" |
Alpha3Code |
string |
ISO 639-2 code (3-letter) | "spa" |
NativeName |
string |
Native name of the language | "Español" |
Script |
string |
Primary writing script | "Latin", "Arabic", "Cyrillic" |
TextDirection |
TextDirection |
Text direction (LTR or RTL) | TextDirection.LeftToRight |
Note: Not all languages have an alpha-2 code. Languages that only exist in ISO 639-2 will have an empty
Alpha2Code.
Lookup Language by Identifier
An identifier can be the alpha-2 code, alpha-3 code, or the full language name.
// Strict lookup — throws LanguageNotFoundException if not found
Language english = Language.GetLanguage("en");
Language arabic = Language.GetLanguage("ara");
Language hindi = Language.GetLanguage("Hindi");
Console.WriteLine($"{english.Name} ({english.Alpha2Code}/{english.Alpha3Code})");
// English (en/eng)
// Safe lookup — returns null if not found
Language? unknown = Language.GetLanguageOrDefault("xyz"); // null
Validate a Language Identifier
bool valid = Language.IsValid("en"); // true
bool valid2 = Language.IsValid("eng"); // true
bool valid3 = Language.IsValid("English"); // true
bool caseOk = Language.IsValid("EN"); // true (case-insensitive)
bool invalid = Language.IsValid("xx"); // false
bool empty = Language.IsValid(""); // false
Get All Languages
List<Language> languages = Language.GetAll();
foreach (var l in languages)
{
Console.WriteLine($"{l.Alpha2Code,-4} {l.Alpha3Code,-5} {l.Name}");
}
Direct Access via LanguageHelper
var urdu = LanguageHelper.Urdu;
Console.WriteLine($"{urdu.Alpha2Code} / {urdu.Alpha3Code} – {urdu.Name}");
// ur / urd – Urdu
var none = LanguageHelper.None; // Empty sentinel value
Holidays
Namespace: Multiverse.Globalization.Holidays
The Holiday class provides access to fixed-date public holidays for 190+ countries around the world. Holidays are accessed directly through the Country object — each country carries its own holidays.
Tip: You can reach a country's holidays directly via
Country.Holidays— see Accessing a Country's Holidays.
Holiday Properties
| Property | Type | Description | Example |
|---|---|---|---|
Name |
string |
Holiday name | "Independence Day" |
Month |
int |
Month of the holiday (1–12) | 7 |
Day |
int |
Day of the holiday (1–31) | 4 |
Type |
HolidayType |
Category of the holiday | HolidayType.National |
Date |
DateTime |
The holiday date in the current year | 2026-07-04 |
Accessing Holidays from a Country
var pakistan = Country.GetCountry("PK");
foreach (var holiday in pakistan.Holidays)
Console.WriteLine($"{holiday.Name} — {holiday.Month:D2}/{holiday.Day:D2} ({holiday.Type})");
// Kashmir Day — 02/05 (Observance)
// Pakistan Day — 03/23 (National)
// Labour Day — 05/01 (Public)
// Independence Day — 08/14 (National)
// Iqbal Day — 11/09 (National)
// Quaid-e-Azam Day — 12/25 (National)
var japan = Country.GetCountry("JP");
Console.WriteLine($"Japan has {japan.Holidays.Count} holidays"); // Japan has 12 holidays
Filtering Holidays by Type
var france = Country.GetCountry("FR");
// Get only national holidays
var national = france.GetHolidaysByType(HolidayType.National);
foreach (var h in national)
Console.WriteLine($"{h.Name} — {h.Month:D2}/{h.Day:D2}");
// Victory in Europe Day — 05/08
// Bastille Day — 07/14
// Armistice Day — 11/11
// Get religious holidays
var religious = france.GetHolidaysByType(HolidayType.Religious);
Console.WriteLine(religious.Count); // 3 (Assumption, All Saints', Christmas)
Checking if a Date is a Holiday
var india = Country.GetCountry("IN");
// Check if a date falls on a holiday
bool isHoliday = india.IsPublicHoliday(new DateTime(2026, 1, 26)); // true (Republic Day)
bool isNot = india.IsPublicHoliday(new DateTime(2026, 3, 15)); // false
// Get the specific holiday on a date
var holiday = india.GetHolidayOnDate(new DateTime(2026, 8, 15));
Console.WriteLine(holiday?.Name); // Independence Day
// Get the date of a holiday in a specific year
var republicDay = india.Holidays.First(h => h.Name == "Republic Day");
Console.WriteLine(republicDay.GetDate(2026)); // 2026-01-26
// Check using Holiday.IsOnDate()
Console.WriteLine(republicDay.IsOnDate(new DateTime(2026, 1, 26))); // true
Holiday Types
| Type | Description |
|---|---|
Public |
A national public holiday observed across the entire country |
Bank |
A bank/government holiday — offices close, but not all businesses |
Religious |
A religious or observance-based holiday |
National |
A national/independence/republic day |
Observance |
A commemoration or remembrance day |
Time Zones
Namespace: Multiverse.Globalization.TimeZones
The CountryTimeZone class provides access to IANA time zone data for all 250 countries and territories. Time zones are accessed directly through the Country object — each country carries its own time zone list.
Standard: Uses the IANA Time Zone Database (also known as the Olson database / tz database), the global standard for time zone identifiers used by Linux, macOS, Java, JavaScript, Go, Python, and .NET 6+.
Tip: You can reach a country's time zones directly via
Country.TimeZones— see Accessing a Country's Time Zones.
Time Zone Properties
| Property | Type | Description | Example |
|---|---|---|---|
IanaId |
string |
IANA time zone identifier | "America/New_York" |
UtcOffsetHours |
double |
Standard UTC offset in hours | -5.0 |
ObservesDst |
bool |
Whether this zone observes Daylight Saving Time | true |
UtcOffset |
TimeSpan |
UTC offset as a TimeSpan |
-05:00:00 |
UtcOffsetString |
string |
Formatted UTC offset string | "UTC-05:00" |
Accessing Time Zones from a Country
var usa = Country.GetCountry("US");
foreach (var tz in usa.TimeZones)
Console.WriteLine($"{tz.IanaId} — {tz.UtcOffsetString}{(tz.ObservesDst ? " (DST)" : "")}");
// America/New_York — UTC-05:00 (DST)
// America/Chicago — UTC-06:00 (DST)
// America/Denver — UTC-07:00 (DST)
// America/Los_Angeles — UTC-08:00 (DST)
// America/Anchorage — UTC-09:00 (DST)
// Pacific/Honolulu — UTC-10:00
// America/Phoenix — UTC-07:00
// Get the primary (capital-city) time zone
var primary = usa.GetPrimaryTimeZone();
Console.WriteLine(primary); // America/New_York (UTC-05:00, DST)
// Single-zone countries
var japan = Country.GetCountry("JP");
Console.WriteLine(japan.TimeZones[0]); // Asia/Tokyo (UTC+09:00)
Multi-Zone Countries
// Check if a country spans multiple time zones
var russia = Country.GetCountry("RU");
Console.WriteLine(russia.HasMultipleTimeZones); // True
Console.WriteLine($"Russia has {russia.TimeZones.Count} time zones"); // 11
var pakistan = Country.GetCountry("PK");
Console.WriteLine(pakistan.HasMultipleTimeZones); // False
// Countries with no time zone data return an empty list
var none = CountryHelper.None;
Console.WriteLine(none.TimeZones.Count); // 0
DST Support
var usa = Country.GetCountry("US");
// Get only time zones that observe DST
var dstZones = usa.GetTimeZonesWithDst();
Console.WriteLine($"{dstZones.Count} zones observe DST"); // 5
foreach (var tz in dstZones)
Console.WriteLine($" {tz.IanaId}");
// America/New_York
// America/Chicago
// America/Denver
// America/Los_Angeles
// America/Anchorage
// Honolulu and Phoenix do NOT observe DST
var japan = Country.GetCountry("JP");
Console.WriteLine(japan.GetTimeZonesWithDst().Count); // 0 (Japan doesn't observe DST)
UTC Offsets
var usa = Country.GetCountry("US");
// Get distinct UTC offsets across all time zones
var offsets = usa.GetUtcOffsets();
Console.WriteLine($"US has {offsets.Count} distinct UTC offsets"); // 6
// -05:00, -06:00, -07:00, -08:00, -09:00, -10:00
// Fractional offsets
var india = Country.GetCountry("IN");
Console.WriteLine(india.TimeZones[0].UtcOffsetString); // UTC+05:30
var nepal = Country.GetCountry("NP");
Console.WriteLine(nepal.TimeZones[0].UtcOffsetString); // UTC+05:45
// Access the TimeSpan directly
var offset = india.TimeZones[0].UtcOffset;
Console.WriteLine(offset.TotalHours); // 5.5
Console.WriteLine(offset.TotalMinutes); // 330
Extended Country Data
Every Country object provides access to rich extended data — geographic, political, transport, electrical, emergency, phone format, locale, translations, subdivisions, and movable holidays. All data is lazily loaded on first access.
Geographic Data
var pakistan = Country.GetCountry("PK");
Console.WriteLine($"Population: {pakistan.Population:N0}"); // Population: 231,402,117
Console.WriteLine($"Area: {pakistan.AreaInSquareKilometers:N0} km²"); // Area: 881,912 km²
Console.WriteLine($"Landlocked: {pakistan.IsLandlocked}"); // Landlocked: False
// Capital coordinates
var coords = pakistan.CapitalCoordinates;
Console.WriteLine($"Capital: {coords?.Latitude}, {coords?.Longitude}"); // Capital: 33.6844, 73.0479
// Bordering countries
Console.WriteLine($"Borders: {string.Join(", ", pakistan.BorderingCountries)}"); // Borders: AF, CN, IN, IR
Political Data
var pakistan = Country.GetCountry("PK");
Console.WriteLine($"UN Member: {pakistan.IsUnMember}"); // UN Member: True
Console.WriteLine($"Independence: {pakistan.IndependenceDate:d}"); // Independence: 8/14/1947
// Territories have no independence date
var aq = Country.GetCountry("AQ");
Console.WriteLine(aq.IndependenceDate is null); // True
Transport Data
var uk = Country.GetCountry("GB");
Console.WriteLine($"Drives on: {uk.DrivingSide}"); // Drives on: Left
Console.WriteLine($"Speed unit: {uk.SpeedUnit}"); // Speed unit: mph
var germany = Country.GetCountry("DE");
Console.WriteLine($"Drives on: {germany.DrivingSide}"); // Drives on: Right
Console.WriteLine($"Speed unit: {germany.SpeedUnit}"); // Speed unit: km/h
Electrical Systems
var pakistan = Country.GetCountry("PK");
var elec = pakistan.ElectricalSystem;
Console.WriteLine($"Voltage: {elec?.Voltage}V"); // Voltage: 230V
Console.WriteLine($"Frequency: {elec?.Frequency}Hz"); // Frequency: 50Hz
Console.WriteLine($"Plugs: {string.Join(", ", elec?.PlugTypes ?? Array.Empty<PlugType>())}");
// Plugs: C, D
Emergency Numbers
var pakistan = Country.GetCountry("PK");
Console.WriteLine($"Emergency: {string.Join(", ", pakistan.EmergencyNumbers)}");
// Emergency: 15, 115, 1122
var usa = Country.GetCountry("US");
Console.WriteLine($"Emergency: {string.Join(", ", usa.EmergencyNumbers)}");
// Emergency: 911
Phone Formats
var pakistan = Country.GetCountry("PK");
var phone = pakistan.PhoneFormat;
Console.WriteLine($"Calling code: {phone?.CallingCode}"); // Calling code: +92
Console.WriteLine($"Trunk prefix: {phone?.TrunkPrefix}"); // Trunk prefix: 0
Console.WriteLine($"Lengths: {string.Join(", ", phone?.PhoneNumberLengths ?? Array.Empty<int>())}");
// Lengths: 10
Locale & Formatting
var pakistan = Country.GetCountry("PK");
var locale = pakistan.Locale;
Console.WriteLine($"Date format: {locale?.DateFormat}"); // Date format: dd/MM/yyyy
Console.WriteLine($"Measurement: {locale?.MeasurementSystem}"); // Measurement: Metric
Console.WriteLine($"Decimal: '{locale?.NumberDecimalSeparator}'"); // Decimal: '.'
Console.WriteLine($"Grouping: '{locale?.NumberGroupSeparator}'"); // Grouping: ','
Console.WriteLine($"Postal code: {locale?.PostalCodeFormat}"); // Postal code: #####
Translations
var pakistan = Country.GetCountry("PK");
// Get all translations
foreach (var (lang, name) in pakistan.Translations)
Console.WriteLine($" {lang}: {name}");
// fr: Pakistan
// es: Pakistán
// de: Pakistan
// ar: باكستان
// zh: 巴基斯坦
// ja: パキスタン
// ...
// Get name in a specific language
Console.WriteLine(pakistan.GetNameInLanguage("fr")); // Pakistan
Console.WriteLine(pakistan.GetNameInLanguage("ar")); // باكستان
Console.WriteLine(pakistan.GetNameInLanguage("zh")); // 巴基斯坦
Console.WriteLine(pakistan.GetNameInLanguage("xx")); // (null — not found)
Subdivisions
var usa = Country.GetCountry("US");
Console.WriteLine($"{usa.Name} has {usa.Subdivisions.Count} subdivisions:");
foreach (var sub in usa.Subdivisions.Take(5))
Console.WriteLine($" {sub.Code}: {sub.Name} ({sub.Type})");
// United States of America has 56 subdivisions:
// US-AL: Alabama (State)
// US-AK: Alaska (State)
// US-AZ: Arizona (State)
// US-AR: Arkansas (State)
// US-CA: California (State)
// Countries without subdivision data return an empty list
var mc = Country.GetCountry("MC");
Console.WriteLine(mc.Subdivisions.Count); // 0
Movable Holidays
Movable holidays have dates that vary by year (e.g. Easter, Thanksgiving). Use GetDate(year) to compute the actual date:
var usa = Country.GetCountry("US");
foreach (var mh in usa.MovableHolidays)
Console.WriteLine($" {mh.Name}: {mh.GetDate(2026):yyyy-MM-dd}");
// Martin Luther King Jr. Day: 2026-01-19
// Presidents' Day: 2026-02-16
// Easter Sunday: 2026-04-05
// Memorial Day: 2026-05-25
// Labor Day: 2026-09-07
// Columbus Day: 2026-10-12
// Thanksgiving Day: 2026-11-26
// Check if a specific date is a movable holiday
bool isThanksgiving = usa.MovableHolidays.Any(h => h.IsOnDate(new DateTime(2026, 11, 26))); // true
// Get ALL holidays (fixed + movable) on a date
var allOnDate = usa.GetAllHolidaysOnDate(new DateTime(2026, 11, 26));
Console.WriteLine(string.Join(", ", allOnDate)); // Thanksgiving Day
Exception Handling
Each domain has a dedicated exception type that inherits from System.Exception:
| Exception | Thrown By |
|---|---|
CountryNotFoundException |
Country.GetCountry() |
CurrencyNotFoundException |
Currency.GetCurrency(string), Currency.GetCurrency(int) |
LanguageNotFoundException |
Language.GetLanguage() |
Example — structured error handling:
try
{
var country = Country.GetCountry(userInput);
Console.WriteLine($"Found: {country.Name} — Currency: {country.CurrencyCode}");
}
catch (CountryNotFoundException ex)
{
Console.WriteLine($"Not found: {ex.Message}");
}
catch (ArgumentNullException)
{
Console.WriteLine("Input was null or empty.");
}
Best Practices
1. Use Country as Your Single Source of Truth
A single Country lookup gives you the country, its currency, and its official languages — no need to query them separately:
var country = Country.GetCountry("PK");
// Everything in one place
var name = country.Name; // Pakistan
var currency = country.Currency!; // CurrencyHelper.PakistanRupee
var code = country.CurrencyCode; // PKR
var languages = country.OfficialLanguages; // [Urdu, English]
var flag = country.Flag; // 🇵🇰
2. Prefer Safe Lookups for User Input
Use the OrDefault variants when dealing with untrusted or user-provided values to avoid unnecessary exception overhead:
var country = Country.GetCountryOrDefault(userInput);
if (country is not null)
{
Console.WriteLine($"{country.Name} uses {country.Currency?.Name ?? "no official currency"}");
}
3. Validate Before Processing
Use IsValid() as a guard clause before further business logic:
if (!Country.IsValid(countryCode))
{
return BadRequest("Invalid country code.");
}
var country = Country.GetCountry(countryCode);
4. Use Static Fields for Known Values
When you know the value at compile time, reference CountryHelper, CurrencyHelper, or LanguageHelper fields directly — this avoids string parsing entirely:
var defaultCountry = CountryHelper.UnitedStatesOfAmerica;
var defaultCurrency = CurrencyHelper.UsDollar;
var defaultLanguage = LanguageHelper.English;
// Or reach currency/language through the country
var usCurrency = CountryHelper.UnitedStatesOfAmerica.Currency; // CurrencyHelper.UsDollar
var usLanguages = CountryHelper.UnitedStatesOfAmerica.OfficialLanguages; // [English]
5. Use Case-Insensitive Input Freely
All lookups normalize to lowercase internally, so you never need to pre-process casing:
// All of these return the same result
Country.GetCountry("us");
Country.GetCountry("US");
Country.GetCountry("Us");
API Reference Summary
Country
| Property / Method | Returns | Description |
|---|---|---|
Name |
string |
Official country name |
Alpha2Code |
string |
ISO 3166-1 alpha-2 code |
Alpha3Code |
string |
ISO 3166-1 alpha-3 code |
NumericCode |
string |
ISO 3166-1 numeric code |
CallingCode |
string |
International dialing code (E.164) |
Capital |
string |
Capital city |
Region |
string |
Geographic region / continent |
SubRegion |
string |
UN M49 sub-region (e.g. "Southern Asia", "Western Europe") |
Demonym |
string |
Demonym — what residents are called (e.g. "Pakistani", "American") |
TLD |
string |
Country-code top-level domain (e.g. ".pk", ".us") |
Currency |
Currency? |
Full currency object (null for territories with no currency) |
CurrencyCode |
string |
ISO 4217 code derived from Currency |
OfficialLanguages |
IReadOnlyList<Language> |
Official languages of the country |
Holidays |
IReadOnlyList<Holiday> |
Public holidays observed in this country |
TimeZones |
IReadOnlyList<CountryTimeZone> |
IANA time zones observed in this country |
HasMultipleTimeZones |
bool |
Whether the country spans more than one time zone |
Flag |
string |
Unicode flag emoji |
Population |
long |
Approximate population count |
AreaInSquareKilometers |
double |
Total area in km² |
CapitalCoordinates |
GeoCoordinate? |
Capital city latitude/longitude |
BorderingCountries |
IReadOnlyList<string> |
Alpha-2 codes of neighboring countries |
IsLandlocked |
bool |
Whether the country has no coastline |
IsUnMember |
bool |
Whether the country is a UN member |
IndependenceDate |
DateTime? |
Date of independence |
DrivingSide |
DrivingSide |
Left or Right driving side |
SpeedUnit |
string |
Speed measurement unit (km/h or mph) |
AlternativeTlds |
IReadOnlyList<string> |
Alternative country-code TLDs |
ElectricalSystem |
ElectricalSystem? |
Voltage, frequency & plug types |
EmergencyNumbers |
IReadOnlyList<string> |
Emergency telephone numbers |
PhoneFormat |
PhoneFormat? |
Phone number format info |
Locale |
CountryLocale? |
Date, number & measurement formats |
Translations |
IReadOnlyDictionary<string, string> |
Country name translations |
Subdivisions |
IReadOnlyList<Subdivision> |
ISO 3166-2 subdivisions |
MovableHolidays |
IReadOnlyList<MovableHoliday> |
Movable holidays |
| Method | Returns | Throws | Description |
|---|---|---|---|
GetCountry(string) |
Country |
CountryNotFoundException, ArgumentNullException |
Strict lookup by alpha-2, alpha-3, numeric code, or name |
GetCountryOrDefault(string) |
Country? |
— | Safe lookup; returns null if not found |
IsValid(string) |
bool |
— | Check if identifier maps to a known country |
GetAll() |
List<Country> |
— | All 250 countries |
| Method | Returns | Description |
|---|---|---|
GetHolidaysByType(HolidayType) |
IReadOnlyList<Holiday> |
Filter holidays by type |
IsPublicHoliday(DateTime) |
bool |
Check if date falls on any holiday |
GetHolidayOnDate(DateTime) |
Holiday? |
Get the holiday on a given date, or null |
GetPrimaryTimeZone() |
CountryTimeZone? |
Get the primary (capital-city) time zone, or null |
GetTimeZonesWithDst() |
IReadOnlyList<CountryTimeZone> |
Get all time zones that observe DST |
GetUtcOffsets() |
IReadOnlyList<TimeSpan> |
Get distinct UTC offsets across all time zones |
GetAllHolidaysOnDate(DateTime) |
IReadOnlyList<string> |
Get all holidays (fixed + movable) on a date |
GetNameInLanguage(string) |
string? |
Get country name in the specified language |
Currency
| Property / Method | Returns | Description |
|---|---|---|
Name |
string |
Currency name |
Code |
string |
ISO 4217 alphabetic code |
Number |
int |
ISO 4217 numeric code |
Symbol |
string |
Currency symbol |
DecimalPlaces |
int |
Minor units (decimal places) |
| Method | Returns | Throws | Description |
|---|---|---|---|
GetCurrency(string) |
Currency |
CurrencyNotFoundException, ArgumentNullException |
Strict lookup by code or name |
GetCurrency(int) |
Currency |
CurrencyNotFoundException |
Strict lookup by ISO numeric code |
GetCurrencyOrDefault(string) |
Currency? |
— | Safe lookup by code or name |
GetCurrencyOrDefault(int) |
Currency? |
— | Safe lookup by numeric code |
IsValid(string) |
bool |
— | Check if code/name maps to a known currency |
IsValid(int) |
bool |
— | Check if numeric code maps to a known currency |
GetAll() |
List<Currency> |
— | All 150+ currencies |
GetCountriesUsingCurrency() |
IReadOnlyList<Country> |
— | All countries using this currency |
Language
| Property / Method | Returns | Description |
|---|---|---|
Name |
string |
Language name (may include alternates) |
Alpha2Code |
string |
ISO 639-1 code (2-letter, may be empty) |
Alpha3Code |
string |
ISO 639-2 code (3-letter) |
NativeName |
string |
Native name of the language |
Script |
string |
Primary writing script |
TextDirection |
TextDirection |
Text direction (LeftToRight or RightToLeft) |
| Method | Returns | Throws | Description |
|---|---|---|---|
GetLanguage(string) |
Language |
LanguageNotFoundException, ArgumentNullException |
Strict lookup by alpha-2, alpha-3, or name |
GetLanguageOrDefault(string) |
Language? |
— | Safe lookup; returns null if not found |
IsValid(string) |
bool |
— | Check if identifier maps to a known language |
GetAll() |
List<Language> |
— | All 475+ languages |
CountryHelper
| Member | Type | Description |
|---|---|---|
None |
Country |
Empty sentinel value representing no country |
GetAll() |
List<Country> |
Returns a new list of all 250 countries, ordered by name |
Alpha2CodeMap |
IReadOnlyDictionary<string, Country> |
O(1) lookup by ISO 3166-1 alpha-2 code (case-insensitive keys) |
Alpha3CodeMap |
IReadOnlyDictionary<string, Country> |
O(1) lookup by ISO 3166-1 alpha-3 code (case-insensitive keys) |
NumericCodeMap |
IReadOnlyDictionary<string, Country> |
O(1) lookup by ISO 3166-1 numeric code |
NameMap |
IReadOnlyDictionary<string, Country> |
O(1) lookup by country name (case-insensitive keys) |
Pakistan, France, ... |
Country |
250 static readonly fields — one per country |
CurrencyHelper
| Member | Type | Description |
|---|---|---|
None |
Currency |
Empty sentinel value representing no currency |
GetAll() |
List<Currency> |
Returns a new list of all currencies, ordered by name |
CodeMap |
IReadOnlyDictionary<string, Currency> |
O(1) lookup by ISO 4217 code (case-insensitive keys) |
NameMap |
IReadOnlyDictionary<string, Currency> |
O(1) lookup by currency name (case-insensitive keys) |
NumberMap |
IReadOnlyDictionary<int, Currency> |
O(1) lookup by ISO 4217 numeric code |
UsDollar, Euro, ... |
Currency |
150+ static readonly fields — one per currency |
LanguageHelper
| Member | Type | Description |
|---|---|---|
None |
Language |
Empty sentinel value representing no language |
GetAll() |
List<Language> |
Returns a new list of all languages |
Alpha2CodeMap |
IReadOnlyDictionary<string, Language> |
O(1) lookup by ISO 639-1 code (lowercase keys) |
Alpha3CodeMap |
IReadOnlyDictionary<string, Language> |
O(1) lookup by ISO 639-2 code (lowercase keys) |
NameMap |
IReadOnlyDictionary<string, Language> |
O(1) lookup by language name (lowercase keys) |
English, Urdu, ... |
Language |
475+ static readonly fields — one per language |
Holiday
| Property / Method | Returns | Description |
|---|---|---|
Name |
string |
Holiday name |
Month |
int |
Month (1–12) |
Day |
int |
Day (1–31) |
Type |
HolidayType |
Category (Public, Bank, Religious, National, Observance) |
Date |
DateTime |
Date in the current year |
GetDate(int) |
DateTime |
Date in a specific year |
IsOnDate(DateTime) |
bool |
Check if month/day matches a given date |
ToString() |
string |
Formatted string, e.g. "Christmas Day (12/25)" |
HolidayHelper
| Member | Type | Description |
|---|---|---|
All |
IReadOnlyDictionary<string, List<Holiday>> |
Complete mapping of alpha-2 codes to holiday lists |
CountryTimeZone
| Property / Method | Returns | Description |
|---|---|---|
IanaId |
string |
IANA time zone identifier (e.g. "America/New_York") |
UtcOffsetHours |
double |
Standard UTC offset in hours (e.g. -5.0, +5.5, +5.75) |
ObservesDst |
bool |
Whether this time zone observes Daylight Saving Time |
UtcOffset |
TimeSpan |
UTC offset as a TimeSpan |
UtcOffsetString |
string |
Formatted offset string (e.g. "UTC-05:00", "UTC+05:45") |
ToString() |
string |
Formatted string, e.g. "America/New_York (UTC-05:00, DST)" |
TimeZoneHelper
| Member | Type | Description |
|---|---|---|
All |
IReadOnlyDictionary<string, List<CountryTimeZone>> |
Complete mapping of alpha-2 codes to time zone lists |
Testing
The project includes a comprehensive test suite with 692 unit tests covering every public API, edge case, and data integrity check across the entire library.
Running Tests
dotnet test
Test Structure
| Test Class | Tests | Covers |
|---|---|---|
CountryTests |
119 | Country API, CountryHelper maps, SubRegion, Demonym, TLD, data integrity across all 250 countries |
CurrencyTests |
56 | Currency API (string & int overloads), CurrencyHelper maps, data integrity |
LanguageTests |
42 | Language API, LanguageHelper maps, data integrity |
ExceptionTests |
19 | All three custom exception types — constructors, inheritance, and throw behavior |
HolidayTests |
76 | Holiday model, HolidayType enum, Country.Holidays, filtering, date checks, data integrity |
TimeZoneTests |
98 | CountryTimeZone model, Country.TimeZones, DST support, UTC offsets, multi-zone countries, data integrity |
GeographicDataTests |
49 | Population, area, capital coordinates, bordering countries, landlocked status |
PoliticalDataTests |
14 | UN membership, independence dates |
TransportDataTests |
18 | Driving side, speed units, DrivingSide enum |
ElectricalSystemTests |
24 | Voltage, frequency, plug types, PlugType enum |
EmergencyNumberTests |
10 | Emergency telephone numbers |
PhoneFormatTests |
15 | Phone number formatting, calling codes, trunk prefixes |
LocaleTests |
21 | Date/number formats, measurement systems, postal codes |
TranslationTests |
17 | Country name translations, GetNameInLanguage |
SubdivisionTests |
18 | ISO 3166-2 subdivisions, code uniqueness |
MovableHolidayTests |
26 | Easter calculation, nth-weekday holidays, date computation |
CurrencyExtendedTests |
24 | Decimal places, reverse country lookup |
LanguageExtendedTests |
24 | Native names, scripts, text direction |
CountryIntegrationTests |
22 | Alternative TLDs, full property integration |
What's Tested
- All lookup methods —
GetCountry,GetCurrency,GetLanguageand theirOrDefaultvariants, by every supported identifier type (alpha-2, alpha-3, numeric code, name) - Validation —
IsValid()for valid codes, invalid codes,null, empty strings, whitespace, and case variations - Exception paths —
ArgumentNullExceptionfor null/empty input, domain-specificNotFoundExceptionfor unknown identifiers - Case insensitivity — lookups work with any casing (
"us","US","Us") - Helper maps —
Alpha2CodeMap,Alpha3CodeMap,NameMap,NumericCodeMap,CodeMap,NumberMapall contain expected entries - Data integrity — no duplicate codes/names, all required properties are non-empty, regions come from a known set, calling codes start with
+, currency codes are uppercase 3-letter, alpha codes have correct lengths, SubRegions/Demonyms/TLDs populated for all countries - Relationships —
Country.CurrencymatchesCurrencyCode,Country.OfficialLanguagesreturns correct languages,Country.Flagis derived fromAlpha2Code,Country.Holidaysreturns correct holidays with filtering and date-check methods - Collection behavior —
GetAll()returns new list instances each time, lists are ordered, singletons are reference-equal across lookups - Holiday data — all holidays have valid names, months, days, and types; no duplicate names per country; consistent across accesses
- Time zone data — all IANA IDs are non-empty and contain "/", UTC offsets in valid range (−12 to +14), no duplicate IANA IDs per country, all country codes exist in CountryHelper, fractional offsets formatted correctly
- Extended country data — geographic data (population, area, coordinates, borders, landlocked), political data (UN membership, independence dates), transport data (driving side, speed units), electrical systems (voltage, frequency, plug types), emergency numbers, phone formats, locale/formatting (date/number formats, measurement systems, postal codes), translations (country names in 10+ languages), subdivisions (ISO 3166-2), and movable holidays (Easter, Thanksgiving, etc.)
- Currency extensions — decimal places (minor units) for all currencies, reverse lookup via
GetCountriesUsingCurrency() - Language extensions — native names, scripts, text direction (LTR/RTL) for all languages
Test Dependencies
| Package | Purpose |
|---|---|
| xUnit | Test framework |
| FluentAssertions | Assertion library |
| NSubstitute | Mocking framework |
Contributing
Contributions, issues, and feature requests are welcome! Feel free to open an issue or submit a pull request on the GitHub repository.
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes (
git commit -m "Add my feature") - Push to the branch (
git push origin feature/my-feature) - Open a Pull Request
License
This project is licensed under the MIT License — see the LICENSE file for details.
Copyright © 2023 Muhammad Waseem
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.6.2
- System.ValueTuple (>= 4.5.0)
-
.NETStandard 2.0
- No dependencies.
-
net6.0
- No dependencies.
-
net7.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.46 | 129 | 3/9/2026 |
| 2.0.45 | 120 | 2/27/2026 |
| 2.0.42 | 125 | 2/13/2026 |
| 2.0.39 | 124 | 2/12/2026 |
| 2.0.36 | 134 | 2/12/2026 |
| 2.0.35 | 116 | 2/12/2026 |
| 2.0.1 | 298 | 4/2/2025 |
| 2.0.0.44 | 115 | 2/27/2026 |
| 2.0.0 | 236 | 4/2/2025 |
| 2.0.0-preview.23 | 163 | 3/30/2025 |
| 2.0.0-preview.18 | 158 | 3/30/2025 |
| 1.0.3 | 281 | 3/30/2025 |
| 1.0.2 | 289 | 3/30/2025 |
| 1.0.1 | 229 | 3/30/2025 |
| 1.0.0 | 354 | 11/12/2023 |
## Extended Country Data, Multi-Framework Support & Test Reorganization
### Multi-Framework Support
- Added .NET 6.0, .NET 7.0, and .NET 9.0 targets alongside existing .NET 8.0, .NET Standard 2.0, and .NET Framework 4.6.2
- Now targets: `net9.0`, `net8.0`, `net7.0`, `net6.0`, `netstandard2.0`, `net462`
- FrozenDictionary optimization on .NET 8+ with automatic fallback to Dictionary on earlier frameworks
### Geographic Data (250 countries)
- Country.Population — approximate population count
- Country.AreaInSquareKilometers — total area in km²
- Country.CapitalCoordinates — latitude/longitude of the capital city (GeoCoordinate model)
- Country.BorderingCountries — ISO alpha-2 codes of neighboring countries
- Country.IsLandlocked — whether the country has no coastline
### Political Data (250 countries)
- Country.IsUnMember — whether the country is a United Nations member
- Country.IndependenceDate — date of independence (null for territories)
### Transport Data (250 countries)
- Country.DrivingSide — Left or Right (DrivingSide enum)
- Country.SpeedUnit — "km/h" or "mph"
### Electrical Systems (250 countries)
- Country.ElectricalSystem — voltage, frequency & plug types
- ElectricalSystem model with Voltage, Frequency, PlugTypes
- PlugType enum covering all international plug standards (A through O)
### Emergency Numbers (250 countries)
- Country.EmergencyNumbers — emergency telephone numbers (e.g. 911, 112, 999)
### Phone Formats (250 countries)
- Country.PhoneFormat — phone number format information
- PhoneFormat model with CallingCode, TrunkPrefix, PhoneNumberLengths
### Locale & Formatting (250 countries)
- Country.Locale — locale and formatting conventions
- CountryLocale model with DateFormat, NumberDecimalSeparator, NumberGroupSeparator, MeasurementSystem, PostalCodeFormat
- MeasurementSystem enum (Metric, Imperial, USCustomary)
### Country Translations (250 countries)
- Country.Translations — country name in 10+ languages (fr, es, de, ar, zh, ja, ru, pt, it, ko, hi)
- Country.GetNameInLanguage(string) — get country name in a specific language
### Subdivisions (50+ countries)
- Country.Subdivisions — ISO 3166-2 first-level administrative subdivisions
- Subdivision model with Code, Name, Type
- SubdivisionHelper with data for 50+ countries (states, provinces, regions, cantons, etc.)
### Movable Holidays (40+ countries)
- Country.MovableHolidays — holidays with dates that vary by year (Easter, Thanksgiving, etc.)
- MovableHoliday model with Name, GetDate(year), IsOnDate(date)
- Country.GetAllHolidaysOnDate(date) — combined check for fixed + movable holidays
- Easter computation via Computus algorithm
- NthWeekdayOfMonth, LastWeekdayOfMonth, LastWeekdayBefore helper methods
### Currency Extensions
- Currency.DecimalPlaces — minor units (0 for JPY, 2 for USD/EUR, 3 for KWD/BHD)
- Currency.GetCountriesUsingCurrency() — reverse lookup of all countries using this currency
### Language Extensions
- Language.NativeName — native name of the language (e.g. "Deutsch", "العربية", "中文")
- Language.Script — primary writing script (e.g. "Latin", "Arabic", "Cyrillic", "Han")
- Language.TextDirection — LeftToRight or RightToLeft (TextDirection enum)
### Alternative TLDs
- Country.AlternativeTlds — additional country-code TLDs (e.g. ".uk" for GB alongside ".gb")
### Test Reorganization (SRP)
- Split monolithic ExtendedFeaturesTests.cs into 13 focused test files following Single Responsibility Principle
- GeographicDataTests, PoliticalDataTests, TransportDataTests, ElectricalSystemTests, EmergencyNumberTests, PhoneFormatTests, LocaleTests, TranslationTests, SubdivisionTests, MovableHolidayTests, CurrencyExtendedTests, LanguageExtendedTests, CountryIntegrationTests
- 692 total unit tests, 0 failures, 0 warnings
---
## Time Zones
- Time Zones — IANA Time Zone Database support for all 250 countries & territories
- CountryTimeZone model with IanaId, UtcOffsetHours, ObservesDst, UtcOffset, UtcOffsetString, ToString()
- TimeZoneHelper.All — complete dictionary of alpha-2 codes to time zone lists
- Country.TimeZones — IANA time zones for the country, accessed directly from the Country object
- Country.HasMultipleTimeZones — whether the country spans more than one time zone
- Country.GetPrimaryTimeZone() — capital-city / primary time zone
- Country.GetTimeZonesWithDst() — filter to DST-observing zones
- Country.GetUtcOffsets() — distinct UTC offsets across all zones
- Fractional UTC offsets supported (e.g. +5:30 India, +5:45 Nepal, -3:30 Newfoundland)
- DST flagged per zone (e.g. US Eastern = DST, Hawaii = no DST)
- Multi-zone countries: US (7), Russia (11), Canada (7), Australia (8), Brazil (8), Antarctica (10), and more
## Time Zones, Holidays, SubRegion, Demonym & TLD
- Holidays support — fixed-date public holidays for 190+ countries, accessible via Country.Holidays
- Holiday model with Name, Month, Day, Type, Date, GetDate(), IsOnDate(), ToString()
- HolidayType enum: Public, Bank, Religious, National, Observance
- HolidayHelper.All — complete dictionary of alpha-2 codes to holiday lists
- Country methods: GetHolidaysByType(), IsPublicHoliday(), GetHolidayOnDate()
- SubRegion — UN M49 sub-region for every country (e.g. Southern Asia, Western Europe)
- Demonym — what residents of each country are called (e.g. Pakistani, American)
- TLD — country-code top-level domain for every country (e.g. .pk, .us, .jp)
- 312 unit tests covering holidays, SubRegion, Demonym, TLD, and all existing APIs
- 98 additional unit tests for time zones (410 total)
## Country-Centric Architecture
- Country-centric design — Country is now the central entity carrying Currency and OfficialLanguages
- Official Languages — each country carries its official languages
- Flag emoji — Country.Flag property returns the Unicode flag emoji
- Dictionary maps — pre-built Alpha2CodeMap, Alpha3CodeMap, NumericCodeMap, NameMap for O(1) lookups
- OrDefault variants — GetCountryOrDefault(), GetCurrencyOrDefault(), GetLanguageOrDefault()
- Validation methods — IsValid() on Country, Currency, and Language
- Multi-targeting — supports net9.0, net8.0, net7.0, net6.0, netstandard2.0, and net462
## Initial Release
- 250 countries and territories — ISO 3166-1 (alpha-2, alpha-3, numeric) with capitals, regions, and E.164 calling codes
- 150+ currencies — ISO 4217 (code, numeric, symbol)
- 475+ languages — ISO 639-1 (alpha-2) and ISO 639-2 (alpha-3)
- Static helper classes — CountryHelper, CurrencyHelper, LanguageHelper with compile-time access
- Custom exceptions — CountryNotFoundException, CurrencyNotFoundException, LanguageNotFoundException
- Zero dependencies — no third-party packages required
- Immutable and thread-safe — all data is readonly singletons