Starting with @Ravi's answer, I also applied some validation rules for the NPA (Area) Code.
In particular:
- It should start with a 2 (or higher)
- It cannot have "11" as the second and third digits (N11).
There are a couple other restrictions, including reserved blocks (N9X, 37X, 96X) and 555, but I left those out, particularly because the reserved blocks may see future use, and 555 is useful for testing.
This is what I came up with:
^((\+\d{1,2}|1)[\s.-]?)?\(?[2-9](?!11)\d{2}\)?[\s.-]?\d{3}[\s.-]?\d{4}$
Alternately, if you also want to match blank values (if the field isn't required), you can use:
(^((\+\d{1,2}|1)[\s.-]?)?\(?[2-9](?!11)\d{2}\)?[\s.-]?\d{3}[\s.-]?\d{4}$|^$)
My test cases for valid numbers (many from @Francis' answer) are:
18005551234
1 800 555 1234
+1 800 555-1234
+86 800 555 1234
1-800-555-1234
1.800.555.1234
+1.800.555.1234
1 (800) 555-1234
(800)555-1234
(800) 555-1234
(800)5551234
800-555-1234
800.555.1234
My invalid test cases include:
(003) 555-1212 // Area code starts with 0
(103) 555-1212 // Area code starts with 1
(911) 555-1212 // Area code ends with 11
180055512345 // Too many digits
1 800 5555 1234 // Prefix code too long
+1 800 555x1234 // Invalid delimiter
+867 800 555 1234 // Country code too long
1-800-555-1234p // Invalid character
1 (800) 555-1234 // Too many spaces
800x555x1234 // Invalid delimiter
86 800 555 1212 // Non-NA country code doesn't have +
My regular expression does not include grouping to extract the digit groups, but it can be modified to include those.