Skip to content

Commit

Permalink
Closes #616
Browse files Browse the repository at this point in the history
Add support for Iceland phone numbers
  • Loading branch information
TrevorPilley authored Apr 15, 2024
1 parent d0bcfe7 commit d933ec4
Show file tree
Hide file tree
Showing 9 changed files with 372 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ Gibraltar | GI | 350 | | Yes | Yes
Greece | GR | 30 | | Yes | Yes | | Yes | Yes | Yes | Yes | Yes | Yes
Guernsey | GG | 44 _(UK)_ | 0 | Yes | Yes | | | | | | |
Hungary | HU | 36 | 06 | Yes | Yes | | | Yes | Yes | Yes | | Yes
Iceland | IS | 354 | | Yes | Yes | | | Yes | Yes | Yes | | Yes
Ireland | IE | 353 | 0 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes
Isle of Man | IM | 44 _(UK)_ | 0 | Yes | Yes | | | | | | |
Italy | IT | 39 | | Yes | Yes | | | Yes | Yes | Yes | Yes |
Expand Down Expand Up @@ -295,3 +296,4 @@ Brazil | BR | 55 | 0 | Yes | Yes
- Mobile numbers are geographically assigned and cannot be determined separately from landlines.
- Freephone numbers (with a few exceptions) are issued from a shared pool. This could mean a Canadian freephone number look up shows as belonging to a different country if parsed from the E.164 format (parsing from the national number format and country code will work as expected).
- Virtual (aka personal numbers) are issued from a shared pool and always show as belonging to the United States.
- Landline numbers can be ported in some countries and therefore although originally geographically assigned, they may no longer match the specified geographic area (Countries affected - Iceland)
12 changes: 12 additions & 0 deletions src/PhoneNumbers/CountryInfo_Europe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,18 @@ public partial class CountryInfo
TrunkPrefix = "06",
};

/// <summary>
/// Gets the <see cref="CountryInfo"/> for Iceland.
/// </summary>
public static CountryInfo Iceland { get; } = new()
{
CallingCode = "354",
Continent = Europe,
Iso3166Code = "IS",
Name = "Iceland",
NsnLengths = new ReadOnlyCollection<int>([7, 9]),
};

/// <summary>
/// Gets the <see cref="CountryInfo"/> for Ireland.
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions src/PhoneNumbers/DataFiles/IS.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# References:
# - https://www.fjarskiptastofa.is/english/telecom-affairs/numbering/
N|||352000000-352999999|M
M|||358000000-358999999,388000000-389999999|
G||Excluding Reykjavík and Capital Region|4100000-4129999,4140000-4169999,4190000-4279999,4300000-4389999,4400000-4429999,4440000-4459999,4480000-4489999,4500000-4539999,4550000-4569999,4580000-4589999,4600000-4789999,4810000-4839999,4860000-4889999,4920000-4969999,4970000-4979999,4990000-4999999|
G||Reykjavík and Capital Region|5050000-5059999,5100000-5179999,5190000-5209999,5220000-5229999,5250000-5259999,5270000-5289999,5300000-5359999,5370000-5379999,5390000-5409999,5430000-5479999,5500000-5729999,5750000-5759999,5770000-5789999,5800000-5839999,5850000-5919999,5930000-5969999,5980000-5999999|
M|||6110000-6189999,6200000-6269999,6300000-6309999,6320000-6329999,6360000-6419999,6440000-6449999,6460000-6479999,6490000-6519999,6550000-6559999,6590000-6669999,6690000-6709999,6800000-6809999,6860000-6999999|
N|||7500000-7509999,7550000-7559999,7570000-7579999|
M|||7600000-7939999|
N|||8010000-8099999|
N|||8000000-8009999|F
M|||8200000-8259999,8290000-8689999,8820000-8839999,8880000-8889999,8900000-8999999|
N|||8780000-8809999|
N|||9000000-9009999,9015000-9017000,9019000-9021999,9025000-9027999,9029000-9029999,9031000-9031999,9033000-9033999,9035000-9037000,9040000-9042000,0944000-9047000,9052000-9057000,9059000-9059999,9071000-9073999,9077000-9077999,9080000-9083999,9085000-9087999|R
N|||9090000-9099999,9540000-9549999,9580000-9589999|
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
namespace PhoneNumbers.Tests.Parsers;

