UK Telephone Number Formatting to Ofcom Specifications

Throughout StackOverflow there's many chunks of code dealing in various ways with telephone numbers.

Most of them use the US telephone number format. There are also a few that are usable for some UK numbers, but not all produce the right results.

The code below formats UK telephone numbers as follows:

Non-geographic numbers beginning 03, 08 and 09 are formatted as  0xxx  xxx  xxxx  and  +44  xxx  xxx  xxxx.

Mobile numbers beginning 07 are formatted as  07xxx  xxxxxx  and  +44  7xxx  xxxxxx.

VoIP and other 05 numbers are formatted as  05xxx xxxxxx  and  +44  5xxx  xxxxxx.

Numbers beginning 01 and 02 are geographic numbers. These have a variable length area code. The latest Ofcom specifications as published at  www.ofcom.org.uk/static/numbering/sabc.txt and www.ofcom.org.uk/static/numbering/codelist.zip  have been used to ensure accuracy.

Ofcom list 0113/0114/0115/0116/0117/0118 and 0121/0141 as having a 3 digit area code and 015242, 013873, 015394/015395/015396, 016973/016974, 017683/017684/017687 and 019467 as having a 5 digit area code. The remainder use a 4 digit area code. 0171 and 0181 used to be 3 digit area codes in London but are no longer in use.

The PHP code is simple to test with the included simple form-based input. The form can be discarded if the code is used in some other manner.

The input is first stripped of any leading international access code and country code digits. After stipping extraneous characters, such as spaces and punctuation, as well as any trunk digit if present, the number length is then checked to ensure it is 10 digits long and in a valid range. The number is then formatted using a small set of simple rules.

Basic support for extension numbers appended in the form "ext. 234" or "x 234" is also included. 

The final output is presented in both national and international format.

The code doesn't take into account the non-standard numbers 0800 1111 and 0845 4647. These are unusual in having only 7 digits.




    <?php
    
    // format UK telephone numbers using Ofcom specifications
    // www.ofcom.org.uk/static/numbering/sabc.txt
    // www.ofcom.org.uk/static/numbering/codelist.zip
    
    
    
    // parse submitted form variables
    
    if (ISSET($_POST['tel_form']) && ($_POST['tel_form'] == "1")) {
    
      if (ISSET($_POST['tel_num'])) {
    
        $tel_num = $_POST['tel_num'];
    
        $text = '    <p><b>Number as input:</b> ' . $tel_num . "</p>\n";
    
    
    
    // remove leading +44, 00 44, 011 44 if present
    
        $leadingPattern = '/^(\+|00|011)?\ ?44(.*)/';
        if (preg_match($leadingPattern, $tel_num, $leadingMatches)) {
          $tel_num = $leadingMatches[2];
        }
    
    
    
    // remove and separately store any extension number
    
        $extPattern = '/((ext|x)(.*))/';
        if (preg_match($extPattern, $tel_num, $extMatches)) {
          $extension = $extMatches[1];
        }
        $extReplacements = '';
        $tel_num = preg_replace($extPattern, $extReplacements, $tel_num);
    
    
    
    // remove all non-digit characters and punctuation
    
        $nonDigitPattern = '([^0-9]+)';
        $nonDigitReplacements = '';
        $tel_num = preg_replace($nonDigitPattern, $nonDigitReplacements, $tel_num);
        $extension = preg_replace($nonDigitPattern, $nonDigitReplacements, $extension);
    
    
    
    // remove leading 0 if present
    
        $leadingZeroPattern = '/^0+(.*)/';
        if (preg_match($leadingZeroPattern, $tel_num, $leadingZeroMatches)) {
          $tel_num = $leadingZeroMatches[1];
        }
    
    
    
    // check remaining number length is 10 digits long
    
        if (strlen($tel_num) < '10') {
          $text .= '    <p>' . 'Telephone number too short.' . "</p>\n";
        }
    
        elseif (strlen($tel_num) > '10') {
          $text .= '    <p>' . 'Telephone number too long.' . "</p>\n";
        }
    
    
    
    // format valid numbers
    
        else {
    
    
    // format 3 digit area code for 0113/4/5/6/7/8, 0121, 0141
    
          $length3pattern = '/^(1(1[345678]|[24]1))([0-9]{3})(.*)/';
          if (preg_match($length3pattern, $tel_num, $matches)) {
            $formatted_number = $matches[1] . ' ' . $matches[3] . ' ' . $matches[4];
          }
    
    
    
    // format 5 digit area code for 015242, 013873, 015394/5/6, 016973/4, 017683/4/7, 019467
    
          $length5pattern = '/^(1(3873|5242|539[456]|697[34]|768[347]|9467))(.*)/';
          if (preg_match($length5pattern, $tel_num, $matches)) {
            $formatted_number = $matches[1] . ' ' . $matches[3];
          }
    
    
    
    // format non-geographic numbers
    
          $NGNpattern = '/^([389][0-9]{2})([0-9]{3})(.*)/';
          if (preg_match($NGNpattern, $tel_num, $matches)) {
            $formatted_number = $matches[1] . ' ' . $matches[2] . ' ' . $matches[3];
          }
    
    
    
    // format all other numbers
    
          if (!ISSET($formatted_number)) {
            $pattern = '/^([1257][0-9]{3})(.*)/';
            if (preg_match($pattern, $tel_num, $matches)) {
              $formatted_number = $matches[1] . ' ' . $matches[2];
            }
    
    
    // else warn that number isn't valid
    
            else {
              $text .= "    <p>Telephone number probably not valid.</p>\n";
            }
          }
    
    
    
    // store number in international and national formats
    
        }
    
        if (ISSET($formatted_number)) {
    
          $int_formatted_number = '+44 ' . $formatted_number;
          $text .= '    <p><b>International format:</b> ' . $int_formatted_number . "</p>\n";
    
          $codePattern = '/^([12][^\ ]+)(\ .*)/';
          if (preg_match($codePattern, $formatted_number, $matches)) {
            $nat_formatted_number = '(0' . $matches[1] . ') ' . $matches[2];
          }
          else {
            $nat_formatted_number = '0' . $formatted_number;
          }
          $text .= '    <p><b>National format:</b> ' . $nat_formatted_number . "</p>\n";
    
          if ((ISSET($extension)) && (!empty($extension))) {
            $text .= '    <p><b>Extension:</b> ' . $extension . "</p>\n";
          }
    
        }
    
    
    
    // show start message for first time form use
    
      }
    }
    else {
      $text = "    <p><b>Please start by entering a UK telephone number.</b></p>\n";
    }
    
    
    
    // show HTML page with form for input
    ?>
    <!DOCTYPE html>
    
    <html>
    
      <head>
    
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>UK telephone number formatter</title>
    
      </head>
    
    <body>
    
    <?php
    if (ISSET($text)) {
      print $text;
    }
    ?>
    
        <hr>
    
    <?php
    if ((ISSET($tel_num)) && (!empty($tel_num))) {
      $tel_num = '0' . $tel_num;
    }
    ?>
        <form action="telnum.php" name="input" method="post">
          <p><b>Enter a UK telephone number to format:</b> <input type="text" name="tel_num" value="<?php print $tel_num; ?>" />
          <input type="hidden" name="tel_form" value="1" />
          <input type="submit" value="submit" /></p>
        </form>
    
      </body>
    
    </html>
    


