Introduction
The function provided below validates a telephone against the requirements of the North American Number Plan (NANP) as administered by Neustar, Inc.
Background
While designing a database application for the company I was working for at the time, I needed a way to ensure that the telephone numbers entered were valid. Initially, I used just regular expressions to make sure that the numbers were valid, but in time it was discovered that some of the phone numbers entered matched the valid pattern, however the numbers were still invalid. The North American Number Plan specifies rules that a phone number must follow such as what range of numbers are valid for area codes, exchange codes, test codes, etc.
Using the Code
This function will accept either a 10-digit or 11-digit phone number, with or without hyphens. Any hyphens are stripped out and any leading '1' (if present) is removed, leaving a 10-digit phone number which is validated. A 10-digit phone number is made up of the following parts:
NPA-NXX-XXXX
Where:
NPA = Number Plan Area Code (Area Code) - 3 digits
NXX = Central Office (Exchange) Code - 3 digits
XXXX = Subscriber Number - 4 digits
The code is highly commented along with the name, and ID numbers, of the reference documents used to develop this function. I believe it meets just about, if not every, requirement for phone numbers complying with the NANP. If there are any requirements missing, I apologize in advance; there are many industry technical documents on this topic and some of it is beyond my understanding.
Public Function IsTelephoneNumberValid(number As String) As Boolean
Const NRegEx As String = "^[2-9]\d{2}$"
Const XXXXRegEx As String = "^\d{4}$"
Dim strippedNumber As String
Dim NPA As String
Dim NXX As String
Dim XXXX As String
strippedNumber = Regex.Replace(number, "[^0-9]", String.Empty)
If strippedNumber.Length = 11 AndAlso strippedNumber.Substring(0, 1) = "1" Then
strippedNumber = strippedNumber.Substring(1, 10)
ElseIf strippedNumber.Length <> 10 Then
Return False
End If
NPA = strippedNumber.Substring(0, 3)
NXX = strippedNumber.Substring(3, 3)
XXXX = strippedNumber.Substring(6, 4)
If Not Regex.IsMatch(NPA, NRegEx) OrElse Not Regex.IsMatch(NXX, NRegEx) _
OrElse Not Regex.IsMatch(XXXX, XXXXRegEx) Then
Return False
ElseIf NPA.Substring(0, 2) = "37" OrElse NPA.Substring(0, 2) = "96" Then
Return False
ElseIf NXX.Substring(1, 2) = "11" AndAlso (CInt(NXX) >= 211 AndAlso CInt(NXX) <= 911) Then
Return False
ElseIf NXX = "912" OrElse NXX = "913" OrElse NXX = "914" _
OrElse NXX = "915" OrElse NXX = "916" Then
Return False
ElseIf NXX = "700" OrElse NXX = "950" OrElse NXX = "958" OrElse NXX = "959" Then
Return False
ElseIf NXX = "555" Then
If CInt(XXXX) >= 100 AndAlso CInt(XXXX) <= 199 Then
Return False
End If
End If
Return True
End Function
History
- 09/12/2014 - Updated an error which would cause a valid exchange code of 111 to be returned as invalid. Thanks to Jeremy Forsythe for finding this and pointing it out. Fixed a couple of small grammar errors.
- 10/18/2012 - Updated an error which would allow a phone number like 718-377-11205 to be entered and recognized as valid. Thanks to Matt Heffron for finding this and pointing it out. Fixed some grammar errors.
- 10/16/2012 - Initial version