【问题标题】:Best practice for parsing and validating mobile number解析和验证手机号码的最佳实践
【发布时间】:2010-12-30 14:28:56
【问题描述】:

我想知道在发送文本之前解析和验证手机号码的最佳做法是什么。我有可以工作的代码,但我想找到更好的方法(作为我的最后一个问题,这是我新年初决心编写更好质量代码的一部分!)。

目前我们非常宽容用户在表单上输入数字时,他们可以输入诸如“+44 123 4567890”、“00441234567890”、“0123456789”、“+44(0)123456789”、“ 012-345-6789”甚至“没有电话”。

但是,要发送文本,格式必须为 44xxxxxxxxxx(这仅适用于英国手机),因此我们需要先对其进行解析和验证,然后才能发送。以下是我现在拥有的代码(C#,asp.net),如果有人对如何改进它有任何想法,那就太好了。

谢谢,

安妮

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;
    }

编辑

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

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, "");
    }

【问题讨论】:

  • 修剪前导零而不是替换“0044”。
  • 好点子,我已经编辑过了,谢谢!
  • 您不能只修剪前导零,因为“0712345678”将变为“712345678”。 number.Trim 也会修剪尾随和前导零,这也是个坏主意。
  • @ShellShock - 我确实想去掉前导零,但你是对的,在执行 number.Trim 时尾随零也会消失。我必须找到另一种方法来修剪领先的。

标签: c# asp.net parsing validation


【解决方案1】:

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

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

或者,我建议您使用带掩码的文本框来收集 #(有很多可用选项)以仅允许数字输入,并以您喜欢的任何格式显示输入。这样您就可以保证收到的值都是数字字符。

【讨论】:

  • 我为 SMS 网关提供的文档将 44xxxxxxxxxx 指定为发送号码的格式,但他们也可能接受 +44、0044 和 0xxxxxxxxx。但是,我们希望他们能够在表格上输入任何这些,即使他们可以在那里输入非英国号码,我们仍然需要确保文本只发送到英国号码。也许这与修剪和替换方法的组合是要走的路?
  • 如果您需要接受多种格式,那么蒙面文本框可能不是可行的方法,因为我想不出一种方法使其足够通用以满足您的要求。但是,上述方法对于从输入字符串中删除任何非数字字符非常有用。
【解决方案2】:

查看 QAS,它是一种商业解决方案。

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:
      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;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-09-25
        • 1970-01-01
        • 1970-01-01
        • 2011-09-22
        • 2020-01-24
        • 2015-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多