question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

International phone number without a plus sign parsed invalid

See original GitHub issue

formatInternational() doubles the country code. It’s a common case to parse a phone without a plus sign. For exampl, sms gateways accept both variants: with or without a plus, also many apps exports phones without a plus (yes, it’s completely incorrect, but this happens everywhere). Can it be handled automatically or should a person decide by himself add a plus or not, even when the country code is specified?

parsePhoneNumberFromString('375447521111', 'BY')
PhoneNumber

  country: "BY"

  countryCallingCode: "375"

  metadata: {version: "1.7.40", country_calling_codes: Object, countries: Object, nonGeographic: Object}

  nationalNumber: "375447521111"

  number: "+375375447521111"

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
blasterpistolcommented, Feb 16, 2020

Works like a charm!

1reaction
catamphetaminecommented, Feb 15, 2020

@testarossaaaaa Hmm, actually that’s a valid correction. Isn’t the isValid() check too strict though? isValid() returns true if the number matches the exact regular expressions for the country. For example, for mobile numbers in France it’s 700\d{6}|(?:6\d|7[3-9])\d{7}. There’s also another way just to validate phone number length: isPossible(). For France it’s possible_lengths: [9]. For Germany, it’s possible_lengths: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], so isPossible() check wouldn’t be so reliable for Germany (+49), because it could be a “possible” 10-digit “local” number, or it could be a “possible” 8-digit “local” number plus the 49 country calling code prepended to it, so just isPossible() wouldn’t tell those two apart (49 is a valid “area code” in Germany). isValid() is more precise, but that’s only if you’re looking for only “valid” numbers, dismissing all other “possible” numbers.

How does Google behave in this scenario? https://github.com/google/libphonenumber/blob/master/FAQ.md#why-wasnt-the-country-code-removed-when-parsing Seems that they do an isPossible() check.

  /**
   * Tries to extract a country calling code from a number. This method will return zero if no
   * country calling code is considered to be present. Country calling codes are extracted in the
   * following ways:
   * <ul>
   *  <li> by stripping the international dialing prefix of the region the person is dialing from,
   *       if this is present in the number, and looking at the next digits
   *  <li> by stripping the '+' sign if present and then looking at the next digits
   *  <li> by comparing the start of the number and the country calling code of the default region.
   *       If the number is not considered possible for the numbering plan of the default region
   *       initially, but starts with the country calling code of this region, validation will be
   *       reattempted after stripping this country calling code. If this number is considered a
   *       possible number, then the first digits will be considered the country calling code and
   *       removed as such.
   * </ul>
   */

Source: https://github.com/google/libphonenumber/blob/876268eb1ad6cdc1b7b5bef17fc5e43052702d57/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java#L2738-L2752

// Check to see if the number starts with the country calling code for the default region. If
// so, we remove the country calling code, and do some checks on the validity of the number
// before and after.
int defaultCountryCode = defaultRegionMetadata.getCountryCode();
String defaultCountryCodeString = String.valueOf(defaultCountryCode);
String normalizedNumber = fullNumber.toString();
if (normalizedNumber.startsWith(defaultCountryCodeString)) {
  StringBuilder potentialNationalNumber =
      new StringBuilder(normalizedNumber.substring(defaultCountryCodeString.length()));
  PhoneNumberDesc generalDesc = defaultRegionMetadata.getGeneralDesc();
  maybeStripNationalPrefixAndCarrierCode(
      potentialNationalNumber, defaultRegionMetadata, null /* Don't need the carrier code */);
  // If the number was not valid before but is valid now, or if it was too long before, we
  // consider the number with the country calling code stripped to be a better result and
  // keep that instead.
  if ((!matcherApi.matchNationalNumber(fullNumber, generalDesc, false)
          && matcherApi.matchNationalNumber(potentialNationalNumber, generalDesc, false))
      || testNumberLength(fullNumber, defaultRegionMetadata) == ValidationResult.TOO_LONG) {
    nationalNumber.append(potentialNationalNumber);
    if (keepRawInput) {
      phoneNumber.setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN);
    }
    phoneNumber.setCountryCode(defaultCountryCode);
    return defaultCountryCode;
  }
}

Source: https://github.com/google/libphonenumber/blob/876268eb1ad6cdc1b7b5bef17fc5e43052702d57/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java#L2806-L2831

So, first they check whether a non-international number starts with the default country’s calling code. If it does, they temporarily construct a shortened number for it. Then they choose that shortened number over the initial number if:

  • Either the “general” (simple) regexp for the country’s phone numbers (for France it’s "national_number_pattern": "[1-9]\\d{8}") doesn’t match the initial number but does match the shortened number.
  • Or the initial number is too long (by checking the possible_lengths for the country).

Seems reasonable. In fact, I guess I’ll make it part of the library. Maybe some time later today.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Formatting International Phone Numbers - Twilio Support
164 phone number formatting entails the following: A + (plus) sign (replacing the International Call Prefix like 011); International Country Calling code; Local ......
Read more >
4.3. Validate International Phone Numbers - O'Reilly
You want to validate international phone numbers. The numbers should start with a plus sign, followed by the country code and national number....
Read more >
Getting INVALID_COUNTRY_CODE exception when trying to ...
I saw following code as recommended. PhoneNumber phoneNumber = phoneUtil.parse(numberStr, ""));. However, this is throwing INVALID_COUNTRY_CODE ...
Read more >
Using libphonenumber for International Phone Numbers
Libphonenumber is Google's formatting, parsing, and validation tool for international phone numbers. Learn how to use it in your global apps ...
Read more >
How to write a cell phone number in an international way ...
+: Plus sign ; country code: International country code. It comes after the plus sign. For ex. It is +91 for India whereas...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found