解析和验证手机号码的最佳做法

时间:2022-10-24 20:16:26

I wonder what the best practice for parsing and validating a mobile number before sending a text is. I've got code that works, but I'd like to find out better ways of doing it (as my last question, this is part of my early new years resolution to write better quality code!).

我想知道在发送文本之前解析和验证手机号码的最佳做法是什么。我已经有了可行的代码,但我想找到更好的方法(我的上一个问题,这是我早期新年决议中编写质量更好的代码的一部分!)。

At the moment we are very forgiving when the user enters the number on the form, they can enter things like "+44 123 4567890", "00441234567890", "0123456789", "+44(0)123456789", "012-345-6789" or even "haven't got a phone".

当用户输入表格上的号码时,我们非常宽容,他们可以输入“+44 123 4567890”,“00441234567890”,“0123456789”,“+ 44(0)123456789”,“012-345”等内容-6789“甚至”没有电话“。

However, to send the text the format must be 44xxxxxxxxxx (this is for UK mobiles only), so we need to parse it and validate it before we can send. Below is the code that I have for now (C#, asp.net), it would be great if anyone had any ideas on how to improve it.

但是,要发送文本格式必须是44xxxxxxxxxx(这仅适用于英国手机),因此我们需要解析并验证它才能发送。下面是我现在的代码(C#,asp.net),如果有人对如何改进它有任何想法会很棒。

Thanks,

Annelie

private bool IsMobileNumberValid(string mobileNumber)
    {
        // parse the number
        _mobileNumber = ParsedMobileNumber(mobileNumber);

        // check if it's the right length
        if (_mobileNumber.Length != 12)
        {
            return false;
        }

        // check if it contains non-numeric characters
        if(!Regex.IsMatch(_mobileNumber, @"^[-+]?[0-9]*\.?[0-9]+$"))
        {
            return false;
        }

        return true;
    }

    private string ParsedMobileNumber(string number)
    {
        number = number.Replace("+", "");
        number = number.Replace(".", "");
        number = number.Replace(" ", "");
        number = number.Replace("-", "");
        number = number.Replace("/", "");
        number = number.Replace("(", "");
        number = number.Replace(")", "");

        number = number.Trim(new char[] { '0' });

        if (!number.StartsWith("44"))
        {
            number = "44" + number;
        }

        return number;
    }

EDIT

Here's what I ended up with:

这就是我最终得到的结果:

private bool IsMobileNumberValid(string mobileNumber)
    {
        // remove all non-numeric characters
        _mobileNumber = CleanNumber(mobileNumber);

        // trim any leading zeros
        _mobileNumber = _mobileNumber.TrimStart(new char[] { '0' });

        // check for this in case they've entered 44 (0)xxxxxxxxx or similar
        if (_mobileNumber.StartsWith("440"))
        {
            _mobileNumber = _mobileNumber.Remove(2, 1);
        }

        // add country code if they haven't entered it
        if (!_mobileNumber.StartsWith("44"))
        {
            _mobileNumber = "44" + _mobileNumber;
        }

        // check if it's the right length
        if (_mobileNumber.Length != 12)
        {
            return false;
        }

        return true;
    }

    private string CleanNumber(string phone)
    {
        Regex digitsOnly = new Regex(@"[^\d]");
        return digitsOnly.Replace(phone, "");
    }

4 个解决方案

#1


2  

Use a regular expression to remove any non-numeric characters instead of trying to guess how a person will enter their number - this will remove all your Replace() and Trim() methods, unless you really need to trim a leading zero.

使用正则表达式删除任何非数字字符,而不是试图猜测一个人将如何输入他们的数字 - 这将删除所有的Replace()和Trim()方法,除非你真的需要修剪前导零。

string CleanPhone(string phone)
{
    Regex digitsOnly = new Regex(@"[^\d]");   
    return digitsOnly.Replace(phone, "");
}

Alternatively, I would recommend you use a masked textbox to collect the # (there are many options available) to allow only numeric input, and display the input with whatever format you'd like. This way you're guaranteeing that the value received will be all numeric characters.

或者,我建议您使用蒙版文本框来收集#(有许多可用选项)以仅允许数字输入,并以您想要的任何格式显示输入。这样,您可以保证收到的值将是所有数字字符。

#2


1  

Check out QAS, it's a commercial solution.

查看QAS,这是一个商业解决方案。

They have email, phone and address validations.

他们有电子邮件,电话和地址验证。

http://www.qas.com/phone-number-validation-web-service.htm

We use their services for Address and Email (not phone) and have been satisfied with it.

我们将他们的服务用于地址和电子邮件(而非电话),并对此感到满意。

#3


0  

@annelie maybe you can update your regular expression to a more powerful one. Check out this site here. It contains many expressions but I think one of the top 2 expressions in the site should be suitable to you.

@annelie也许您可以将正则表达式更新为更强大的正则表达式。在这里查看这个网站。它包含许多表达式,但我认为网站中前2个表达式之一应该适合您。

#4


0  

public class PhoneNumber
{
    public PhoneNumber(string value)
    {
        if (String.IsNullOrEmpty(value))
            throw new ArgumentNullException("numberString", Properties.Resources.PhoneNumberIsNullOrEmpty);

        var match = new Regex(@"\+(\w+) \((\w+)\) (\w+)", RegexOptions.Compiled).Match(value);
        if (match.Success)
        {
            ushort countryCode = 0;
            ushort localCode = 0;
            int number = 0;

            if (UInt16.TryParse(match.Result("$1"), out countryCode) &&
                UInt16.TryParse(match.Result("$2"), out localCode) &&
                Int32.TryParse(match.Result("$3"), out number))
            {
                this.CountryCode = countryCode;
                this.LocalCode = localCode;
                this.Number = number;
            }
        }
        else
        {
            throw new ArgumentNullException("numberString", Properties.Resources.PhoneNumberInvalid);
        }
    }

    public PhoneNumber(int countryCode, int localCode, int number)
    {
        if (countryCode == 0)
            throw new ArgumentOutOfRangeException("countryCode", Properties.Resources.PhoneNumberIsNullOrEmpty);
        else if (localCode == 0)
            throw new ArgumentOutOfRangeException("localCode", Properties.Resources.PhoneNumberIsNullOrEmpty);
        else if (number == 0)
            throw new ArgumentOutOfRangeException("number", Properties.Resources.PhoneNumberIsNullOrEmpty);

        this.CountryCode = countryCode;
        this.LocalCode = localCode;
        this.Number = number;
    }

    public int CountryCode { get; set; }

    public int LocalCode { get; set; }

    public int Number { get; set; }

    public override string ToString()
    {
        return String.Format(System.Globalization.CultureInfo.CurrentCulture, "+{0} ({1}) {2}", CountryCode, LocalCode, Number);
    }

    public static bool Validate(string value)
    {
        return new Regex(@"\+\w+ \(\w+\) \w+", RegexOptions.Compiled).IsMatch(value);
    }

    public static bool Validate(string countryCode, string localCode, string number, out PhoneNumber phoneNumber)
    {
        var valid = false;
        phoneNumber = null;
        try
        {
            ushort uCountryCode = 0;
            ushort uLocalCode = 0;
            int iNumber = 0;

            // match only if all three numbers have been parsed successfully
            valid = UInt16.TryParse(countryCode, out uCountryCode) &&
                    UInt16.TryParse(localCode, out uLocalCode) &&
                    Int32.TryParse(number, out iNumber);

            if (valid)
                phoneNumber = new PhoneNumber(uCountryCode, uLocalCode, iNumber);
        }
        catch (ArgumentException)
        {
            // still not match
        }
        return valid;
    }
}

#1


2  

Use a regular expression to remove any non-numeric characters instead of trying to guess how a person will enter their number - this will remove all your Replace() and Trim() methods, unless you really need to trim a leading zero.

使用正则表达式删除任何非数字字符,而不是试图猜测一个人将如何输入他们的数字 - 这将删除所有的Replace()和Trim()方法,除非你真的需要修剪前导零。

string CleanPhone(string phone)
{
    Regex digitsOnly = new Regex(@"[^\d]");   
    return digitsOnly.Replace(phone, "");
}

Alternatively, I would recommend you use a masked textbox to collect the # (there are many options available) to allow only numeric input, and display the input with whatever format you'd like. This way you're guaranteeing that the value received will be all numeric characters.

或者,我建议您使用蒙版文本框来收集#(有许多可用选项)以仅允许数字输入,并以您想要的任何格式显示输入。这样,您可以保证收到的值将是所有数字字符。

#2


1  

Check out QAS, it's a commercial solution.

查看QAS,这是一个商业解决方案。

They have email, phone and address validations.

他们有电子邮件,电话和地址验证。

http://www.qas.com/phone-number-validation-web-service.htm

We use their services for Address and Email (not phone) and have been satisfied with it.

我们将他们的服务用于地址和电子邮件(而非电话),并对此感到满意。

#3


0  

@annelie maybe you can update your regular expression to a more powerful one. Check out this site here. It contains many expressions but I think one of the top 2 expressions in the site should be suitable to you.

@annelie也许您可以将正则表达式更新为更强大的正则表达式。在这里查看这个网站。它包含许多表达式,但我认为网站中前2个表达式之一应该适合您。

#4


0  

public class PhoneNumber
{
    public PhoneNumber(string value)
    {
        if (String.IsNullOrEmpty(value))
            throw new ArgumentNullException("numberString", Properties.Resources.PhoneNumberIsNullOrEmpty);

        var match = new Regex(@"\+(\w+) \((\w+)\) (\w+)", RegexOptions.Compiled).Match(value);
        if (match.Success)
        {
            ushort countryCode = 0;
            ushort localCode = 0;
            int number = 0;

            if (UInt16.TryParse(match.Result("$1"), out countryCode) &&
                UInt16.TryParse(match.Result("$2"), out localCode) &&
                Int32.TryParse(match.Result("$3"), out number))
            {
                this.CountryCode = countryCode;
                this.LocalCode = localCode;
                this.Number = number;
            }
        }
        else
        {
            throw new ArgumentNullException("numberString", Properties.Resources.PhoneNumberInvalid);
        }
    }

    public PhoneNumber(int countryCode, int localCode, int number)
    {
        if (countryCode == 0)
            throw new ArgumentOutOfRangeException("countryCode", Properties.Resources.PhoneNumberIsNullOrEmpty);
        else if (localCode == 0)
            throw new ArgumentOutOfRangeException("localCode", Properties.Resources.PhoneNumberIsNullOrEmpty);
        else if (number == 0)
            throw new ArgumentOutOfRangeException("number", Properties.Resources.PhoneNumberIsNullOrEmpty);

        this.CountryCode = countryCode;
        this.LocalCode = localCode;
        this.Number = number;
    }

    public int CountryCode { get; set; }

    public int LocalCode { get; set; }

    public int Number { get; set; }

    public override string ToString()
    {
        return String.Format(System.Globalization.CultureInfo.CurrentCulture, "+{0} ({1}) {2}", CountryCode, LocalCode, Number);
    }

    public static bool Validate(string value)
    {
        return new Regex(@"\+\w+ \(\w+\) \w+", RegexOptions.Compiled).IsMatch(value);
    }

    public static bool Validate(string countryCode, string localCode, string number, out PhoneNumber phoneNumber)
    {
        var valid = false;
        phoneNumber = null;
        try
        {
            ushort uCountryCode = 0;
            ushort uLocalCode = 0;
            int iNumber = 0;

            // match only if all three numbers have been parsed successfully
            valid = UInt16.TryParse(countryCode, out uCountryCode) &&
                    UInt16.TryParse(localCode, out uLocalCode) &&
                    Int32.TryParse(number, out iNumber);

            if (valid)
                phoneNumber = new PhoneNumber(uCountryCode, uLocalCode, iNumber);
        }
        catch (ArgumentException)
        {
            // still not match
        }
        return valid;
    }
}