/// <summary>
/// Contains unit tests for the <see cref="DefaultPhoneNumberParser"/> class for Iceland <see cref="PhoneNumber"/>s.
/// </summary>
public class DefaultPhoneNumberParserTests_IS_GeographicNumber
{
private static readonly PhoneNumberParser s_parser = DefaultPhoneNumberParser.Create(CountryInfo.Iceland);

[Theory]
[InlineData("4100000", "4100000", "Excluding Reykjavík and Capital Region")]
[InlineData("4129999", "4129999", "Excluding Reykjavík and Capital Region")]
[InlineData("4140000", "4140000", "Excluding Reykjavík and Capital Region")]
[InlineData("4169999", "4169999", "Excluding Reykjavík and Capital Region")]
[InlineData("4190000", "4190000", "Excluding Reykjavík and Capital Region")]
[InlineData("4279999", "4279999", "Excluding Reykjavík and Capital Region")]
[InlineData("4300000", "4300000", "Excluding Reykjavík and Capital Region")]
[InlineData("4389999", "4389999", "Excluding Reykjavík and Capital Region")]
[InlineData("4400000", "4400000", "Excluding Reykjavík and Capital Region")]
[InlineData("4429999", "4429999", "Excluding Reykjavík and Capital Region")]
[InlineData("4440000", "4440000", "Excluding Reykjavík and Capital Region")]
[InlineData("4459999", "4459999", "Excluding Reykjavík and Capital Region")]
[InlineData("4480000", "4480000", "Excluding Reykjavík and Capital Region")]
[InlineData("4489999", "4489999", "Excluding Reykjavík and Capital Region")]
[InlineData("4500000", "4500000", "Excluding Reykjavík and Capital Region")]
[InlineData("4539999", "4539999", "Excluding Reykjavík and Capital Region")]
[InlineData("4550000", "4550000", "Excluding Reykjavík and Capital Region")]
[InlineData("4569999", "4569999", "Excluding Reykjavík and Capital Region")]
[InlineData("4580000", "4580000", "Excluding Reykjavík and Capital Region")]
[InlineData("4589999", "4589999", "Excluding Reykjavík and Capital Region")]
[InlineData("4600000", "4600000", "Excluding Reykjavík and Capital Region")]
[InlineData("4789999", "4789999", "Excluding Reykjavík and Capital Region")]
[InlineData("4810000", "4810000", "Excluding Reykjavík and Capital Region")]
[InlineData("4839999", "4839999", "Excluding Reykjavík and Capital Region")]
[InlineData("4860000", "4860000", "Excluding Reykjavík and Capital Region")]
[InlineData("4889999", "4889999", "Excluding Reykjavík and Capital Region")]
[InlineData("4920000", "4920000", "Excluding Reykjavík and Capital Region")]
[InlineData("4969999", "4969999", "Excluding Reykjavík and Capital Region")]
[InlineData("4970000", "4970000", "Excluding Reykjavík and Capital Region")]
[InlineData("4979999", "4979999", "Excluding Reykjavík and Capital Region")]
[InlineData("4990000", "4990000", "Excluding Reykjavík and Capital Region")]
[InlineData("4999999", "4999999", "Excluding Reykjavík and Capital Region")]
[InlineData("5050000", "5050000", "Reykjavík and Capital Region")]
[InlineData("5059999", "5059999", "Reykjavík and Capital Region")]
[InlineData("5100000", "5100000", "Reykjavík and Capital Region")]
[InlineData("5179999", "5179999", "Reykjavík and Capital Region")]
[InlineData("5190000", "5190000", "Reykjavík and Capital Region")]
[InlineData("5209999", "5209999", "Reykjavík and Capital Region")]
[InlineData("5220000", "5220000", "Reykjavík and Capital Region")]
[InlineData("5229999", "5229999", "Reykjavík and Capital Region")]
[InlineData("5250000", "5250000", "Reykjavík and Capital Region")]
[InlineData("5259999", "5259999", "Reykjavík and Capital Region")]
[InlineData("5270000", "5270000", "Reykjavík and Capital Region")]
[InlineData("5289999", "5289999", "Reykjavík and Capital Region")]
[InlineData("5300000", "5300000", "Reykjavík and Capital Region")]
[InlineData("5359999", "5359999", "Reykjavík and Capital Region")]
[InlineData("5370000", "5370000", "Reykjavík and Capital Region")]
[InlineData("5379999", "5379999", "Reykjavík and Capital Region")]
[InlineData("5390000", "5390000", "Reykjavík and Capital Region")]
[InlineData("5409999", "5409999", "Reykjavík and Capital Region")]
[InlineData("5430000", "5430000", "Reykjavík and Capital Region")]
[InlineData("5479999", "5479999", "Reykjavík and Capital Region")]
[InlineData("5500000", "5500000", "Reykjavík and Capital Region")]
[InlineData("5729999", "5729999", "Reykjavík and Capital Region")]
[InlineData("5750000", "5750000", "Reykjavík and Capital Region")]
[InlineData("5759999", "5759999", "Reykjavík and Capital Region")]
[InlineData("5770000", "5770000", "Reykjavík and Capital Region")]
[InlineData("5789999", "5789999", "Reykjavík and Capital Region")]
[InlineData("5800000", "5800000", "Reykjavík and Capital Region")]
[InlineData("5839999", "5839999", "Reykjavík and Capital Region")]
[InlineData("5850000", "5850000", "Reykjavík and Capital Region")]
[InlineData("5919999", "5919999", "Reykjavík and Capital Region")]
[InlineData("5930000", "5930000", "Reykjavík and Capital Region")]
[InlineData("5969999", "5969999", "Reykjavík and Capital Region")]
[InlineData("5980000", "5980000", "Reykjavík and Capital Region")]
[InlineData("5999999", "5999999", "Reykjavík and Capital Region")]
public void Parse_Known_GeographicPhoneNumber(string value, string subscriberNumber, string geographicArea)
{
var parseResult = s_parser.Parse(value);
parseResult.ThrowIfFailure();

var phoneNumber = parseResult.PhoneNumber;

Assert.NotNull(phoneNumber);
Assert.IsType<GeographicPhoneNumber>(phoneNumber);

var geographicPhoneNumber = (GeographicPhoneNumber)phoneNumber;
Assert.Equal(CountryInfo.Iceland, geographicPhoneNumber.Country);
Assert.Equal(geographicArea, geographicPhoneNumber.GeographicArea);
Assert.Null(geographicPhoneNumber.NationalDestinationCode);
Assert.Equal(subscriberNumber, geographicPhoneNumber.SubscriberNumber);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
namespace PhoneNumbers.Tests.Parsers;

/// <summary>
/// Contains unit tests for the <see cref="DefaultPhoneNumberParser"/> class for Iceland <see cref="PhoneNumber"/>s.
/// </summary>
public class DefaultPhoneNumberParserTests_IS_MobilePhoneNumber
{
private static readonly PhoneNumberParser s_parser = DefaultPhoneNumberParser.Create(CountryInfo.Iceland);

[Theory]
[InlineData("6110000", "6110000")]
[InlineData("6189999", "6189999")]
[InlineData("6200000", "6200000")]
[InlineData("6269999", "6269999")]
[InlineData("6300000", "6300000")]
[InlineData("6309999", "6309999")]
[InlineData("6320000", "6320000")]
[InlineData("6329999", "6329999")]
[InlineData("6360000", "6360000")]
[InlineData("6419999", "6419999")]
[InlineData("6440000", "6440000")]
[InlineData("6449999", "6449999")]
[InlineData("6460000", "6460000")]
[InlineData("6479999", "6479999")]
[InlineData("6490000", "6490000")]
[InlineData("6519999", "6519999")]
[InlineData("6550000", "6550000")]
[InlineData("6559999", "6559999")]
[InlineData("6590000", "6590000")]
[InlineData("6669999", "6669999")]
[InlineData("6690000", "6690000")]
[InlineData("6709999", "6709999")]
[InlineData("6800000", "6800000")]
[InlineData("6809999", "6809999")]
[InlineData("6860000", "6860000")]
[InlineData("6999999", "6999999")]
[InlineData("7600000", "7600000")]
[InlineData("7939999", "7939999")]
[InlineData("8200000", "8200000")]
[InlineData("8259999", "8259999")]
[InlineData("8290000", "8290000")]
[InlineData("8689999", "8689999")]
[InlineData("8820000", "8820000")]
[InlineData("8839999", "8839999")]
[InlineData("8880000", "8880000")]
[InlineData("8889999", "8889999")]
[InlineData("8900000", "8900000")]
[InlineData("8999999", "8999999")]
[InlineData("358000000", "358000000")]
[InlineData("358999999", "358999999")]
[InlineData("388000000", "388000000")]
[InlineData("389999999", "389999999")]
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<MobilePhoneNumber>(phoneNumber);

var mobilePhoneNumber = (MobilePhoneNumber)phoneNumber;
Assert.Equal(CountryInfo.Iceland, mobilePhoneNumber.Country);
Assert.False(mobilePhoneNumber.IsPager);
Assert.False(mobilePhoneNumber.IsVirtual);
Assert.Null(mobilePhoneNumber.NationalDestinationCode);
Assert.Equal(subscriberNumber, mobilePhoneNumber.SubscriberNumber);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
namespace PhoneNumbers.Tests.Parsers;

/// <summary>
/// Contains unit tests for the <see cref="DefaultPhoneNumberParser"/> class for Iceland <see cref="PhoneNumber"/>s.
/// </summary>
public class DefaultPhoneNumberParserTests_IS_NonGeographicPhoneNumber
{
private static readonly PhoneNumberParser s_parser = DefaultPhoneNumberParser.Create(CountryInfo.Iceland);

[Theory]
[InlineData("7500000", "7500000")]
[InlineData("7509999", "7509999")]
[InlineData("7550000", "7550000")]
[InlineData("7559999", "7559999")]
[InlineData("7570000", "7570000")]
[InlineData("7579999", "7579999")]
[InlineData("8010000", "8010000")]
[InlineData("8099999", "8099999")]
[InlineData("8780000", "8780000")]
[InlineData("8809999", "8809999")]
[InlineData("9090000", "9090000")]
[InlineData("9099999", "9099999")]
[InlineData("9540000", "9540000")]
[InlineData("9549999", "9549999")]
[InlineData("9580000", "9580000")]
[InlineData("9589999", "9589999")]
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<NonGeographicPhoneNumber>(phoneNumber);

var nonGeographicPhoneNumber = (NonGeographicPhoneNumber)phoneNumber;
Assert.Equal(CountryInfo.Iceland, 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("8009999", "8009999")]
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<NonGeographicPhoneNumber>(phoneNumber);

var nonGeographicPhoneNumber = (NonGeographicPhoneNumber)phoneNumber;
Assert.Equal(CountryInfo.Iceland, 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("352000000", "352000000")]
[InlineData("352999999", "352999999")]
public void Parse_Known_NonGeographicPhoneNumber_MachineToMachine(string value, string subscriberNumber)
{
var parseResult = s_parser.Parse(value);
parseResult.ThrowIfFailure();

var phoneNumber = parseResult.PhoneNumber;

Assert.NotNull(phoneNumber);
Assert.IsType<NonGeographicPhoneNumber>(phoneNumber);

var nonGeographicPhoneNumber = (NonGeographicPhoneNumber)phoneNumber;
Assert.Equal(CountryInfo.Iceland, nonGeographicPhoneNumber.Country);
Assert.False(nonGeographicPhoneNumber.IsFreephone);
Assert.True(nonGeographicPhoneNumber.IsMachineToMachine);
Assert.False(nonGeographicPhoneNumber.IsPremiumRate);
Assert.False(nonGeographicPhoneNumber.IsSharedCost);
Assert.Null(nonGeographicPhoneNumber.NationalDestinationCode);
Assert.Equal(subscriberNumber, nonGeographicPhoneNumber.SubscriberNumber);
}

[Theory]
[InlineData("0944000", "0944000")]
[InlineData("9000000", "9000000")]
[InlineData("9009999", "9009999")]
[InlineData("9015000", "9015000")]
[InlineData("9017000", "9017000")]
[InlineData("9019000", "9019000")]
[InlineData("9021999", "9021999")]
[InlineData("9025000", "9025000")]
[InlineData("9027999", "9027999")]
[InlineData("9029000", "9029000")]
[InlineData("9029999", "9029999")]
[InlineData("9031000", "9031000")]
[InlineData("9031999", "9031999")]
[InlineData("9033000", "9033000")]
[InlineData("9033999", "9033999")]
[InlineData("9035000", "9035000")]
[InlineData("9037000", "9037000")]
[InlineData("9040000", "9040000")]
[InlineData("9042000", "9042000")]
[InlineData("9047000", "9047000")]
[InlineData("9052000", "9052000")]
[InlineData("9057000", "9057000")]
[InlineData("9059000", "9059000")]
[InlineData("9059999", "9059999")]
[InlineData("9071000", "9071000")]
[InlineData("9073999", "9073999")]
[InlineData("9077000", "9077000")]
[InlineData("9077999", "9077999")]
[InlineData("9080000", "9080000")]
[InlineData("9083999", "9083999")]
[InlineData("9085000", "9085000")]
[InlineData("9087999", "9087999")]
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<NonGeographicPhoneNumber>(phoneNumber);

var nonGeographicPhoneNumber = (NonGeographicPhoneNumber)phoneNumber;
Assert.Equal(CountryInfo.Iceland, 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);
}
}
Loading

0 comments on commit d933ec4

Please sign in to comment.