UK Telephone Number Formatting to Ofcom Specifications
===


Throughout StackOverflow there's many chunks of code dealing in various ways with telephone numbers.

Most of them use the US telephone number format. There are also a few that are usable for some UK numbers, but not all produce the right results.

The code below formats UK telephone numbers as follows:

Non-geographic numbers beginning 03, 08 and 09 are formatted as  0xxx  xxx  xxxx  and  +44  xxx  xxx  xxxx.

Mobile numbers beginning 07 are formatted as  07xxx  xxxxxx  and  +44  7xxx  xxxxxx.

VoIP and other 05 numbers are formatted as  05xxx xxxxxx  and  +44  5xxx  xxxxxx.

Numbers beginning 01 and 02 are geographic numbers. These have a variable length area code. The latest Ofcom specifications as published at  www.ofcom.org.uk/static/numbering/sabc.txt and www.ofcom.org.uk/static/numbering/codelist.zip  have been used to ensure accuracy.

Ofcom list 0113/0114/0115/0116/0117/0118 and 0121/0141 as having a 3 digit area code and 015242, 013873, 015394/015395/015396, 016973/016974, 017683/017684/017687 and 019467 as having a 5 digit area code. The remainder use a 4 digit area code. 0171 and 0181 used to be 3 digit area codes in London but are no longer in use.

The PHP code is simple to test with the included simple form-based input. The form can be discarded if the code is used in some other manner.

The input is first stripped of any leading international access code and country code digits. After stipping extraneous characters, such as spaces and punctuation, as well as any trunk digit if present, the number length is then checked to ensure it is 10 digits long and in a valid range. The number is then formatted using a small set of simple rules.

Basic support for extension numbers appended in the form "ext. 234" or "x 234" is also included. 

The final output is presented in both national and international format.

