格式化字符串为英国电话号码

时间:2009-01-23 13:31:48

标签: c# regex formatting user-interface

我正在寻找一个例程,将一串数字格式化为英国电话号码。该例程应考虑需要不同格式的英国区域代码(即伦敦与爱丁堡相比,与伍斯特相比)以及手机号码。

我的电话号码作为字符串存储在数据库中,仅包含数字字符。

到目前为止,我已经提出了这个问题,但表现似乎很差。

/// <summary>
/// Formats a string as a UK phone number
/// </summary>
/// <remarks>
/// 02012345678 becomes 020 1234 5678
/// 01311234567 becomes 0131 123 4567
/// 01905123456 becomes 01905 123456
/// 07816123456 becomes 07816 123456
/// </remarks>
public static string FormatPhoneNumber(string phoneNumber)
{
    string formattedPhoneNumber = null;

    if (!string.IsNullOrEmpty(phoneNumber))
    {
        System.Text.RegularExpressions.Regex area1 = new System.Text.RegularExpressions.Regex(@"^0[1-9]0");
        System.Text.RegularExpressions.Regex area2 = new System.Text.RegularExpressions.Regex(@"^01[1-9]1");

        string formatString;

        if (area1.Match(phoneNumber).Success)
        {
            formatString = "0{0:00 0000 0000}";
        }
        else if (area2.Match(phoneNumber).Success)
        {
            formatString = "0{0:000 000 0000}";
        }
        else
        {
            formatString = "0{0:0000 000000}";
        }

        formattedPhoneNumber = string.Format(formatString, Int64.Parse(phoneNumber));
    }

    return formattedPhoneNumber;
}

欢迎如何改善这一点......

修改

我最初的想法是我应该将电话号码存储为数据库中的数字字段,然后我可以不使用Int64.Parse和知道它们是真正的数字。

编辑2

电话号码将全部为英国地理或英国手机号码,因此不需要考虑像0800这样的特殊情况

4 个答案:

答案 0 :(得分:12)

英国电话号码的长度从7位到10位不等,不包括前导零。 “区域”代码可以在2到4个(但偶尔为5个)数字之间变化。

所有显示每个数字前缀的区号和总长度的表都可从OFCOM's website获得。注意:这些表格非常长。

此外,对于确切放置空间的位置没有标准。有些人可能会把它们放在不同的地方,这取决于它产生文本的“可读性”。

答案 1 :(得分:2)

**我正在寻找一个将一串数字格式化为英国电话号码的例程。 **

您可以下载Ofcom数据库,其中列出了每个号码范围的格式,包括全国拨号号码,并查找您需要格式化的每个号码。数据库列出了每个范围的SABCDE数字和格式:0 + 10,2 + 8,3 + 7,4 + 6,4 + 5,5 + 5或5 + 4。

数据库中存在少量错误(尤其是01697和0169 77代码),但在超过25万个条目中,错误数量少于10个。

有四个文件涵盖01和02号码,以及各种非地理号码范围的单独文件。

0 + 10个号码是“全国拨号”,并且在区号部分周围没有括号。区号为所有02号码的02x,所有011x和01x1号码的01xx,以及大多数其他01号码的01xxx(非常小的数字 - 大约十几个 - 将是01xx xx)。

括号围绕所有其他01和02号码上的区号(即,使用01和02号码上的括号,其中本地号码部分以0或1开头)。括号表示通过省略括号括起来的数字,可以在同一区域内进行本地拨号。

2 + 8命名法显示区号和本地号码长度,条目2075:2 + 8表示号码格式为(020)75xx xxxx。请记住,在2 + 8判断中,前导零不会被“计算”。

**英国电话号码的长度从8位到12位不等**

没有。自2000年以来,大多数都在'0'中继代码之后有10位数字。少数仍然在'0'中继代码后有9位数字。

还需要考虑一些特殊数字,如0800 1111和0845 4647。

**“区域”代码可以在2到4位数之间变化。 **

区号可以在2到5位之间变化(不计算前导零)。需要说明的是,'020'被归类为2位区号,因为前导0实际上是中继码。还有011x和01x1区号,大多数其他区号都有01xxx区号。后者可能具有仅5位数的本地数字,而不是更广泛发现的6位数本地数字。一个非常小的数字有一个01xx xx区号,它们有5或4位本地号码。

**此外,对于确切放置空间的位置没有标准。 **

所有01和02号码的区号部分和本地号码部分之间总是有空格。

