diff --git a/README.md b/README.md index d11e85fcc..cb7d51374 100644 --- a/README.md +++ b/README.md @@ -197,6 +197,7 @@ Country | ISO 3166 Code | Calling Code | Trunk Prefix | Geographic | Mobi Austria | AT | 43 | 0 | Yes | Yes | | | Yes | Yes | Yes | | Belarus | BY | 375 | 8 | Yes | Yes | | | Yes | Yes | Yes | | Belgium | BE | 32 | 0 | Yes | Yes | | | Yes | Yes | Yes | | Yes +Bosnia and Herzegovina | BA | 387 | 0 | Yes | Yes | | Yes | Yes | Yes | Yes | Yes | Yes Bulgaria | BG | 359 | 0 | Yes | Yes | | Yes | Yes | Yes | Yes | | Yes Croatia | HR | 385 | 0 | Yes | Yes | | Yes | Yes | Yes | Yes | | Yes Cyprus | CY | 387 | | Yes | Yes | | Yes | Yes | Yes | Yes | Yes | Yes diff --git a/src/PhoneNumbers/CountryInfo_Europe.cs b/src/PhoneNumbers/CountryInfo_Europe.cs index df379a430..f4379f8eb 100644 --- a/src/PhoneNumbers/CountryInfo_Europe.cs +++ b/src/PhoneNumbers/CountryInfo_Europe.cs @@ -51,6 +51,20 @@ public partial class CountryInfo TrunkPrefix = "0", }; + /// + /// Gets the for Bosnia and Herzegovina. + /// + public static CountryInfo BosniaAndHerzegovina { get; } = new() + { + CallingCode = "387", + Continent = Europe, + Iso3166Code = "BA", + Name = "Bosnia and Herzegovina", + NdcLengths = new ReadOnlyCollection([4, 3, 2]), + NsnLengths = new ReadOnlyCollection([6, 8, 9]), + TrunkPrefix = "0", + }; + /// /// Gets the for Bulgaria. /// diff --git a/src/PhoneNumbers/DataFiles/BA.txt b/src/PhoneNumbers/DataFiles/BA.txt new file mode 100644 index 000000000..030bc9df7 --- /dev/null +++ b/src/PhoneNumbers/DataFiles/BA.txt @@ -0,0 +1,34 @@ +# References: +# - https://www.itu.int/dms_pub/itu-t/oth/02/02/T020200001B0001PDFE.pdf +G|30|Central Bosnia Canton|000000-999999| +G|31|Posavina Canton|000000-999999| +G|32|Zenica-Doboj Canton|000000-999999| +G|33|Sarajevo Canton|000000-999999| +G|34|Canton 10|000000-999999| +G|35|Tuzla Canton|000000-999999| +G|36|Hercegovina-Neretva Canton|000000-999999| +G|37|Unsa-Sana Canton|000000-999999| +G|38|Bosanian-Podrinje Goražde Canton|000000-999999| +G|39|West Herzegovina Canton|000000-999999| +G|49|Brčko Distirct B&H|000000-999999| +G|50|Mrkonjić Grad|000000-999999| +G|51|Banja Luka|000000-999999| +G|52|Prijedor|000000-999999| +G|53|Doboj|000000-999999| +G|54|Šamac|000000-999999| +G|55|Bijeljina|000000-999999| +G|56|Zvornik|000000-999999| +G|57|Istočno Sarajevo|000000-999999| +G|58|Foča|000000-999999| +G|59|Trebinje|000000-999999| +M|60,64,67||0000000-9999999| +M|61-63,65-66||000000-999999| +N|70||000000-099999|V +N|800||00000-99999|F +N|8010||0000-9999| +N|810-818||000000-999999|S +N|819||00000-99999| +N|82||000000-999999|S +N|83||0000-9999| +N|85||0000000-9999999|M +N|90-92,94,96||000000-999999|R diff --git a/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_BA_GeographicNumber.cs b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_BA_GeographicNumber.cs new file mode 100644 index 000000000..af5385fb5 --- /dev/null +++ b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_BA_GeographicNumber.cs @@ -0,0 +1,105 @@ +namespace PhoneNumbers.Tests.Parsers; + +/// +/// Contains unit tests for the class for Bosnia and herzegovina s. +/// +public class DefaultPhoneNumberParserTests_BA_GeographicNumber +{ + private static readonly PhoneNumberParser s_parser = DefaultPhoneNumberParser.Create(CountryInfo.BosniaAndHerzegovina); + + [Theory] + [InlineData("030000000", "30", "000000", "Central Bosnia Canton")] + [InlineData("030999999", "30", "999999", "Central Bosnia Canton")] + [InlineData("031000000", "31", "000000", "Posavina Canton")] + [InlineData("031999999", "31", "999999", "Posavina Canton")] + [InlineData("032000000", "32", "000000", "Zenica-Doboj Canton")] + [InlineData("032999999", "32", "999999", "Zenica-Doboj Canton")] + [InlineData("033000000", "33", "000000", "Sarajevo Canton")] + [InlineData("033999999", "33", "999999", "Sarajevo Canton")] + [InlineData("034000000", "34", "000000", "Canton 10")] + [InlineData("034999999", "34", "999999", "Canton 10")] + [InlineData("035000000", "35", "000000", "Tuzla Canton")] + [InlineData("035999999", "35", "999999", "Tuzla Canton")] + [InlineData("036000000", "36", "000000", "Hercegovina-Neretva Canton")] + [InlineData("036999999", "36", "999999", "Hercegovina-Neretva Canton")] + [InlineData("037000000", "37", "000000", "Unsa-Sana Canton")] + [InlineData("037999999", "37", "999999", "Unsa-Sana Canton")] + [InlineData("038000000", "38", "000000", "Bosanian-Podrinje Goražde Canton")] + [InlineData("038999999", "38", "999999", "Bosanian-Podrinje Goražde Canton")] + [InlineData("039000000", "39", "000000", "West Herzegovina Canton")] + [InlineData("039999999", "39", "999999", "West Herzegovina Canton")] + public void Parse_Known_GeographicPhoneNumber_3X_NationalDestinationCode(string value, string NationalDestinationCode, string subscriberNumber, string geographicArea) + { + var parseResult = s_parser.Parse(value); + parseResult.ThrowIfFailure(); + + var phoneNumber = parseResult.PhoneNumber; + + Assert.NotNull(phoneNumber); + Assert.IsType(phoneNumber); + + var geographicPhoneNumber = (GeographicPhoneNumber)phoneNumber; + Assert.Equal(CountryInfo.BosniaAndHerzegovina, geographicPhoneNumber.Country); + Assert.Equal(geographicArea, geographicPhoneNumber.GeographicArea); + Assert.Equal(NationalDestinationCode, geographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, geographicPhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("049000000", "49", "000000", "Brčko Distirct B&H")] + [InlineData("049999999", "49", "999999", "Brčko Distirct B&H")] + public void Parse_Known_GeographicPhoneNumber_4X_NationalDestinationCode(string value, string NationalDestinationCode, string subscriberNumber, string geographicArea) + { + var parseResult = s_parser.Parse(value); + parseResult.ThrowIfFailure(); + + var phoneNumber = parseResult.PhoneNumber; + + Assert.NotNull(phoneNumber); + Assert.IsType(phoneNumber); + + var geographicPhoneNumber = (GeographicPhoneNumber)phoneNumber; + Assert.Equal(CountryInfo.BosniaAndHerzegovina, geographicPhoneNumber.Country); + Assert.Equal(geographicArea, geographicPhoneNumber.GeographicArea); + Assert.Equal(NationalDestinationCode, geographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, geographicPhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("050000000", "50", "000000", "Mrkonjić Grad")] + [InlineData("050999999", "50", "999999", "Mrkonjić Grad")] + [InlineData("051000000", "51", "000000", "Banja Luka")] + [InlineData("051999999", "51", "999999", "Banja Luka")] + [InlineData("052000000", "52", "000000", "Prijedor")] + [InlineData("052999999", "52", "999999", "Prijedor")] + [InlineData("053000000", "53", "000000", "Doboj")] + [InlineData("053999999", "53", "999999", "Doboj")] + [InlineData("054000000", "54", "000000", "Šamac")] + [InlineData("054999999", "54", "999999", "Šamac")] + [InlineData("055000000", "55", "000000", "Bijeljina")] + [InlineData("055999999", "55", "999999", "Bijeljina")] + [InlineData("056000000", "56", "000000", "Zvornik")] + [InlineData("056999999", "56", "999999", "Zvornik")] + [InlineData("057000000", "57", "000000", "Istočno Sarajevo")] + [InlineData("057999999", "57", "999999", "Istočno Sarajevo")] + [InlineData("058000000", "58", "000000", "Foča")] + [InlineData("058999999", "58", "999999", "Foča")] + [InlineData("059000000", "59", "000000", "Trebinje")] + [InlineData("059999999", "59", "999999", "Trebinje")] + public void Parse_Known_GeographicPhoneNumber_5X_NationalDestinationCode(string value, string NationalDestinationCode, string subscriberNumber, string geographicArea) + { + var parseResult = s_parser.Parse(value); + parseResult.ThrowIfFailure(); + + var phoneNumber = parseResult.PhoneNumber; + + Assert.NotNull(phoneNumber); + Assert.IsType(phoneNumber); + + var geographicPhoneNumber = (GeographicPhoneNumber)phoneNumber; + Assert.Equal(CountryInfo.BosniaAndHerzegovina, geographicPhoneNumber.Country); + Assert.Equal(geographicArea, geographicPhoneNumber.GeographicArea); + Assert.Equal(NationalDestinationCode, geographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, geographicPhoneNumber.SubscriberNumber); + } +} diff --git a/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_BA_MobilePhoneNumber.cs b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_BA_MobilePhoneNumber.cs new file mode 100644 index 000000000..2a5cdf598 --- /dev/null +++ b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_BA_MobilePhoneNumber.cs @@ -0,0 +1,42 @@ +namespace PhoneNumbers.Tests.Parsers; + +/// +/// Contains unit tests for the class for Bosnia and herzegovina s. +/// +public class DefaultPhoneNumberParserTests_BA_MobilePhoneNumber +{ + private static readonly PhoneNumberParser s_parser = DefaultPhoneNumberParser.Create(CountryInfo.BosniaAndHerzegovina); + + [Theory] + [InlineData("0600000000", "60", "0000000")] + [InlineData("0609999999", "60", "9999999")] + [InlineData("061000000", "61", "000000")] + [InlineData("061999999", "61", "999999")] + [InlineData("063000000", "63", "000000")] + [InlineData("063999999", "63", "999999")] + [InlineData("0640000000", "64", "0000000")] + [InlineData("0649999999", "64", "9999999")] + [InlineData("065000000", "65", "000000")] + [InlineData("065999999", "65", "999999")] + [InlineData("066000000", "66", "000000")] + [InlineData("066999999", "66", "999999")] + [InlineData("0670000000", "67", "0000000")] + [InlineData("0679999999", "67", "9999999")] + public void Parse_Known_MobilePhoneNumber(string value, string NationalDestinationCode, string subscriberNumber) + { + var parseResult = s_parser.Parse(value); + parseResult.ThrowIfFailure(); + + var phoneNumber = parseResult.PhoneNumber; + + Assert.NotNull(phoneNumber); + Assert.IsType(phoneNumber); + + var mobilePhoneNumber = (MobilePhoneNumber)phoneNumber; + Assert.Equal(CountryInfo.BosniaAndHerzegovina, mobilePhoneNumber.Country); + Assert.False(mobilePhoneNumber.IsPager); + Assert.False(mobilePhoneNumber.IsVirtual); + Assert.Equal(NationalDestinationCode, mobilePhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, mobilePhoneNumber.SubscriberNumber); + } +} diff --git a/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_BA_NonGeographicPhoneNumber.cs b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_BA_NonGeographicPhoneNumber.cs new file mode 100644 index 000000000..01cc7a6ae --- /dev/null +++ b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_BA_NonGeographicPhoneNumber.cs @@ -0,0 +1,138 @@ +namespace PhoneNumbers.Tests.Parsers; + +/// +/// Contains unit tests for the class for Bosnia and herzegovina s. +/// +public class DefaultPhoneNumberParserTests_BA_NonGeographicPhoneNumber +{ + private static readonly PhoneNumberParser s_parser = DefaultPhoneNumberParser.Create(CountryInfo.BosniaAndHerzegovina); + + [Theory] + [InlineData("080100000", "8010", "0000")] + [InlineData("080109999", "8010", "9999")] + [InlineData("081900000", "819", "00000")] + [InlineData("081999999", "819", "99999")] + [InlineData("0830000", "83", "0000")] + [InlineData("0839999", "83", "9999")] + public void Parse_Known_NonGeographicPhoneNumber_8XXX_NationalDestinationCode(string value, string NationalDestinationCode, string subscriberNumber) + { + var parseResult = s_parser.Parse(value); + parseResult.ThrowIfFailure(); + + var phoneNumber = parseResult.PhoneNumber; + + Assert.NotNull(phoneNumber); + Assert.IsType(phoneNumber); + + var nonGeographicPhoneNumber = (NonGeographicPhoneNumber)phoneNumber; + Assert.Equal(CountryInfo.BosniaAndHerzegovina, nonGeographicPhoneNumber.Country); + Assert.False(nonGeographicPhoneNumber.IsFreephone); + Assert.False(nonGeographicPhoneNumber.IsMachineToMachine); + Assert.False(nonGeographicPhoneNumber.IsPremiumRate); + Assert.False(nonGeographicPhoneNumber.IsSharedCost); + Assert.Equal(NationalDestinationCode, nonGeographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, nonGeographicPhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("080000000", "800", "00000")] + [InlineData("080099999", "800", "99999")] + public void Parse_Known_NonGeographicPhoneNumber_Freephone(string value, string NationalDestinationCode, string subscriberNumber) + { + var parseResult = s_parser.Parse(value); + parseResult.ThrowIfFailure(); + + var phoneNumber = parseResult.PhoneNumber; + + Assert.NotNull(phoneNumber); + Assert.IsType(phoneNumber); + + var nonGeographicPhoneNumber = (NonGeographicPhoneNumber)phoneNumber; + Assert.Equal(CountryInfo.BosniaAndHerzegovina, nonGeographicPhoneNumber.Country); + Assert.True(nonGeographicPhoneNumber.IsFreephone); + Assert.False(nonGeographicPhoneNumber.IsMachineToMachine); + Assert.False(nonGeographicPhoneNumber.IsPremiumRate); + Assert.False(nonGeographicPhoneNumber.IsSharedCost); + Assert.Equal(NationalDestinationCode, nonGeographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, nonGeographicPhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("0850000000", "85", "0000000")] + [InlineData("0859999999", "85", "9999999")] + public void Parse_Known_NonGeographicPhoneNumber_MachineToMachine(string value, string NationalDestinationCode, string subscriberNumber) + { + var parseResult = s_parser.Parse(value); + parseResult.ThrowIfFailure(); + + var phoneNumber = parseResult.PhoneNumber; + + Assert.NotNull(phoneNumber); + Assert.IsType(phoneNumber); + + var nonGeographicPhoneNumber = (NonGeographicPhoneNumber)phoneNumber; + Assert.Equal(CountryInfo.BosniaAndHerzegovina, nonGeographicPhoneNumber.Country); + Assert.False(nonGeographicPhoneNumber.IsFreephone); + Assert.True(nonGeographicPhoneNumber.IsMachineToMachine); + Assert.False(nonGeographicPhoneNumber.IsPremiumRate); + Assert.False(nonGeographicPhoneNumber.IsSharedCost); + Assert.Equal(NationalDestinationCode, nonGeographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, nonGeographicPhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("090000000", "90", "000000")] + [InlineData("090999999", "90", "999999")] + [InlineData("092000000", "92", "000000")] + [InlineData("092999999", "92", "999999")] + [InlineData("094000000", "94", "000000")] + [InlineData("094999999", "94", "999999")] + [InlineData("096000000", "96", "000000")] + [InlineData("096999999", "96", "999999")] + public void Parse_Known_NonGeographicPhoneNumber_PremiumRate(string value, string NationalDestinationCode, string subscriberNumber) + { + var parseResult = s_parser.Parse(value); + parseResult.ThrowIfFailure(); + + var phoneNumber = parseResult.PhoneNumber; + + Assert.NotNull(phoneNumber); + Assert.IsType(phoneNumber); + + var nonGeographicPhoneNumber = (NonGeographicPhoneNumber)phoneNumber; + Assert.Equal(CountryInfo.BosniaAndHerzegovina, nonGeographicPhoneNumber.Country); + Assert.False(nonGeographicPhoneNumber.IsFreephone); + Assert.False(nonGeographicPhoneNumber.IsMachineToMachine); + Assert.True(nonGeographicPhoneNumber.IsPremiumRate); + Assert.False(nonGeographicPhoneNumber.IsSharedCost); + Assert.Equal(NationalDestinationCode, nonGeographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, nonGeographicPhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("0810000000", "810", "000000")] + [InlineData("0810999999", "810", "999999")] + [InlineData("0818000000", "818", "000000")] + [InlineData("0818999999", "818", "999999")] + [InlineData("082000000", "82", "000000")] + [InlineData("082999999", "82", "999999")] + public void Parse_Known_NonGeographicPhoneNumber_SharedCost(string value, string NationalDestinationCode, string subscriberNumber) + { + var parseResult = s_parser.Parse(value); + parseResult.ThrowIfFailure(); + + var phoneNumber = parseResult.PhoneNumber; + + Assert.NotNull(phoneNumber); + Assert.IsType(phoneNumber); + + var nonGeographicPhoneNumber = (NonGeographicPhoneNumber)phoneNumber; + Assert.Equal(CountryInfo.BosniaAndHerzegovina, nonGeographicPhoneNumber.Country); + Assert.False(nonGeographicPhoneNumber.IsFreephone); + Assert.False(nonGeographicPhoneNumber.IsMachineToMachine); + Assert.False(nonGeographicPhoneNumber.IsPremiumRate); + Assert.True(nonGeographicPhoneNumber.IsSharedCost); + Assert.Equal(NationalDestinationCode, nonGeographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, nonGeographicPhoneNumber.SubscriberNumber); + } +} diff --git a/test/PhoneNumbers.Tests/CountryInfo_Europe_Tests.cs b/test/PhoneNumbers.Tests/CountryInfo_Europe_Tests.cs index bde35dfa7..d87627a04 100644 --- a/test/PhoneNumbers.Tests/CountryInfo_Europe_Tests.cs +++ b/test/PhoneNumbers.Tests/CountryInfo_Europe_Tests.cs @@ -64,6 +64,26 @@ public void CountryInfo_Belgium() Assert.Equal("0", countryInfo.TrunkPrefix); } + [Fact] + public void CountryInfo_BosniaAndHerzegovina() + { + Assert.Same(CountryInfo.BosniaAndHerzegovina, CountryInfo.BosniaAndHerzegovina); + + var countryInfo = CountryInfo.BosniaAndHerzegovina; + + Assert.False(countryInfo.AllowsLocalGeographicDialling); + Assert.Equal("387", countryInfo.CallingCode); + Assert.Equal(CountryInfo.Europe, countryInfo.Continent); + Assert.IsType(countryInfo.FormatProvider); + Assert.False(countryInfo.IsEuropeanUnionMember); + Assert.Equal("BA", countryInfo.Iso3166Code); + Assert.Equal("Bosnia and Herzegovina", countryInfo.Name); + Assert.Equal(new[] { 4, 3, 2 }, countryInfo.NdcLengths); + Assert.Equal(new[] { 6, 8, 9 }, countryInfo.NsnLengths); + Assert.False(countryInfo.SharesCallingCode); + Assert.Equal("0", countryInfo.TrunkPrefix); + } + [Fact] public void CountryInfo_Bulgaria() { diff --git a/test/PhoneNumbers.Tests/PhoneNumber_Parse_Europe_Tests.cs b/test/PhoneNumbers.Tests/PhoneNumber_Parse_Europe_Tests.cs index 32d6a4dd2..1547bcda5 100644 --- a/test/PhoneNumbers.Tests/PhoneNumber_Parse_Europe_Tests.cs +++ b/test/PhoneNumbers.Tests/PhoneNumber_Parse_Europe_Tests.cs @@ -26,6 +26,14 @@ public void Parse_Value_For_Belgium_CallingCode() Assert.Equal(CountryInfo.Belgium, phoneNumber.Country); } + [Fact] + public void Parse_Value_For_BosniaAndHerzegovina_CallingCode() + { + var phoneNumber = PhoneNumber.Parse("+38733250600"); + Assert.NotNull(phoneNumber); + Assert.Equal(CountryInfo.BosniaAndHerzegovina, phoneNumber.Country); + } + [Fact] public void Parse_Value_For_Bulgaria_CallingCode() { diff --git a/test/PhoneNumbers.Tests/PhoneNumber_ToString_Europe_Tests.cs b/test/PhoneNumbers.Tests/PhoneNumber_ToString_Europe_Tests.cs index 98af8265a..7dbf7e9f7 100644 --- a/test/PhoneNumbers.Tests/PhoneNumber_ToString_Europe_Tests.cs +++ b/test/PhoneNumbers.Tests/PhoneNumber_ToString_Europe_Tests.cs @@ -22,6 +22,13 @@ public void Belarus_Numbers(string input, string format, string expected) => public void Belgium_Numbers(string input, string format, string expected) => Assert.Equal(expected, PhoneNumber.Parse(input).ToString(format)); + [Theory] + [InlineData("+38733250600", "E.123", "+387 33 250 600")] + [InlineData("+38733250600", "N", "033 250 600")] + [InlineData("+38733250600", "RFC3966", "tel:+387-33-250-600")] + public void BosniaAndHerzegovina_Numbers(string input, string format, string expected) => + Assert.Equal(expected, PhoneNumber.Parse(input).ToString(format)); + [Theory] [InlineData("+35929492760", "E.123", "+359 2 949 2760")] [InlineData("+35929492760", "N", "(02) 949 2760")]