The code doesn't take into account the non-standard numbers 0800 1111 and 0845 4647. These are unusual in having only 7 digits.




    <?php
    
    // format UK telephone numbers using Ofcom specifications
    // www.ofcom.org.uk/static/numbering/sabc.txt
    // www.ofcom.org.uk/static/numbering/codelist.zip
    
    
    
    // parse submitted form variables
    
    if (ISSET($_POST['tel_form']) && ($_POST['tel_form'] == "1")) {
    
      if (ISSET($_POST['tel_num'])) {
    
        $tel_num = $_POST['tel_num'];
    
        $text = '    <p><b>Number as input:</b> ' . $tel_num . "</p>\n";
    
    
    
    // remove leading +44, 00 44, 011 44 if present
    
        $leadingPattern = '/^(\+|00|011)?\ ?44(.*)/';
        if (preg_match($leadingPattern, $tel_num, $leadingMatches)) {
          $tel_num = $leadingMatches[2];
        }
    
    
    
    // remove and separately store any extension number
    
        $extPattern = '/((ext|x)(.*))/';
        if (preg_match($extPattern, $tel_num, $extMatches)) {
          $extension = $extMatches[1];
        }
        $extReplacements = '';
        $tel_num = preg_replace($extPattern, $extReplacements, $tel_num);
    
    
    
    // remove all non-digit characters and punctuation
    
        $nonDigitPattern = '([^0-9]+)';
        $nonDigitReplacements = '';
        $tel_num = preg_replace($nonDigitPattern, $nonDigitReplacements, $tel_num);
        $extension = preg_replace($nonDigitPattern, $nonDigitReplacements, $extension);
    
    
    
    // remove leading 0 if present
    
        $leadingZeroPattern = '/^0+(.*)/';
        if (preg_match($leadingZeroPattern, $tel_num, $leadingZeroMatches)) {
          $tel_num = $leadingZeroMatches[1];
        }
    
    
    
    // check remaining number length is 10 digits long
    
        if (strlen($tel_num) < '10') {
          $text .= '    <p>' . 'Telephone number too short.' . "</p>\n";
        }
    
        elseif (strlen($tel_num) > '10') {
          $text .= '    <p>' . 'Telephone number too long.' . "</p>\n";
        }
    
    
    
    // format valid numbers
    
        else {
    
    
    // format 3 digit area code for 0113/4/5/6/7/8, 0121, 0141
    
          $length3pattern = '/^(1(1[345678]|[24]1))([0-9]{3})(.*)/';
          if (preg_match($length3pattern, $tel_num, $matches)) {
            $formatted_number = $matches[1] . ' ' . $matches[3] . ' ' . $matches[4];
          }
    
    
    
    // format 5 digit area code for 015242, 013873, 015394/5/6, 016973/4, 017683/4/7, 019467
    
          $length5pattern = '/^(1(3873|5242|539[456]|697[34]|768[347]|9467))(.*)/';
          if (preg_match($length5pattern, $tel_num, $matches)) {
            $formatted_number = $matches[1] . ' ' . $matches[3];
          }
    
    
    
    // format non-geographic numbers
    
          $NGNpattern = '/^([389][0-9]{2})([0-9]{3})(.*)/';
          if (preg_match($NGNpattern, $tel_num, $matches)) {
            $formatted_number = $matches[1] . ' ' . $matches[2] . ' ' . $matches[3];
          }
    
    
    
    // format all other numbers
    
          if (!ISSET($formatted_number)) {
            $pattern = '/^([1257][0-9]{3})(.*)/';
            if (preg_match($pattern, $tel_num, $matches)) {
              $formatted_number = $matches[1] . ' ' . $matches[2];
            }
    
    
    // else warn that number isn't valid
    
            else {
              $text .= "    <p>Telephone number probably not valid.</p>\n";
            }
          }
    
    
    
    // store number in international and national formats
    
        }
    
        if (ISSET($formatted_number)) {
    
          $int_formatted_number = '+44 ' . $formatted_number;
          $text .= '    <p><b>International format:</b> ' . $int_formatted_number . "</p>\n";
    
          $codePattern = '/^([12][^\ ]+)(\ .*)/';
          if (preg_match($codePattern, $formatted_number, $matches)) {
            $nat_formatted_number = '(0' . $matches[1] . ') ' . $matches[2];
          }
          else {
            $nat_formatted_number = '0' . $formatted_number;
          }
          $text .= '    <p><b>National format:</b> ' . $nat_formatted_number . "</p>\n";
    
          if ((ISSET($extension)) && (!empty($extension))) {
            $text .= '    <p><b>Extension:</b> ' . $extension . "</p>\n";
          }
    
        }
    
    
    
    // show start message for first time form use
    
      }
    }
    else {
      $text = "    <p><b>Please start by entering a UK telephone number.</b></p>\n";
    }
    
    
    
    // show HTML page with form for input
    ?>
    <!DOCTYPE html>
    
    <html>
    
      <head>
    
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>UK telephone number formatter</title>
    
      </head>
    
    <body>
    
    <?php
    if (ISSET($text)) {
      print $text;
    }
    ?>
    
        <hr>
    
    <?php
    if ((ISSET($tel_num)) && (!empty($tel_num))) {
      $tel_num = '0' . $tel_num;
    }
    ?>
        <form action="telnum.php" name="input" method="post">
          <p><b>Enter a UK telephone number to format:</b> <input type="text" name="tel_num" value="<?php print $tel_num; ?>" />
          <input type="hidden" name="tel_form" value="1" />
          <input type="submit" value="submit" /></p>
        </form>
    
      </body>
    
    </html>
    