传统的(01xx xx)区域代码在区域代码中有一个空格,如图所示。这表示此系统仍在使用的旧本地交换分组。其他(较短的)区号不分开。

7位或8位数的本地数字在结尾的第四位数之前有一个分割。 4位,5位或6位的本地号码不会分开。这同样适用于地理和非地理数字。

对于大多数03,08和09号码,该号码写为0xxx xxx xxxx。

某些0800和所有0500号码都写成0xxx xxxxxx。

对于055,056和070数字,该数字写为0xx xxxx xxxx。

对于手机和寻呼机号码,请使用07xxx xxxxxx。

**除了有些人使用'08000 abc def'而不是'0800 0abc def'**

该用法不正确。请注意,一些0800号码在0中继码后有9位数字,而其他号码在0中继码后有10位数字。

所以,0800 xxxxxx和0800 xxx xxxx都是正确的。

0500号码仅使用0500 xxxxxx。

大多数03,08和09编号写为0xxx xxx xxxx。

另见: http://en.wikipedia.org/wiki/Local_conventions_for_writing_telephone_numbers#United_Kingdom

答案 2 :(得分:2)

我花了一些时间浏览OFCOM表并提出以下内容。

public static class TelephoneHelper
{

    #region Regex Patterns
    private static readonly Regex[] patterns = 
    {
        new Regex(@"(?<first>013873)(?<second>\d{5})"),
        new Regex(@"(?<first>015242)(?<second>\d{5})"),
        new Regex(@"(?<first>015394)(?<second>\d{5})"),
        new Regex(@"(?<first>015395)(?<second>\d{5})"),
        new Regex(@"(?<first>015396)(?<second>\d{5})"),
        new Regex(@"(?<first>016973)(?<second>\d{5})"),
        new Regex(@"(?<first>016974)(?<second>\d{5})"),
        new Regex(@"(?<first>016977)(?<second>\d{4}\d?)"),
        new Regex(@"(?<first>017683)(?<second>\d{5})"),
        new Regex(@"(?<first>017684)(?<second>\d{5})"),
        new Regex(@"(?<first>017687)(?<second>\d{5})"),
        new Regex(@"(?<first>019467)(?<second>\d{5})"),
        new Regex(@"(?<first>02\d)(?<second>\d{4})(?<third>\d{4})"),
        new Regex(@"(?<first>03\d{2})(?<second>\d{3})(?<third>\d{4})"),
        new Regex(@"(?<first>0500\d{6})"),
        new Regex(@"(?<first>05\d{3})(?<second>\d{6})"),
        new Regex(@"(?<first>07\d{3})(?<second>\d{6})"),
        new Regex(@"(?<first>08\d{2})(?<second>\d{3})(?<third>\d{3}\d?)"),
        new Regex(@"(?<first>09\d{2})(?<second>\d{3})(?<third>\d{4})"),
        new Regex(@"(?<first>01\d1)(?<second>\d{3})(?<third>\d{4})"),
        new Regex(@"(?<first>011\d)(?<second>\d{3})(?<third>\d{4})"),
        new Regex(@"(?<first>01\d{3})(?<second>\d{5}\d?)")
    };
    #endregion

    public static string FormatAsUkTelephone(this string number)
    {
        Regex matchedPattern = null;
        foreach (Regex pattern in patterns)
        {
            if (pattern.IsMatch(number))
            {
                matchedPattern = pattern;
                break;
            }
        }
        if (matchedPattern != null)
        {
            var mc = matchedPattern.Matches(number);
            if (mc[0].Groups.Count == 3)
            {
                return String.Format("{0} {1}", mc[0].Groups["first"], mc[0].Groups["second"]);
            }
            else if (mc[0].Groups.Count == 4)
            {
                return String.Format("{0} {1} {2}", mc[0].Groups["first"], mc[0].Groups["second"], mc[0].Groups["third"]);
            }
        }
        return number;
    }

答案 3 :(得分:1)

我很想使用更严格的规则来检查熊的最小值;因此,假设前导零在数据库中,伪代码将是:

if( phoneNumber.substring(1,1) == "2" )
{
    // 000 0000 0000
}
else if( phoneNumber.substring(1,1) == "1" && (phoneNumber.substring(1,1) == "2" || phoneNumber.substring(3,1) = "1") )
{
    // 0000 000 0000
}
else
{
    // 00000 000000
}

NB。你的模式有点错误023是三位数代码,0800不是