From 06a8abe5a15b798bde2fa057b07eeaa25e9d8b57 Mon Sep 17 00:00:00 2001 From: Trevor Pilley Date: Sat, 23 Nov 2024 23:00:25 +0000 Subject: [PATCH] Closes #619 Add support for Liechtenstein phone numbers --- README.md | 1 + src/PhoneNumbers/CountryInfo_Europe.cs | 13 +++ src/PhoneNumbers/DataFiles/LI.txt | 11 ++ .../LIPhoneNumberFormatProvider.cs | 21 ++++ ...eNumberParserTests_LI_MobilePhoneNumber.cs | 55 +++++++++ ...ParserTests_LI_NonGeographicPhoneNumber.cs | 105 ++++++++++++++++++ .../CountryInfo_Europe_Tests.cs | 20 ++++ .../PhoneNumber_Parse_Europe_Tests.cs | 8 ++ .../PhoneNumber_ToString_Europe_Tests.cs | 7 ++ .../phone-number-utilities-testgenerator | 2 +- 10 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 src/PhoneNumbers/DataFiles/LI.txt create mode 100644 src/PhoneNumbers/Formatters/FormatProviders/LIPhoneNumberFormatProvider.cs create mode 100644 test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_LI_MobilePhoneNumber.cs create mode 100644 test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_LI_NonGeographicPhoneNumber.cs diff --git a/README.md b/README.md index ed3c4686..abb7b6bb 100644 --- a/README.md +++ b/README.md @@ -221,6 +221,7 @@ Jersey | JE | 44 _(UK)_ | 0 | Yes | Yes Kosovo | XK | 383 | 0 | Yes | Yes | | | Yes | Yes | Yes | Yes | Latvia | LV | 371 | | Yes | Yes | | | Yes | Yes | Yes | Yes | Lithuania | LT | 370 | 8 | Yes | Yes | | Yes | Yes | Yes | Yes | Yes | +Liechtenstein | LI | 423 | | | Yes | | Yes | Yes | Yes | Yes | Yes | Luxembourg | LU | 352 | | | Yes | | | Yes | Yes | Yes | | Yes Malta | MT | 356 | | Yes | Yes | Yes | | Yes | Yes | Yes | | Yes Moldova | MD | 373 | 0 | Yes | Yes | | | Yes | Yes | Yes | Yes | diff --git a/src/PhoneNumbers/CountryInfo_Europe.cs b/src/PhoneNumbers/CountryInfo_Europe.cs index 2544d532..19992b0f 100644 --- a/src/PhoneNumbers/CountryInfo_Europe.cs +++ b/src/PhoneNumbers/CountryInfo_Europe.cs @@ -373,6 +373,19 @@ public partial class CountryInfo NsnLengths = new ReadOnlyCollection([8]), }; + /// + /// Gets the for Liechtenstein. + /// + public static CountryInfo Liechtenstein { get; } = new() + { + CallingCode = "423", + Continent = Europe, + FormatProvider = LIPhoneNumberFormatProvider.Instance, + Iso3166Code = "LI", + Name = "Liechtenstein", + NsnLengths = new ReadOnlyCollection([7, 9]), + }; + /// /// Gets the for Lithuania. /// diff --git a/src/PhoneNumbers/DataFiles/LI.txt b/src/PhoneNumbers/DataFiles/LI.txt new file mode 100644 index 00000000..6a0e0576 --- /dev/null +++ b/src/PhoneNumbers/DataFiles/LI.txt @@ -0,0 +1,11 @@ +# Reference: https://archiv.llv.li/files/ak/pdf-llv-ak-liechtenstein_numbering_plan.pdf via https://www.llv.li/en/national-administration/office-for-communications/electronic-communication/numbering/liechtenstein-numbering-plan-itu-t-e.164- +# Reference Date: 01/03/2017 +N|||2000000-3999999| +M|||600000000-689999999| +M|||690000000-699999999| +M|||7000000-7999999| +N|||8000000-8099999|F +N|||8400000-8499999|S +N|||8700000-8799999| +M|||8900000-8999999|V +N|||9000000-9019999,9060000-9069999|R diff --git a/src/PhoneNumbers/Formatters/FormatProviders/LIPhoneNumberFormatProvider.cs b/src/PhoneNumbers/Formatters/FormatProviders/LIPhoneNumberFormatProvider.cs new file mode 100644 index 00000000..0de45bc3 --- /dev/null +++ b/src/PhoneNumbers/Formatters/FormatProviders/LIPhoneNumberFormatProvider.cs @@ -0,0 +1,21 @@ +namespace PhoneNumbers.Formatters.FormatProviders; + +/// +/// A for Liechtenstein numbers. +/// +internal sealed class LIPhoneNumberFormatProvider : SimplePhoneNumberFormatProvider +{ + private LIPhoneNumberFormatProvider() + { + } + + internal static PhoneNumberFormatProvider Instance { get; } = new LIPhoneNumberFormatProvider(); + + protected override string ProvideFormat(PhoneNumber phoneNumber, bool international) => + phoneNumber.NationalSignificantNumber.Length switch + { + 7 => "### ## ##", + 9 => "### ### ###", + _ => base.ProvideFormat(phoneNumber, international), + }; +} diff --git a/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_LI_MobilePhoneNumber.cs b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_LI_MobilePhoneNumber.cs new file mode 100644 index 00000000..3b3570d7 --- /dev/null +++ b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_LI_MobilePhoneNumber.cs @@ -0,0 +1,55 @@ +namespace PhoneNumbers.Tests.Parsers; + +/// +/// Contains unit tests for the class for Liechtenstein s. +/// +public class DefaultPhoneNumberParserTests_LI_MobilePhoneNumber +{ + private static readonly PhoneNumberParser s_parser = DefaultPhoneNumberParser.Create(CountryInfo.Liechtenstein); + + [Theory] + [InlineData("7000000", "7000000")] + [InlineData("7999999", "7999999")] + [InlineData("600000000", "600000000")] + [InlineData("689999999", "689999999")] + [InlineData("690000000", "690000000")] + [InlineData("699999999", "699999999")] + public void Parse_Known_MobilePhoneNumber(string value, 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.Liechtenstein, mobilePhoneNumber.Country); + Assert.False(mobilePhoneNumber.IsPager); + Assert.False(mobilePhoneNumber.IsVirtual); + Assert.Null(mobilePhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, mobilePhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("8900000", "8900000")] + [InlineData("8999999", "8999999")] + public void Parse_Known_MobilePhoneNumber_Virtual(string value, 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.Liechtenstein, mobilePhoneNumber.Country); + Assert.False(mobilePhoneNumber.IsPager); + Assert.True(mobilePhoneNumber.IsVirtual); + Assert.Null(mobilePhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, mobilePhoneNumber.SubscriberNumber); + } +} diff --git a/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_LI_NonGeographicPhoneNumber.cs b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_LI_NonGeographicPhoneNumber.cs new file mode 100644 index 00000000..f6cd2e03 --- /dev/null +++ b/test/PhoneNumbers.Data.Tests/Parsers/DefaultPhoneNumberParserTests_LI_NonGeographicPhoneNumber.cs @@ -0,0 +1,105 @@ +namespace PhoneNumbers.Tests.Parsers; + +/// +/// Contains unit tests for the class for Liechtenstein s. +/// +public class DefaultPhoneNumberParserTests_LI_NonGeographicPhoneNumber +{ + private static readonly PhoneNumberParser s_parser = DefaultPhoneNumberParser.Create(CountryInfo.Liechtenstein); + + [Theory] + [InlineData("2000000", "2000000")] + [InlineData("3999999", "3999999")] + [InlineData("8700000", "8700000")] + [InlineData("8799999", "8799999")] + public void Parse_Known_NonGeographicPhoneNumber(string value, 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.Liechtenstein, nonGeographicPhoneNumber.Country); + Assert.False(nonGeographicPhoneNumber.IsFreephone); + Assert.False(nonGeographicPhoneNumber.IsMachineToMachine); + Assert.False(nonGeographicPhoneNumber.IsPremiumRate); + Assert.False(nonGeographicPhoneNumber.IsSharedCost); + Assert.Null(nonGeographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, nonGeographicPhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("8000000", "8000000")] + [InlineData("8099999", "8099999")] + public void Parse_Known_NonGeographicPhoneNumber_Freephone(string value, 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.Liechtenstein, nonGeographicPhoneNumber.Country); + Assert.True(nonGeographicPhoneNumber.IsFreephone); + Assert.False(nonGeographicPhoneNumber.IsMachineToMachine); + Assert.False(nonGeographicPhoneNumber.IsPremiumRate); + Assert.False(nonGeographicPhoneNumber.IsSharedCost); + Assert.Null(nonGeographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, nonGeographicPhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("9000000", "9000000")] + [InlineData("9019999", "9019999")] + [InlineData("9060000", "9060000")] + [InlineData("9069999", "9069999")] + public void Parse_Known_NonGeographicPhoneNumber_PremiumRate(string value, 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.Liechtenstein, nonGeographicPhoneNumber.Country); + Assert.False(nonGeographicPhoneNumber.IsFreephone); + Assert.False(nonGeographicPhoneNumber.IsMachineToMachine); + Assert.True(nonGeographicPhoneNumber.IsPremiumRate); + Assert.False(nonGeographicPhoneNumber.IsSharedCost); + Assert.Null(nonGeographicPhoneNumber.NationalDestinationCode); + Assert.Equal(subscriberNumber, nonGeographicPhoneNumber.SubscriberNumber); + } + + [Theory] + [InlineData("8400000", "8400000")] + [InlineData("8499999", "8499999")] + public void Parse_Known_NonGeographicPhoneNumber_SharedCost(string value, 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.Liechtenstein, nonGeographicPhoneNumber.Country); + Assert.False(nonGeographicPhoneNumber.IsFreephone); + Assert.False(nonGeographicPhoneNumber.IsMachineToMachine); + Assert.False(nonGeographicPhoneNumber.IsPremiumRate); + Assert.True(nonGeographicPhoneNumber.IsSharedCost); + Assert.Null(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 5cb501f3..3ec01562 100644 --- a/test/PhoneNumbers.Tests/CountryInfo_Europe_Tests.cs +++ b/test/PhoneNumbers.Tests/CountryInfo_Europe_Tests.cs @@ -484,6 +484,26 @@ public void CountryInfo_Latvia() Assert.Null(countryInfo.TrunkPrefix); } + [Fact] + public void CountryInfo_Liechtenstein() + { + Assert.Same(CountryInfo.Liechtenstein, CountryInfo.Liechtenstein); + + var countryInfo = CountryInfo.Liechtenstein; + + Assert.False(countryInfo.AllowsLocalGeographicDialling); + Assert.Equal("423", countryInfo.CallingCode); + Assert.Equal(CountryInfo.Europe, countryInfo.Continent); + Assert.IsType(countryInfo.FormatProvider); + Assert.False(countryInfo.IsEuropeanUnionMember); + Assert.Equal("LI", countryInfo.Iso3166Code); + Assert.Equal("Liechtenstein", countryInfo.Name); + Assert.Empty(countryInfo.NdcLengths); + Assert.Equal(new[] { 7, 9 }, countryInfo.NsnLengths); + Assert.False(countryInfo.SharesCallingCode); + Assert.Null(countryInfo.TrunkPrefix); + } + [Fact] public void CountryInfo_Lithuania() { diff --git a/test/PhoneNumbers.Tests/PhoneNumber_Parse_Europe_Tests.cs b/test/PhoneNumbers.Tests/PhoneNumber_Parse_Europe_Tests.cs index 473f1ef7..28cb3f6a 100644 --- a/test/PhoneNumbers.Tests/PhoneNumber_Parse_Europe_Tests.cs +++ b/test/PhoneNumbers.Tests/PhoneNumber_Parse_Europe_Tests.cs @@ -198,6 +198,14 @@ public void Parse_Value_For_Latvia_CallingCode() Assert.Equal(CountryInfo.Latvia, phoneNumber.Country); } + [Fact] + public void Parse_Value_For_Liechtenstein_CallingCode() + { + var phoneNumber = PhoneNumber.Parse("+4232366488"); + Assert.NotNull(phoneNumber); + Assert.Equal(CountryInfo.Liechtenstein, phoneNumber.Country); + } + [Fact] public void Parse_Value_For_Lithuania_CallingCode() { diff --git a/test/PhoneNumbers.Tests/PhoneNumber_ToString_Europe_Tests.cs b/test/PhoneNumbers.Tests/PhoneNumber_ToString_Europe_Tests.cs index e4faafcd..b60642a3 100644 --- a/test/PhoneNumbers.Tests/PhoneNumber_ToString_Europe_Tests.cs +++ b/test/PhoneNumbers.Tests/PhoneNumber_ToString_Europe_Tests.cs @@ -215,6 +215,13 @@ public void Kosovo_Numbers(string input, string format, string expected) => public void Latvia_Numbers(string input, string format, string expected) => Assert.Equal(expected, PhoneNumber.Parse(input).ToString(format)); + [Theory] + [InlineData("+4232366488", "E.123", "+423 236 64 88")] + [InlineData("+4232366488", "N", "236 64 88")] + [InlineData("+4232366488", "RFC3966", "tel:+423-236-64-88")] + public void Liechtenstein_Numbers(string input, string format, string expected) => + Assert.Equal(expected, PhoneNumber.Parse(input).ToString(format)); + [Theory] [InlineData("+37052105664", "E.123", "+370 5 210 5664")] [InlineData("+37052105664", "N", "(85) 210 5664")] diff --git a/utilities/phone-number-utilities-testgenerator b/utilities/phone-number-utilities-testgenerator index e7e7a484..f45cced3 160000 --- a/utilities/phone-number-utilities-testgenerator +++ b/utilities/phone-number-utilities-testgenerator @@ -1 +1 @@ -Subproject commit e7e7a4848b8ffa9f8d541f4e5d07036c04ae4d96 +Subproject commit f45cced331ea7bd218bb34841e988f9d8b9ab948