3 * Copyright (C) 2010 The Libphonenumber Authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 * @fileoverview Utility for international phone numbers.
20 * Functionality includes formatting, parsing and validation.
21 * (based on the java implementation).
23 * NOTE: A lot of methods in this class require Region Code strings. These must
24 * be provided using ISO 3166-1 two-letter country-code format. These should be
25 * in upper-case (but for compatibility lower-case is also allowed). The list of
26 * the codes can be found here:
27 * http://www.iso.org/iso/english_country_names_and_code_elements
29 * @author Nikolaos Trogkanis
32 goog.provide('i18n.phonenumbers.Error');
33 goog.provide('i18n.phonenumbers.PhoneNumberFormat');
34 goog.provide('i18n.phonenumbers.PhoneNumberType');
35 goog.provide('i18n.phonenumbers.PhoneNumberUtil');
36 goog.provide('i18n.phonenumbers.PhoneNumberUtil.MatchType');
37 goog.provide('i18n.phonenumbers.PhoneNumberUtil.ValidationResult');
39 goog.require('goog.array');
40 goog.require('goog.proto2.PbLiteSerializer');
41 goog.require('goog.string');
42 goog.require('goog.string.StringBuffer');
43 goog.require('i18n.phonenumbers.NumberFormat');
44 goog.require('i18n.phonenumbers.PhoneMetadata');
45 goog.require('i18n.phonenumbers.PhoneMetadataCollection');
46 goog.require('i18n.phonenumbers.PhoneNumber');
47 goog.require('i18n.phonenumbers.PhoneNumber.CountryCodeSource');
48 goog.require('i18n.phonenumbers.PhoneNumberDesc');
49 goog.require('i18n.phonenumbers.metadata');
57 i18n.phonenumbers.PhoneNumberUtil = function() {
59 * A mapping from a region code to the PhoneMetadata for that region.
60 * @type {Object.<string, i18n.phonenumbers.PhoneMetadata>}
62 this.regionToMetadataMap = {};
64 goog.addSingletonGetter(i18n.phonenumbers.PhoneNumberUtil);
68 * Errors encountered when parsing phone numbers.
72 i18n.phonenumbers.Error = {
73 INVALID_COUNTRY_CODE: 'Invalid country calling code',
74 // This generally indicates the string passed in had less than 3 digits in it.
75 // More specifically, the number failed to match the regular expression
76 // VALID_PHONE_NUMBER.
77 NOT_A_NUMBER: 'The string supplied did not seem to be a phone number',
78 // This indicates the string started with an international dialing prefix, but
79 // after this was stripped from the number, had less digits than any valid
80 // phone number (including country calling code) could have.
81 TOO_SHORT_AFTER_IDD: 'Phone number too short after IDD',
82 // This indicates the string, after any country calling code has been
83 // stripped, had less digits than any valid phone number could have.
84 TOO_SHORT_NSN: 'The string supplied is too short to be a phone number',
85 // This indicates the string had more digits than any valid phone number could
87 TOO_LONG: 'The string supplied is too long to be a phone number'
96 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_ = 1;
100 * The minimum length of the national significant number.
106 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ = 2;
110 * The ITU says the maximum length should be 15, but we have found longer
111 * numbers in Germany.
117 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_ = 16;
121 * The maximum length of the country calling code.
127 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE_ = 3;
131 * We don't allow input strings for parsing to be longer than 250 chars. This
132 * prevents malicious input from consuming CPU.
138 i18n.phonenumbers.PhoneNumberUtil.MAX_INPUT_STRING_LENGTH_ = 250;
142 * Region-code for the unknown region.
148 i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ = 'ZZ';
152 * The prefix that needs to be inserted in front of a Colombian landline number
153 * when dialed from a mobile phone in Colombia.
159 i18n.phonenumbers.PhoneNumberUtil.COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX_ = '3';
163 * The PLUS_SIGN signifies the international prefix.
168 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN = '+';
176 i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ = '*';
180 * The RFC 3966 format for extensions.
186 i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ = ';ext=';
194 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_ = 'tel:';
202 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_ = ';phone-context=';
210 i18n.phonenumbers.PhoneNumberUtil.RFC3966_ISDN_SUBADDRESS_ = ';isub=';
214 * These mappings map a character (key) to a specific digit that should replace
215 * it for normalization purposes. Non-European digits that may be used in phone
216 * numbers are mapped to a European equivalent.
219 * @type {!Object.<string, string>}
221 i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS = {
232 '\uFF10': '0', // Fullwidth digit 0
233 '\uFF11': '1', // Fullwidth digit 1
234 '\uFF12': '2', // Fullwidth digit 2
235 '\uFF13': '3', // Fullwidth digit 3
236 '\uFF14': '4', // Fullwidth digit 4
237 '\uFF15': '5', // Fullwidth digit 5
238 '\uFF16': '6', // Fullwidth digit 6
239 '\uFF17': '7', // Fullwidth digit 7
240 '\uFF18': '8', // Fullwidth digit 8
241 '\uFF19': '9', // Fullwidth digit 9
242 '\u0660': '0', // Arabic-indic digit 0
243 '\u0661': '1', // Arabic-indic digit 1
244 '\u0662': '2', // Arabic-indic digit 2
245 '\u0663': '3', // Arabic-indic digit 3
246 '\u0664': '4', // Arabic-indic digit 4
247 '\u0665': '5', // Arabic-indic digit 5
248 '\u0666': '6', // Arabic-indic digit 6
249 '\u0667': '7', // Arabic-indic digit 7
250 '\u0668': '8', // Arabic-indic digit 8
251 '\u0669': '9', // Arabic-indic digit 9
252 '\u06F0': '0', // Eastern-Arabic digit 0
253 '\u06F1': '1', // Eastern-Arabic digit 1
254 '\u06F2': '2', // Eastern-Arabic digit 2
255 '\u06F3': '3', // Eastern-Arabic digit 3
256 '\u06F4': '4', // Eastern-Arabic digit 4
257 '\u06F5': '5', // Eastern-Arabic digit 5
258 '\u06F6': '6', // Eastern-Arabic digit 6
259 '\u06F7': '7', // Eastern-Arabic digit 7
260 '\u06F8': '8', // Eastern-Arabic digit 8
261 '\u06F9': '9' // Eastern-Arabic digit 9
266 * A map that contains characters that are essential when dialling. That means
267 * any of the characters in this map must not be removed from a number when
268 * dialling, otherwise the call will not reach the intended destination.
271 * @type {!Object.<string, string>}
274 i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_ = {
285 '+': i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN,
291 * Only upper-case variants of alpha characters are stored.
294 * @type {!Object.<string, string>}
297 i18n.phonenumbers.PhoneNumberUtil.ALPHA_MAPPINGS_ = {
328 * For performance reasons, amalgamate both into one map.
331 * @type {!Object.<string, string>}
334 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_ = {
345 '\uFF10': '0', // Fullwidth digit 0
346 '\uFF11': '1', // Fullwidth digit 1
347 '\uFF12': '2', // Fullwidth digit 2
348 '\uFF13': '3', // Fullwidth digit 3
349 '\uFF14': '4', // Fullwidth digit 4
350 '\uFF15': '5', // Fullwidth digit 5
351 '\uFF16': '6', // Fullwidth digit 6
352 '\uFF17': '7', // Fullwidth digit 7
353 '\uFF18': '8', // Fullwidth digit 8
354 '\uFF19': '9', // Fullwidth digit 9
355 '\u0660': '0', // Arabic-indic digit 0
356 '\u0661': '1', // Arabic-indic digit 1
357 '\u0662': '2', // Arabic-indic digit 2
358 '\u0663': '3', // Arabic-indic digit 3
359 '\u0664': '4', // Arabic-indic digit 4
360 '\u0665': '5', // Arabic-indic digit 5
361 '\u0666': '6', // Arabic-indic digit 6
362 '\u0667': '7', // Arabic-indic digit 7
363 '\u0668': '8', // Arabic-indic digit 8
364 '\u0669': '9', // Arabic-indic digit 9
365 '\u06F0': '0', // Eastern-Arabic digit 0
366 '\u06F1': '1', // Eastern-Arabic digit 1
367 '\u06F2': '2', // Eastern-Arabic digit 2
368 '\u06F3': '3', // Eastern-Arabic digit 3
369 '\u06F4': '4', // Eastern-Arabic digit 4
370 '\u06F5': '5', // Eastern-Arabic digit 5
371 '\u06F6': '6', // Eastern-Arabic digit 6
372 '\u06F7': '7', // Eastern-Arabic digit 7
373 '\u06F8': '8', // Eastern-Arabic digit 8
374 '\u06F9': '9', // Eastern-Arabic digit 9
405 * Separate map of all symbols that we wish to retain when formatting alpha
406 * numbers. This includes digits, ASCII letters and number grouping symbols such
410 * @type {!Object.<string, string>}
413 i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_ = {
496 * Pattern that makes it easy to distinguish whether a region has a unique
497 * international dialing prefix or not. If a region has a unique international
498 * prefix (e.g. 011 in USA), it will be represented as a string that contains a
499 * sequence of ASCII digits. If there are multiple available international
500 * prefixes in a region, they will be represented as a regex string that always
501 * contains character(s) other than ASCII digits. Note this regex also includes
502 * tilde, which signals waiting for the tone.
508 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_ =
509 /[\d]+(?:[~\u2053\u223C\uFF5E][\d]+)?/;
513 * Regular expression of acceptable punctuation found in phone numbers. This
514 * excludes punctuation found as a leading character only. This consists of dash
515 * characters, white space characters, full stops, slashes, square brackets,
516 * parentheses and tildes. It also includes the letter 'x' as that is found as a
517 * placeholder for carrier information in some phone numbers. Full-width
518 * variants are also present.
523 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION =
524 '-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F \u00A0\u00AD\u200B\u2060\u3000' +
525 '()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E';
529 * Digits accepted in phone numbers (ascii, fullwidth, arabic-indic, and eastern
536 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ =
537 '0-9\uFF10-\uFF19\u0660-\u0669\u06F0-\u06F9';
541 * We accept alpha characters in phone numbers, ASCII only, upper and lower
548 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ = 'A-Za-z';
556 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ = '+\uFF0B';
563 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN =
564 new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']+');
572 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_ =
573 new RegExp('^[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']+');
581 i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_ =
582 '[' + i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION + ']+';
589 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN =
590 new RegExp('([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + '])');
594 * Regular expression of acceptable characters that may start a phone number for
595 * the purposes of parsing. This allows us to strip away meaningless prefixes to
596 * phone numbers that may be mistakenly given to us. This consists of digits,
597 * the plus symbol and arabic-indic digits. This does not contain alpha
598 * characters, although they may be used later in the number. It also does not
599 * include other punctuation, as this will be stripped later during parsing and
600 * is of no information value when parsing a number.
606 i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN_ =
607 new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ +
608 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']');
612 * Regular expression of characters typically used to start a second phone
613 * number for the purposes of parsing. This allows us to strip off parts of the
614 * number that are actually the start of another number, such as for:
615 * (530) 583-6985 x302/x2303 -> the second extension here makes this actually
616 * two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove
617 * the second extension so that the first number is parsed correctly.
623 i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_ = /[\\\/] *x/;
627 * Regular expression of trailing characters that we want to remove. We remove
628 * all characters that are not alpha or numerical characters. The hash character
629 * is retained here, as it may signify the previous block was an extension.
635 i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_ =
636 new RegExp('[^' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ +
637 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ + '#]+$');
641 * We use this pattern to check if the phone number has at least three letters
642 * in it - if so, then we treat it as a number where some phone-number digits
643 * are represented by letters.
649 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_ =
650 /(?:.*?[A-Za-z]){3}.*/;
654 * Regular expression of viable phone numbers. This is location independent.
655 * Checks we have at least three leading digits, and only valid punctuation,
656 * alpha characters and digits in the phone number. Does not include extension
657 * data. The symbol 'x' is allowed here as valid punctuation since it is often
658 * used as a placeholder for carrier codes, for example in Brazilian phone
659 * numbers. We also allow multiple '+' characters at the start.
660 * Corresponds to the following:
661 * [digits]{minLengthNsn}|
663 * (([punctuation]|[star])*[digits]){3,}([punctuation]|[star]|[digits]|[alpha])*
665 * The first reg-ex is to allow short numbers (two digits long) to be parsed if
666 * they are entered as "15" etc, but only if there is no punctuation in them.
667 * The second expression restricts the number of digits to three or more, but
668 * then allows them to be in international form, and to have alpha-characters
669 * and punctuation. We split up the two reg-exes here and combine them when
670 * creating the reg-ex VALID_PHONE_NUMBER_PATTERN_ itself so we can prefix it
671 * with ^ and append $ to each branch.
673 * Note VALID_PUNCTUATION starts with a -, so must be the first in the range.
679 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_PHONE_NUMBER_PATTERN_ =
680 '[' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{' +
681 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ + '}';
685 * See MIN_LENGTH_PHONE_NUMBER_PATTERN_ for a full description of this reg-exp.
691 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ =
692 '[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']*(?:[' +
693 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
694 i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ + ']*[' +
695 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']){3,}[' +
696 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
697 i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ +
698 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ +
699 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']*';
703 * Default extension prefix to use when formatting. This will be put in front of
704 * any extension component of the number, after the main national number is
705 * formatted. For example, if you wish the default extension formatting to be
706 * ' extn: 3456', then you should specify ' extn: ' here as the default
707 * extension prefix. This can be overridden by region-specific preferences.
713 i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ = ' ext. ';
717 * Pattern to capture digits used in an extension.
718 * Places a maximum length of '7' for an extension.
724 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ =
725 '([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,7})';
729 * Regexp of all possible ways to write extensions, for use when parsing. This
730 * will be run as a case-insensitive regexp match. Wide character versions are
731 * also provided after each ASCII version. There are three regular expressions
732 * here. The first covers RFC 3966 format, where the extension is added using
733 * ';ext='. The second more generic one starts with optional white space and
734 * ends with an optional full stop (.), followed by zero or more spaces/tabs and
735 * then the numbers themselves. The other one covers the special case of
736 * American numbers where the extension is written with a hash at the end, such
737 * as '- 503#'. Note that the only capturing groups should be around the digits
738 * that you want to capture as part of the extension, or else parsing will fail!
739 * We allow two options for representing the accented o - the character itself,
740 * and one in the unicode decomposed form with the combining acute accent.
746 i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ =
747 i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
748 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '|' +
750 '(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|' +
751 '[,x\uFF58#\uFF03~\uFF5E]|int|anexo|\uFF49\uFF4E\uFF54)' +
752 '[:\\.\uFF0E]?[ \u00A0\\t,-]*' +
753 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '#?|' +
754 '[- ]+([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,5})#';
758 * Regexp of all known extension prefixes used by different regions followed by
759 * 1 or more valid digits, for use when parsing.
765 i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_ =
767 i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ +
772 * We append optionally the extension pattern to the end here, as a valid phone
773 * number may have an extension prefix appended, followed by 1 or more digits.
779 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_ =
782 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_PHONE_NUMBER_PATTERN_ +
784 '^' + i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ +
785 '(?:' + i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ +
794 i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_ = /\D+/;
798 * This was originally set to $1 but there are some countries for which the
799 * first group is not used in the national pattern (e.g. Argentina) so the $1
800 * group does not match correctly. Therefore, we use \d, so that the first
801 * group actually used in the pattern will be matched.
806 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_ = /(\$\d)/;
814 i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_ = /\$NP/;
822 i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_ = /\$FG/;
830 i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_ = /\$CC/;
834 * A pattern that is used to determine if the national prefix formatting rule
835 * has the first group only, i.e., does not start with the national prefix.
836 * Note that the pattern explicitly allows for unbalanced parentheses.
841 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_ONLY_PREFIX_PATTERN_ =
849 i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY = '001';
853 * INTERNATIONAL and NATIONAL formats are consistent with the definition in
854 * ITU-T Recommendation E123. For example, the number of the Google Switzerland
855 * office will be written as '+41 44 668 1800' in INTERNATIONAL format, and as
856 * '044 668 1800' in NATIONAL format. E164 format is as per INTERNATIONAL format
857 * but with no formatting applied, e.g. '+41446681800'. RFC3966 is as per
858 * INTERNATIONAL format, but with all spaces and other separating symbols
859 * replaced with a hyphen, and with any phone number extension appended with
860 * ';ext='. It also will have a prefix of 'tel:' added, e.g.
861 * 'tel:+41-44-668-1800'.
863 * Note: If you are considering storing the number in a neutral format, you are
864 * highly advised to use the PhoneNumber class.
867 i18n.phonenumbers.PhoneNumberFormat = {
876 * Type of phone numbers.
880 i18n.phonenumbers.PhoneNumberType = {
883 // In some regions (e.g. the USA), it is impossible to distinguish between
884 // fixed-line and mobile numbers by looking at the phone number itself.
885 FIXED_LINE_OR_MOBILE: 2,
889 // The cost of this call is shared between the caller and the recipient, and
890 // is hence typically less than PREMIUM_RATE calls. See
891 // http://en.wikipedia.org/wiki/Shared_Cost_Service for more information.
893 // Voice over IP numbers. This includes TSoIP (Telephony Service over IP).
895 // A personal number is associated with a particular person, and may be routed
896 // to either a MOBILE or FIXED_LINE number. Some more information can be found
897 // here: http://en.wikipedia.org/wiki/Personal_Numbers
900 // Used for 'Universal Access Numbers' or 'Company Numbers'. They may be
901 // further routed to specific offices, but allow one number to be used for a
904 // Used for 'Voice Mail Access Numbers'.
906 // A phone number is of type UNKNOWN when it does not fit any of the known
907 // patterns for a specific region.
913 * Types of phone number matches. See detailed description beside the
914 * isNumberMatch() method.
918 i18n.phonenumbers.PhoneNumberUtil.MatchType = {
928 * Possible outcomes when testing if a PhoneNumber is possible.
932 i18n.phonenumbers.PhoneNumberUtil.ValidationResult = {
934 INVALID_COUNTRY_CODE: 1,
941 * Attempts to extract a possible number from the string passed in. This
942 * currently strips all leading characters that cannot be used to start a phone
943 * number. Characters that can be used to start a phone number are defined in
944 * the VALID_START_CHAR_PATTERN. If none of these characters are found in the
945 * number passed in, an empty string is returned. This function also attempts to
946 * strip off any alternative extensions or endings if two or more are present,
947 * such as in the case of: (530) 583-6985 x302/x2303. The second extension here
948 * makes this actually two phone numbers, (530) 583-6985 x302 and (530) 583-6985
949 * x2303. We remove the second extension so that the first number is parsed
952 * @param {string} number the string that might contain a phone number.
953 * @return {string} the number, stripped of any non-phone-number prefix (such as
954 * 'Tel:') or an empty string if no character used to start phone numbers
955 * (such as + or any digit) is found in the number.
957 i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber = function(number) {
958 /** @type {string} */
961 /** @type {number} */
963 .search(i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN_);
965 possibleNumber = number.substring(start);
966 // Remove trailing non-alpha non-numerical characters.
967 possibleNumber = possibleNumber.replace(
968 i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_, '');
970 // Check for extra numbers at the end.
971 /** @type {number} */
972 var secondNumberStart = possibleNumber
973 .search(i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_);
974 if (secondNumberStart >= 0) {
975 possibleNumber = possibleNumber.substring(0, secondNumberStart);
980 return possibleNumber;
985 * Checks to see if the string of characters could possibly be a phone number at
986 * all. At the moment, checks to see that the string begins with at least 2
987 * digits, ignoring any punctuation commonly found in phone numbers. This method
988 * does not require the number to be normalized in advance - but does assume
989 * that leading non-number symbols have been removed, such as by the method
990 * extractPossibleNumber.
992 * @param {string} number string to be checked for viability as a phone number.
993 * @return {boolean} true if the number could be a phone number of some sort,
996 i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber = function(number) {
997 if (number.length < i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
1000 return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1001 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_, number);
1006 * Normalizes a string of characters representing a phone number. This performs
1007 * the following conversions:
1008 * Punctuation is stripped.
1009 * For ALPHA/VANITY numbers:
1010 * Letters are converted to their numeric representation on a telephone
1011 * keypad. The keypad used here is the one defined in ITU Recommendation
1012 * E.161. This is only done if there are 3 or more letters in the number,
1013 * to lessen the risk that such letters are typos.
1014 * For other numbers:
1015 * Wide-ascii digits are converted to normal ASCII (European) digits.
1016 * Arabic-Indic numerals are converted to European numerals.
1017 * Spurious alpha characters are stripped.
1019 * @param {string} number a string of characters representing a phone number.
1020 * @return {string} the normalized string version of the phone number.
1022 i18n.phonenumbers.PhoneNumberUtil.normalize = function(number) {
1023 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1024 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_, number)) {
1025 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
1026 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, true);
1028 return i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(number);
1034 * Normalizes a string of characters representing a phone number. This is a
1035 * wrapper for normalize(String number) but does in-place normalization of the
1036 * StringBuffer provided.
1038 * @param {!goog.string.StringBuffer} number a StringBuffer of characters
1039 * representing a phone number that will be normalized in place.
1042 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_ = function(number) {
1043 /** @type {string} */
1044 var normalizedNumber = i18n.phonenumbers.PhoneNumberUtil.normalize(number
1047 number.append(normalizedNumber);
1052 * Normalizes a string of characters representing a phone number. This converts
1053 * wide-ascii and arabic-indic numerals to European numerals, and strips
1054 * punctuation and alpha characters.
1056 * @param {string} number a string of characters representing a phone number.
1057 * @return {string} the normalized string version of the phone number.
1059 i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly = function(number) {
1060 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
1061 i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS, true);
1066 * Converts all alpha characters in a number to their respective digits on a
1067 * keypad, but retains existing formatting. Also converts wide-ascii digits to
1068 * normal ascii digits, and converts Arabic-Indic numerals to European numerals.
1070 * @param {string} number a string of characters representing a phone number.
1071 * @return {string} the normalized string version of the phone number.
1073 i18n.phonenumbers.PhoneNumberUtil.convertAlphaCharactersInNumber =
1076 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
1077 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, false);
1082 * Gets the length of the geographical area code from the
1083 * {@code national_number} field of the PhoneNumber object passed in, so that
1084 * clients could use it to split a national significant number into geographical
1085 * area code and subscriber number. It works in such a way that the resultant
1086 * subscriber number should be diallable, at least on some devices. An example
1087 * of how this could be used:
1090 * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
1091 * var number = phoneUtil.parse('16502530000', 'US');
1092 * var nationalSignificantNumber =
1093 * phoneUtil.getNationalSignificantNumber(number);
1095 * var subscriberNumber;
1097 * var areaCodeLength = phoneUtil.getLengthOfGeographicalAreaCode(number);
1098 * if (areaCodeLength > 0) {
1099 * areaCode = nationalSignificantNumber.substring(0, areaCodeLength);
1100 * subscriberNumber = nationalSignificantNumber.substring(areaCodeLength);
1103 * subscriberNumber = nationalSignificantNumber;
1107 * N.B.: area code is a very ambiguous concept, so the I18N team generally
1108 * recommends against using it for most purposes, but recommends using the more
1109 * general {@code national_number} instead. Read the following carefully before
1110 * deciding to use this method:
1112 * <li> geographical area codes change over time, and this method honors those
1113 * changes; therefore, it doesn't guarantee the stability of the result it
1115 * <li> subscriber numbers may not be diallable from all devices (notably
1116 * mobile devices, which typically requires the full national_number to be
1117 * dialled in most regions).
1118 * <li> most non-geographical numbers have no area codes, including numbers
1119 * from non-geographical entities.
1120 * <li> some geographical numbers have no area codes.
1123 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
1124 * which clients want to know the length of the area code.
1125 * @return {number} the length of area code of the PhoneNumber object passed in.
1127 i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfGeographicalAreaCode =
1129 /** @type {i18n.phonenumbers.PhoneMetadata} */
1130 var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
1131 if (metadata == null) {
1134 // If a country doesn't use a national prefix, and this number doesn't have
1135 // an Italian leading zero, we assume it is a closed dialling plan with no
1137 if (!metadata.hasNationalPrefix() && !number.hasItalianLeadingZero()) {
1141 if (!this.isNumberGeographical_(number)) {
1145 return this.getLengthOfNationalDestinationCode(number);
1150 * Gets the length of the national destination code (NDC) from the PhoneNumber
1151 * object passed in, so that clients could use it to split a national
1152 * significant number into NDC and subscriber number. The NDC of a phone number
1153 * is normally the first group of digit(s) right after the country calling code
1154 * when the number is formatted in the international format, if there is a
1155 * subscriber number part that follows. An example of how this could be used:
1158 * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
1159 * var number = phoneUtil.parse('18002530000', 'US');
1160 * var nationalSignificantNumber =
1161 * phoneUtil.getNationalSignificantNumber(number);
1162 * var nationalDestinationCode;
1163 * var subscriberNumber;
1165 * var nationalDestinationCodeLength =
1166 * phoneUtil.getLengthOfNationalDestinationCode(number);
1167 * if (nationalDestinationCodeLength > 0) {
1168 * nationalDestinationCode =
1169 * nationalSignificantNumber.substring(0, nationalDestinationCodeLength);
1170 * subscriberNumber =
1171 * nationalSignificantNumber.substring(nationalDestinationCodeLength);
1173 * nationalDestinationCode = '';
1174 * subscriberNumber = nationalSignificantNumber;
1178 * Refer to the unittests to see the difference between this function and
1179 * {@link #getLengthOfGeographicalAreaCode}.
1181 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
1182 * which clients want to know the length of the NDC.
1183 * @return {number} the length of NDC of the PhoneNumber object passed in.
1185 i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfNationalDestinationCode =
1188 /** @type {i18n.phonenumbers.PhoneNumber} */
1190 if (number.hasExtension()) {
1191 // We don't want to alter the proto given to us, but we don't want to
1192 // include the extension when we format it, so we copy it and clear the
1194 copiedProto = number.clone();
1195 copiedProto.clearExtension();
1197 copiedProto = number;
1200 /** @type {string} */
1201 var nationalSignificantNumber = this.format(copiedProto,
1202 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1203 /** @type {!Array.<string>} */
1204 var numberGroups = nationalSignificantNumber.split(
1205 i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_);
1206 // The pattern will start with '+COUNTRY_CODE ' so the first group will always
1207 // be the empty string (before the + symbol) and the second group will be the
1208 // country calling code. The third group will be area code if it is not the
1210 // NOTE: On IE the first group that is supposed to be the empty string does
1211 // not appear in the array of number groups... so make the result on non-IE
1212 // browsers to be that of IE.
1213 if (numberGroups[0].length == 0) {
1214 numberGroups.shift();
1216 if (numberGroups.length <= 2) {
1220 if (this.getRegionCodeForCountryCode(number.getCountryCodeOrDefault()) ==
1222 this.getNumberType(number) == i18n.phonenumbers.PhoneNumberType.MOBILE) {
1223 // Argentinian mobile numbers, when formatted in the international format,
1224 // are in the form of +54 9 NDC XXXX.... As a result, we take the length of
1225 // the third group (NDC) and add 1 for the digit 9, which also forms part of
1226 // the national significant number.
1228 // TODO: Investigate the possibility of better modeling the metadata to make
1229 // it easier to obtain the NDC.
1230 return numberGroups[2].length + 1;
1232 return numberGroups[1].length;
1237 * Normalizes a string of characters representing a phone number by replacing
1238 * all characters found in the accompanying map with the values therein, and
1239 * stripping all other characters if removeNonMatches is true.
1241 * @param {string} number a string of characters representing a phone number.
1242 * @param {!Object.<string, string>} normalizationReplacements a mapping of
1243 * characters to what they should be replaced by in the normalized version
1244 * of the phone number.
1245 * @param {boolean} removeNonMatches indicates whether characters that are not
1246 * able to be replaced should be stripped from the number. If this is false,
1247 * they will be left unchanged in the number.
1248 * @return {string} the normalized string version of the phone number.
1251 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_ =
1252 function(number, normalizationReplacements, removeNonMatches) {
1254 /** @type {!goog.string.StringBuffer} */
1255 var normalizedNumber = new goog.string.StringBuffer();
1256 /** @type {string} */
1258 /** @type {string} */
1260 /** @type {number} */
1261 var numberLength = number.length;
1262 for (var i = 0; i < numberLength; ++i) {
1263 character = number.charAt(i);
1264 newDigit = normalizationReplacements[character.toUpperCase()];
1265 if (newDigit != null) {
1266 normalizedNumber.append(newDigit);
1267 } else if (!removeNonMatches) {
1268 normalizedNumber.append(character);
1270 // If neither of the above are true, we remove this character.
1272 return normalizedNumber.toString();
1277 * Helper function to check if the national prefix formatting rule has the first
1278 * group only, i.e., does not start with the national prefix.
1280 * @param {string} nationalPrefixFormattingRule The formatting rule for the
1282 * @return {boolean} true if the national prefix formatting rule has the first
1285 i18n.phonenumbers.PhoneNumberUtil.prototype.formattingRuleHasFirstGroupOnly =
1286 function(nationalPrefixFormattingRule) {
1287 return i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_ONLY_PREFIX_PATTERN_.
1288 test(nationalPrefixFormattingRule);
1293 * Tests whether a phone number has a geographical association. It checks if
1294 * the number is associated to a certain region in the country where it belongs
1295 * to. Note that this doesn't verify if the number is actually in use.
1297 * @param {i18n.phonenumbers.PhoneNumber} phoneNumber The phone number to test.
1298 * @return {boolean} true if the phone number has a geographical association.
1301 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberGeographical_ =
1302 function(phoneNumber) {
1303 /** @type {i18n.phonenumbers.PhoneNumberType} */
1304 var numberType = this.getNumberType(phoneNumber);
1305 // TODO: Include mobile phone numbers from countries like Indonesia, which
1306 // has some mobile numbers that are geographical.
1307 return numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE ||
1308 numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
1313 * Helper function to check region code is not unknown or null.
1315 * @param {?string} regionCode the ISO 3166-1 two-letter region code.
1316 * @return {boolean} true if region code is valid.
1319 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidRegionCode_ =
1320 function(regionCode) {
1322 // In Java we check whether the regionCode is contained in supportedRegions
1323 // that is built out of all the values of countryCallingCodeToRegionCodeMap
1324 // (countryCodeToRegionCodeMap in JS) minus REGION_CODE_FOR_NON_GEO_ENTITY.
1325 // In JS we check whether the regionCode is contained in the keys of
1326 // countryToMetadata but since for non-geographical country calling codes
1327 // (e.g. +800) we use the country calling codes instead of the region code as
1328 // key in the map we have to make sure regionCode is not a number to prevent
1329 // returning true for non-geographical country calling codes.
1330 return regionCode != null &&
1331 isNaN(regionCode) &&
1332 regionCode.toUpperCase() in i18n.phonenumbers.metadata.countryToMetadata;
1337 * Helper function to check the country calling code is valid.
1339 * @param {number} countryCallingCode the country calling code.
1340 * @return {boolean} true if country calling code code is valid.
1343 i18n.phonenumbers.PhoneNumberUtil.prototype.hasValidCountryCallingCode_ =
1344 function(countryCallingCode) {
1346 return countryCallingCode in
1347 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap;
1352 * Formats a phone number in the specified format using default rules. Note that
1353 * this does not promise to produce a phone number that the user can dial from
1354 * where they are - although we do format in either 'national' or
1355 * 'international' format depending on what the client asks for, we do not
1356 * currently support a more abbreviated format, such as for users in the same
1357 * 'area' who could potentially dial the number without area code. Note that if
1358 * the phone number has a country calling code of 0 or an otherwise invalid
1359 * country calling code, we cannot work out which formatting rules to apply so
1360 * we return the national significant number with no formatting applied.
1362 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1364 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1365 * phone number should be formatted into.
1366 * @return {string} the formatted phone number.
1368 i18n.phonenumbers.PhoneNumberUtil.prototype.format =
1369 function(number, numberFormat) {
1371 if (number.getNationalNumber() == 0 && number.hasRawInput()) {
1372 // Unparseable numbers that kept their raw input just use that.
1373 // This is the only case where a number can be formatted as E164 without a
1374 // leading '+' symbol (but the original number wasn't parseable anyway).
1375 // TODO: Consider removing the 'if' above so that unparseable strings
1376 // without raw input format to the empty string instead of "+00"
1377 /** @type {string} */
1378 var rawInput = number.getRawInputOrDefault();
1379 if (rawInput.length > 0) {
1383 /** @type {number} */
1384 var countryCallingCode = number.getCountryCodeOrDefault();
1385 /** @type {string} */
1386 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1387 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.E164) {
1388 // Early exit for E164 case (even if the country calling code is invalid)
1389 // since no formatting of the national number needs to be applied.
1390 // Extensions are not formatted.
1391 return this.prefixNumberWithCountryCallingCode_(
1392 countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.E164,
1393 nationalSignificantNumber, '');
1395 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1396 return nationalSignificantNumber;
1398 // Note getRegionCodeForCountryCode() is used because formatting information
1399 // for regions which share a country calling code is contained by only one
1400 // region for performance reasons. For example, for NANPA regions it will be
1401 // contained in the metadata for US.
1402 /** @type {string} */
1403 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1405 // Metadata cannot be null because the country calling code is valid (which
1406 // means that the region code cannot be ZZ and must be one of our supported
1408 /** @type {i18n.phonenumbers.PhoneMetadata} */
1410 this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1411 /** @type {string} */
1412 var formattedExtension =
1413 this.maybeGetFormattedExtension_(number, metadata, numberFormat);
1414 /** @type {string} */
1415 var formattedNationalNumber =
1416 this.formatNsn_(nationalSignificantNumber, metadata, numberFormat);
1417 return this.prefixNumberWithCountryCallingCode_(countryCallingCode,
1419 formattedNationalNumber,
1420 formattedExtension);
1425 * Formats a phone number in the specified format using client-defined
1426 * formatting rules. Note that if the phone number has a country calling code of
1427 * zero or an otherwise invalid country calling code, we cannot work out things
1428 * like whether there should be a national prefix applied, or how to format
1429 * extensions, so we return the national significant number with no formatting
1432 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1434 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1435 * phone number should be formatted into.
1436 * @param {Array.<i18n.phonenumbers.NumberFormat>} userDefinedFormats formatting
1437 * rules specified by clients.
1438 * @return {string} the formatted phone number.
1440 i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern =
1441 function(number, numberFormat, userDefinedFormats) {
1443 /** @type {number} */
1444 var countryCallingCode = number.getCountryCodeOrDefault();
1445 /** @type {string} */
1446 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1447 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1448 return nationalSignificantNumber;
1450 // Note getRegionCodeForCountryCode() is used because formatting information
1451 // for regions which share a country calling code is contained by only one
1452 // region for performance reasons. For example, for NANPA regions it will be
1453 // contained in the metadata for US.
1454 /** @type {string} */
1455 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1456 // Metadata cannot be null because the country calling code is valid
1457 /** @type {i18n.phonenumbers.PhoneMetadata} */
1459 this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1461 /** @type {string} */
1462 var formattedNumber = '';
1464 /** @type {i18n.phonenumbers.NumberFormat} */
1465 var formattingPattern = this.chooseFormattingPatternForNumber_(
1466 userDefinedFormats, nationalSignificantNumber);
1467 if (formattingPattern == null) {
1468 // If no pattern above is matched, we format the number as a whole.
1469 formattedNumber = nationalSignificantNumber;
1471 // Before we do a replacement of the national prefix pattern $NP with the
1472 // national prefix, we need to copy the rule so that subsequent replacements
1473 // for different numbers have the appropriate national prefix.
1474 /** type {i18n.phonenumbers.NumberFormat} */
1475 var numFormatCopy = formattingPattern.clone();
1476 /** @type {string} */
1477 var nationalPrefixFormattingRule =
1478 formattingPattern.getNationalPrefixFormattingRuleOrDefault();
1479 /** @type {string} */
1480 if (nationalPrefixFormattingRule.length > 0) {
1481 var nationalPrefix = metadata.getNationalPrefixOrDefault();
1482 if (nationalPrefix.length > 0) {
1483 // Replace $NP with national prefix and $FG with the first group ($1).
1484 nationalPrefixFormattingRule = nationalPrefixFormattingRule
1485 .replace(i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_,
1487 .replace(i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_, '$1');
1488 numFormatCopy.setNationalPrefixFormattingRule(
1489 nationalPrefixFormattingRule);
1491 // We don't want to have a rule for how to format the national prefix if
1493 numFormatCopy.clearNationalPrefixFormattingRule();
1496 formattedNumber = this.formatNsnUsingPattern_(
1497 nationalSignificantNumber, numFormatCopy, numberFormat);
1500 /** @type {string} */
1501 var formattedExtension =
1502 this.maybeGetFormattedExtension_(number, metadata, numberFormat);
1503 return this.prefixNumberWithCountryCallingCode_(countryCallingCode,
1506 formattedExtension);
1511 * Formats a phone number in national format for dialing using the carrier as
1512 * specified in the {@code carrierCode}. The {@code carrierCode} will always be
1513 * used regardless of whether the phone number already has a preferred domestic
1514 * carrier code stored. If {@code carrierCode} contains an empty string, returns
1515 * the number in national format without any carrier code.
1517 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1519 * @param {string} carrierCode the carrier selection code to be used.
1520 * @return {string} the formatted phone number in national format for dialing
1521 * using the carrier as specified in the {@code carrierCode}.
1523 i18n.phonenumbers.PhoneNumberUtil.prototype.
1524 formatNationalNumberWithCarrierCode = function(number, carrierCode) {
1526 /** @type {number} */
1527 var countryCallingCode = number.getCountryCodeOrDefault();
1528 /** @type {string} */
1529 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1530 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1531 return nationalSignificantNumber;
1534 // Note getRegionCodeForCountryCode() is used because formatting information
1535 // for regions which share a country calling code is contained by only one
1536 // region for performance reasons. For example, for NANPA regions it will be
1537 // contained in the metadata for US.
1538 /** @type {string} */
1539 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1540 // Metadata cannot be null because the country calling code is valid.
1541 /** @type {i18n.phonenumbers.PhoneMetadata} */
1543 this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1544 /** @type {string} */
1545 var formattedExtension = this.maybeGetFormattedExtension_(
1546 number, metadata, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1547 /** @type {string} */
1548 var formattedNationalNumber = this.formatNsn_(
1549 nationalSignificantNumber, metadata,
1550 i18n.phonenumbers.PhoneNumberFormat.NATIONAL, carrierCode);
1551 return this.prefixNumberWithCountryCallingCode_(
1552 countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL,
1553 formattedNationalNumber, formattedExtension);
1558 * @param {number} countryCallingCode
1559 * @param {?string} regionCode
1560 * @return {i18n.phonenumbers.PhoneMetadata}
1563 i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegionOrCallingCode_ =
1564 function(countryCallingCode, regionCode) {
1565 return i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY ==
1567 this.getMetadataForNonGeographicalRegion(countryCallingCode) :
1568 this.getMetadataForRegion(regionCode);
1573 * Formats a phone number in national format for dialing using the carrier as
1574 * specified in the preferred_domestic_carrier_code field of the PhoneNumber
1575 * object passed in. If that is missing, use the {@code fallbackCarrierCode}
1576 * passed in instead. If there is no {@code preferred_domestic_carrier_code},
1577 * and the {@code fallbackCarrierCode} contains an empty string, return the
1578 * number in national format without any carrier code.
1580 * <p>Use {@link #formatNationalNumberWithCarrierCode} instead if the carrier
1581 * code passed in should take precedence over the number's
1582 * {@code preferred_domestic_carrier_code} when formatting.
1584 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1586 * @param {string} fallbackCarrierCode the carrier selection code to be used, if
1587 * none is found in the phone number itself.
1588 * @return {string} the formatted phone number in national format for dialing
1589 * using the number's preferred_domestic_carrier_code, or the
1590 * {@code fallbackCarrierCode} passed in if none is found.
1592 i18n.phonenumbers.PhoneNumberUtil.prototype.
1593 formatNationalNumberWithPreferredCarrierCode = function(
1594 number, fallbackCarrierCode) {
1595 return this.formatNationalNumberWithCarrierCode(
1597 number.hasPreferredDomesticCarrierCode() ?
1598 number.getPreferredDomesticCarrierCodeOrDefault() :
1599 fallbackCarrierCode);
1604 * Returns a number formatted in such a way that it can be dialed from a mobile
1605 * phone in a specific region. If the number cannot be reached from the region
1606 * (e.g. some countries block toll-free numbers from being called outside of the
1607 * country), the method returns an empty string.
1609 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1611 * @param {string} regionCallingFrom the region where the call is being placed.
1612 * @param {boolean} withFormatting whether the number should be returned with
1613 * formatting symbols, such as spaces and dashes.
1614 * @return {string} the formatted phone number.
1616 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberForMobileDialing =
1617 function(number, regionCallingFrom, withFormatting) {
1619 /** @type {number} */
1620 var countryCallingCode = number.getCountryCodeOrDefault();
1621 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1622 return number.hasRawInput() ? number.getRawInputOrDefault() : '';
1625 /** @type {string} */
1626 var formattedNumber = '';
1627 // Clear the extension, as that part cannot normally be dialed together with
1629 /** @type {i18n.phonenumbers.PhoneNumber} */
1630 var numberNoExt = number.clone();
1631 numberNoExt.clearExtension();
1632 /** @type {string} */
1633 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1634 if (regionCallingFrom == regionCode) {
1635 /** @type {i18n.phonenumbers.PhoneNumberType} */
1636 var numberType = this.getNumberType(numberNoExt);
1637 var isFixedLineOrMobile =
1638 (numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) ||
1639 (numberType == i18n.phonenumbers.PhoneNumberType.MOBILE) ||
1640 (numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE);
1641 // Carrier codes may be needed in some countries. We handle this here.
1642 if (regionCode == 'CO' &&
1643 numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) {
1644 formattedNumber = this.formatNationalNumberWithCarrierCode(
1646 i18n.phonenumbers.PhoneNumberUtil
1647 .COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX_);
1648 } else if (regionCode == 'BR' && isFixedLineOrMobile) {
1649 formattedNumber = numberNoExt.hasPreferredDomesticCarrierCode() ?
1650 this.formatNationalNumberWithPreferredCarrierCode(numberNoExt, '') :
1651 // Brazilian fixed line and mobile numbers need to be dialed with a
1652 // carrier code when called within Brazil. Without that, most of the
1653 // carriers won't connect the call. Because of that, we return an empty
1657 // For NANPA countries, non-geographical countries, and Mexican fixed
1658 // line and mobile numbers, we output international format for numbersi
1659 // that can be dialed internationally as that always works.
1660 if ((countryCallingCode ==
1661 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_ ||
1663 i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY ||
1664 // MX fixed line and mobile numbers should always be formatted in
1665 // international format, even when dialed within MX. For national
1666 // format to work, a carrier code needs to be used, and the correct
1667 // carrier code depends on if the caller and callee are from the
1668 // same local area. It is trickier to get that to work correctly than
1669 // using international format, which is tested to work fine on all
1671 (regionCode == 'MX' && isFixedLineOrMobile)) &&
1672 this.canBeInternationallyDialled(numberNoExt)) {
1673 formattedNumber = this.format(
1674 numberNoExt, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1676 formattedNumber = this.format(
1677 numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1680 } else if (this.canBeInternationallyDialled(numberNoExt)) {
1681 return withFormatting ?
1682 this.format(numberNoExt,
1683 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL) :
1684 this.format(numberNoExt, i18n.phonenumbers.PhoneNumberFormat.E164);
1686 return withFormatting ?
1688 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
1689 i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_, true);
1694 * Formats a phone number for out-of-country dialing purposes. If no
1695 * regionCallingFrom is supplied, we format the number in its INTERNATIONAL
1696 * format. If the country calling code is the same as that of the region where
1697 * the number is from, then NATIONAL formatting will be applied.
1699 * <p>If the number itself has a country calling code of zero or an otherwise
1700 * invalid country calling code, then we return the number with no formatting
1703 * <p>Note this function takes care of the case for calling inside of NANPA and
1704 * between Russia and Kazakhstan (who share the same country calling code). In
1705 * those cases, no international prefix is used. For regions which have multiple
1706 * international prefixes, the number in its INTERNATIONAL format will be
1709 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1711 * @param {string} regionCallingFrom the region where the call is being placed.
1712 * @return {string} the formatted phone number.
1714 i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
1715 function(number, regionCallingFrom) {
1717 if (!this.isValidRegionCode_(regionCallingFrom)) {
1718 return this.format(number,
1719 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1721 /** @type {number} */
1722 var countryCallingCode = number.getCountryCodeOrDefault();
1723 /** @type {string} */
1724 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1725 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1726 return nationalSignificantNumber;
1728 if (countryCallingCode ==
1729 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
1730 if (this.isNANPACountry(regionCallingFrom)) {
1731 // For NANPA regions, return the national format for these regions but
1732 // prefix it with the country calling code.
1733 return countryCallingCode + ' ' +
1734 this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1736 } else if (countryCallingCode ==
1737 this.getCountryCodeForValidRegion_(regionCallingFrom)) {
1738 // If regions share a country calling code, the country calling code need
1739 // not be dialled. This also applies when dialling within a region, so this
1740 // if clause covers both these cases. Technically this is the case for
1741 // dialling from La Reunion to other overseas departments of France (French
1742 // Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover
1743 // this edge case for now and for those cases return the version including
1744 // country calling code. Details here:
1745 // http://www.petitfute.com/voyage/225-info-pratiques-reunion
1746 return this.format(number,
1747 i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1749 // Metadata cannot be null because we checked 'isValidRegionCode()' above.
1750 /** @type {i18n.phonenumbers.PhoneMetadata} */
1751 var metadataForRegionCallingFrom =
1752 this.getMetadataForRegion(regionCallingFrom);
1753 /** @type {string} */
1754 var internationalPrefix =
1755 metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
1757 // For regions that have multiple international prefixes, the international
1758 // format of the number is returned, unless there is a preferred international
1760 /** @type {string} */
1761 var internationalPrefixForFormatting = '';
1762 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1763 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
1764 internationalPrefix)) {
1765 internationalPrefixForFormatting = internationalPrefix;
1766 } else if (metadataForRegionCallingFrom.hasPreferredInternationalPrefix()) {
1767 internationalPrefixForFormatting =
1768 metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
1771 /** @type {string} */
1772 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1773 // Metadata cannot be null because the country calling code is valid.
1774 /** @type {i18n.phonenumbers.PhoneMetadata} */
1775 var metadataForRegion =
1776 this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1777 /** @type {string} */
1778 var formattedNationalNumber = this.formatNsn_(
1779 nationalSignificantNumber, metadataForRegion,
1780 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1781 /** @type {string} */
1782 var formattedExtension = this.maybeGetFormattedExtension_(number,
1783 metadataForRegion, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1784 return internationalPrefixForFormatting.length > 0 ?
1785 internationalPrefixForFormatting + ' ' + countryCallingCode + ' ' +
1786 formattedNationalNumber + formattedExtension :
1787 this.prefixNumberWithCountryCallingCode_(
1788 countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
1789 formattedNationalNumber, formattedExtension);
1794 * Formats a phone number using the original phone number format that the number
1795 * is parsed from. The original format is embedded in the country_code_source
1796 * field of the PhoneNumber object passed in. If such information is missing,
1797 * the number will be formatted into the NATIONAL format by default. When the
1798 * number contains a leading zero and this is unexpected for this country, or we
1799 * don't have a formatting pattern for the number, the method returns the raw
1800 * input when it is available.
1802 * Note this method guarantees no digit will be inserted, removed or modified as
1803 * a result of formatting.
1805 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
1806 * be formatted in its original number format.
1807 * @param {string} regionCallingFrom the region whose IDD needs to be prefixed
1808 * if the original number has one.
1809 * @return {string} the formatted phone number in its original number format.
1811 i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat =
1812 function(number, regionCallingFrom) {
1814 if (number.hasRawInput() &&
1815 (this.hasUnexpectedItalianLeadingZero_(number) ||
1816 !this.hasFormattingPatternForNumber_(number))) {
1817 // We check if we have the formatting pattern because without that, we might
1818 // format the number as a group without national prefix.
1819 return number.getRawInputOrDefault();
1821 if (!number.hasCountryCodeSource()) {
1822 return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1824 /** @type {string} */
1825 var formattedNumber;
1826 switch (number.getCountryCodeSource()) {
1827 case i18n.phonenumbers.PhoneNumber.CountryCodeSource
1828 .FROM_NUMBER_WITH_PLUS_SIGN:
1829 formattedNumber = this.format(number,
1830 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1832 case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD:
1834 this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
1836 case i18n.phonenumbers.PhoneNumber.CountryCodeSource
1837 .FROM_NUMBER_WITHOUT_PLUS_SIGN:
1838 formattedNumber = this.format(number,
1839 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL).substring(1);
1841 case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY:
1842 // Fall-through to default case.
1844 /** @type {string} */
1846 this.getRegionCodeForCountryCode(number.getCountryCodeOrDefault());
1847 // We strip non-digits from the NDD here, and from the raw input later,
1848 // so that we can compare them easily.
1849 /** @type {?string} */
1850 var nationalPrefix = this.getNddPrefixForRegion(regionCode, true);
1851 /** @type {string} */
1852 var nationalFormat =
1853 this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1854 if (nationalPrefix == null || nationalPrefix.length == 0) {
1855 // If the region doesn't have a national prefix at all, we can safely
1856 // return the national format without worrying about a national prefix
1858 formattedNumber = nationalFormat;
1861 // Otherwise, we check if the original number was entered with a national
1863 if (this.rawInputContainsNationalPrefix_(
1864 number.getRawInputOrDefault(), nationalPrefix, regionCode)) {
1865 // If so, we can safely return the national format.
1866 formattedNumber = nationalFormat;
1869 // Metadata cannot be null here because getNddPrefixForRegion() (above)
1870 // returns null if there is no metadata for the region.
1871 /** @type {i18n.phonenumbers.PhoneMetadata} */
1872 var metadata = this.getMetadataForRegion(regionCode);
1873 /** @type {string} */
1874 var nationalNumber = this.getNationalSignificantNumber(number);
1875 /** @type {i18n.phonenumbers.NumberFormat} */
1876 var formatRule = this.chooseFormattingPatternForNumber_(
1877 metadata.numberFormatArray(), nationalNumber);
1878 // The format rule could still be null here if the national number was 0
1879 // and there was no raw input (this should not be possible for numbers
1880 // generated by the phonenumber library as they would also not have a
1881 // country calling code and we would have exited earlier).
1882 if (formatRule == null) {
1883 formattedNumber = nationalFormat;
1886 // When the format we apply to this number doesn't contain national
1887 // prefix, we can just return the national format.
1888 // TODO: Refactor the code below with the code in
1889 // isNationalPrefixPresentIfRequired.
1890 /** @type {string} */
1891 var candidateNationalPrefixRule =
1892 formatRule.getNationalPrefixFormattingRuleOrDefault();
1893 // We assume that the first-group symbol will never be _before_ the
1895 /** @type {number} */
1896 var indexOfFirstGroup = candidateNationalPrefixRule.indexOf('$1');
1897 if (indexOfFirstGroup <= 0) {
1898 formattedNumber = nationalFormat;
1901 candidateNationalPrefixRule =
1902 candidateNationalPrefixRule.substring(0, indexOfFirstGroup);
1903 candidateNationalPrefixRule = i18n.phonenumbers.PhoneNumberUtil
1904 .normalizeDigitsOnly(candidateNationalPrefixRule);
1905 if (candidateNationalPrefixRule.length == 0) {
1906 // National prefix not used when formatting this number.
1907 formattedNumber = nationalFormat;
1910 // Otherwise, we need to remove the national prefix from our output.
1911 /** @type {i18n.phonenumbers.NumberFormat} */
1912 var numFormatCopy = formatRule.clone();
1913 numFormatCopy.clearNationalPrefixFormattingRule();
1914 formattedNumber = this.formatByPattern(number,
1915 i18n.phonenumbers.PhoneNumberFormat.NATIONAL, [numFormatCopy]);
1918 /** @type {string} */
1919 var rawInput = number.getRawInputOrDefault();
1920 // If no digit is inserted/removed/modified as a result of our formatting, we
1921 // return the formatted phone number; otherwise we return the raw input the
1923 if (formattedNumber != null && rawInput.length > 0) {
1924 /** @type {string} */
1925 var normalizedFormattedNumber =
1926 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
1927 i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
1928 true /* remove non matches */);
1929 /** @type {string} */
1930 var normalizedRawInput =
1931 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(rawInput,
1932 i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
1933 true /* remove non matches */);
1934 if (normalizedFormattedNumber != normalizedRawInput) {
1935 formattedNumber = rawInput;
1938 return formattedNumber;
1943 * Check if rawInput, which is assumed to be in the national format, has a
1944 * national prefix. The national prefix is assumed to be in digits-only form.
1945 * @param {string} rawInput
1946 * @param {string} nationalPrefix
1947 * @param {string} regionCode
1951 i18n.phonenumbers.PhoneNumberUtil.prototype.rawInputContainsNationalPrefix_ =
1952 function(rawInput, nationalPrefix, regionCode) {
1954 /** @type {string} */
1955 var normalizedNationalNumber =
1956 i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(rawInput);
1957 if (goog.string.startsWith(normalizedNationalNumber, nationalPrefix)) {
1959 // Some Japanese numbers (e.g. 00777123) might be mistaken to contain the
1960 // national prefix when written without it (e.g. 0777123) if we just do
1961 // prefix matching. To tackle that, we check the validity of the number if
1962 // the assumed national prefix is removed (777123 won't be valid in
1964 return this.isValidNumber(
1965 this.parse(normalizedNationalNumber.substring(nationalPrefix.length),
1976 * Returns true if a number is from a region whose national significant number
1977 * couldn't contain a leading zero, but has the italian_leading_zero field set
1979 * @param {i18n.phonenumbers.PhoneNumber} number
1983 i18n.phonenumbers.PhoneNumberUtil.prototype.hasUnexpectedItalianLeadingZero_ =
1986 return number.hasItalianLeadingZero() &&
1987 !this.isLeadingZeroPossible(number.getCountryCodeOrDefault());
1992 * @param {i18n.phonenumbers.PhoneNumber} number
1996 i18n.phonenumbers.PhoneNumberUtil.prototype.hasFormattingPatternForNumber_ =
1999 /** @type {number} */
2000 var countryCallingCode = number.getCountryCodeOrDefault();
2001 /** @type {string} */
2002 var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCallingCode);
2003 /** @type {i18n.phonenumbers.PhoneMetadata} */
2004 var metadata = this.getMetadataForRegionOrCallingCode_(
2005 countryCallingCode, phoneNumberRegion);
2006 if (metadata == null) {
2009 /** @type {string} */
2010 var nationalNumber = this.getNationalSignificantNumber(number);
2011 /** @type {i18n.phonenumbers.NumberFormat} */
2012 var formatRule = this.chooseFormattingPatternForNumber_(
2013 metadata.numberFormatArray(), nationalNumber);
2014 return formatRule != null;
2019 * Formats a phone number for out-of-country dialing purposes.
2021 * Note that in this version, if the number was entered originally using alpha
2022 * characters and this version of the number is stored in raw_input, this
2023 * representation of the number will be used rather than the digit
2024 * representation. Grouping information, as specified by characters such as '-'
2025 * and ' ', will be retained.
2027 * <p><b>Caveats:</b></p>
2029 * <li>This will not produce good results if the country calling code is both
2030 * present in the raw input _and_ is the start of the national number. This is
2031 * not a problem in the regions which typically use alpha numbers.
2032 * <li>This will also not produce good results if the raw input has any grouping
2033 * information within the first three digits of the national number, and if the
2034 * function needs to strip preceding digits/words in the raw input before these
2035 * digits. Normally people group the first three digits together so this is not
2036 * a huge problem - and will be fixed if it proves to be so.
2039 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
2041 * @param {string} regionCallingFrom the region where the call is being placed.
2042 * @return {string} the formatted phone number.
2044 i18n.phonenumbers.PhoneNumberUtil.prototype.
2045 formatOutOfCountryKeepingAlphaChars = function(number, regionCallingFrom) {
2046 /** @type {string} */
2047 var rawInput = number.getRawInputOrDefault();
2048 // If there is no raw input, then we can't keep alpha characters because there
2049 // aren't any. In this case, we return formatOutOfCountryCallingNumber.
2050 if (rawInput.length == 0) {
2051 return this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
2053 /** @type {number} */
2054 var countryCode = number.getCountryCodeOrDefault();
2055 if (!this.hasValidCountryCallingCode_(countryCode)) {
2058 // Strip any prefix such as country calling code, IDD, that was present. We do
2059 // this by comparing the number in raw_input with the parsed number. To do
2060 // this, first we normalize punctuation. We retain number grouping symbols
2061 // such as ' ' only.
2062 rawInput = i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(
2064 i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_,
2066 // Now we trim everything before the first three digits in the parsed number.
2067 // We choose three because all valid alpha numbers have 3 digits at the start
2068 // - if it does not, then we don't trim anything at all. Similarly, if the
2069 // national number was less than three digits, we don't trim anything at all.
2070 /** @type {string} */
2071 var nationalNumber = this.getNationalSignificantNumber(number);
2072 if (nationalNumber.length > 3) {
2073 /** @type {number} */
2074 var firstNationalNumberDigit =
2075 rawInput.indexOf(nationalNumber.substring(0, 3));
2076 if (firstNationalNumberDigit != -1) {
2077 rawInput = rawInput.substring(firstNationalNumberDigit);
2080 /** @type {i18n.phonenumbers.PhoneMetadata} */
2081 var metadataForRegionCallingFrom =
2082 this.getMetadataForRegion(regionCallingFrom);
2083 if (countryCode == i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
2084 if (this.isNANPACountry(regionCallingFrom)) {
2085 return countryCode + ' ' + rawInput;
2087 } else if (metadataForRegionCallingFrom != null &&
2088 countryCode == this.getCountryCodeForValidRegion_(regionCallingFrom)) {
2089 /** @type {i18n.phonenumbers.NumberFormat} */
2090 var formattingPattern = this.chooseFormattingPatternForNumber_(
2091 metadataForRegionCallingFrom.numberFormatArray(), nationalNumber);
2092 if (formattingPattern == null) {
2093 // If no pattern above is matched, we format the original input.
2096 /** @type {i18n.phonenumbers.NumberFormat} */
2097 var newFormat = formattingPattern.clone();
2098 // The first group is the first group of digits that the user wrote
2100 newFormat.setPattern('(\\d+)(.*)');
2101 // Here we just concatenate them back together after the national prefix
2103 newFormat.setFormat('$1$2');
2104 // Now we format using this pattern instead of the default pattern, but
2105 // with the national prefix prefixed if necessary.
2106 // This will not work in the cases where the pattern (and not the leading
2107 // digits) decide whether a national prefix needs to be used, since we have
2108 // overridden the pattern to match anything, but that is not the case in the
2109 // metadata to date.
2110 return this.formatNsnUsingPattern_(rawInput, newFormat,
2111 i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
2113 /** @type {string} */
2114 var internationalPrefixForFormatting = '';
2115 // If an unsupported region-calling-from is entered, or a country with
2116 // multiple international prefixes, the international format of the number is
2117 // returned, unless there is a preferred international prefix.
2118 if (metadataForRegionCallingFrom != null) {
2119 /** @type {string} */
2120 var internationalPrefix =
2121 metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
2122 internationalPrefixForFormatting =
2123 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2124 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
2125 internationalPrefix) ?
2126 internationalPrefix :
2127 metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
2129 /** @type {string} */
2130 var regionCode = this.getRegionCodeForCountryCode(countryCode);
2131 // Metadata cannot be null because the country calling code is valid.
2132 /** @type {i18n.phonenumbers.PhoneMetadata} */
2133 var metadataForRegion =
2134 this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
2135 /** @type {string} */
2136 var formattedExtension = this.maybeGetFormattedExtension_(
2137 number, metadataForRegion,
2138 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
2139 if (internationalPrefixForFormatting.length > 0) {
2140 return internationalPrefixForFormatting + ' ' + countryCode + ' ' +
2141 rawInput + formattedExtension;
2143 // Invalid region entered as country-calling-from (so no metadata was found
2144 // for it) or the region chosen has multiple international dialling
2146 return this.prefixNumberWithCountryCallingCode_(
2147 countryCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
2148 rawInput, formattedExtension);
2154 * Gets the national significant number of the a phone number. Note a national
2155 * significant number doesn't contain a national prefix or any formatting.
2157 * @param {i18n.phonenumbers.PhoneNumber} number the phone number for which the
2158 * national significant number is needed.
2159 * @return {string} the national significant number of the PhoneNumber object
2162 i18n.phonenumbers.PhoneNumberUtil.prototype.getNationalSignificantNumber =
2165 // If a leading zero has been set, we prefix this now. Note this is not a
2167 /** @type {string} */
2168 var nationalNumber = '' + number.getNationalNumber();
2169 if (number.hasItalianLeadingZero() && number.getItalianLeadingZero()) {
2170 return '0' + nationalNumber;
2172 return nationalNumber;
2177 * A helper function that is used by format and formatByPattern.
2179 * @param {number} countryCallingCode the country calling code.
2180 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2181 * phone number should be formatted into.
2182 * @param {string} formattedNationalNumber
2183 * @param {string} formattedExtension
2184 * @return {string} the formatted phone number.
2187 i18n.phonenumbers.PhoneNumberUtil.prototype.
2188 prefixNumberWithCountryCallingCode_ = function(countryCallingCode,
2190 formattedNationalNumber,
2191 formattedExtension) {
2193 switch (numberFormat) {
2194 case i18n.phonenumbers.PhoneNumberFormat.E164:
2195 return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
2196 formattedNationalNumber + formattedExtension;
2197 case i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL:
2198 return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
2199 ' ' + formattedNationalNumber + formattedExtension;
2200 case i18n.phonenumbers.PhoneNumberFormat.RFC3966:
2201 return i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_ +
2202 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
2203 '-' + formattedNationalNumber + formattedExtension;
2204 case i18n.phonenumbers.PhoneNumberFormat.NATIONAL:
2206 return formattedNationalNumber + formattedExtension;
2212 * Note in some regions, the national number can be written in two completely
2213 * different ways depending on whether it forms part of the NATIONAL format or
2214 * INTERNATIONAL format. The numberFormat parameter here is used to specify
2215 * which format to use for those cases. If a carrierCode is specified, this will
2216 * be inserted into the formatted string to replace $CC.
2218 * @param {string} number a string of characters representing a phone number.
2219 * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
2220 * region that we think this number is from.
2221 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2222 * phone number should be formatted into.
2223 * @param {string=} opt_carrierCode
2224 * @return {string} the formatted phone number.
2227 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNsn_ =
2228 function(number, metadata, numberFormat, opt_carrierCode) {
2230 /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
2231 var intlNumberFormats = metadata.intlNumberFormatArray();
2232 // When the intlNumberFormats exists, we use that to format national number
2233 // for the INTERNATIONAL format instead of using the numberDesc.numberFormats.
2234 /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
2235 var availableFormats =
2236 (intlNumberFormats.length == 0 ||
2237 numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL) ?
2238 metadata.numberFormatArray() : metadata.intlNumberFormatArray();
2239 /** @type {i18n.phonenumbers.NumberFormat} */
2240 var formattingPattern = this.chooseFormattingPatternForNumber_(
2241 availableFormats, number);
2242 return (formattingPattern == null) ?
2244 this.formatNsnUsingPattern_(number, formattingPattern,
2245 numberFormat, opt_carrierCode);
2250 * @param {Array.<i18n.phonenumbers.NumberFormat>} availableFormats the
2251 * available formats the phone number could be formatted into.
2252 * @param {string} nationalNumber a string of characters representing a phone
2254 * @return {i18n.phonenumbers.NumberFormat}
2257 i18n.phonenumbers.PhoneNumberUtil.prototype.chooseFormattingPatternForNumber_ =
2258 function(availableFormats, nationalNumber) {
2260 /** @type {i18n.phonenumbers.NumberFormat} */
2262 /** @type {number} */
2263 var l = availableFormats.length;
2264 for (var i = 0; i < l; ++i) {
2265 numFormat = availableFormats[i];
2266 /** @type {number} */
2267 var size = numFormat.leadingDigitsPatternCount();
2269 // We always use the last leading_digits_pattern, as it is the most
2272 .search(numFormat.getLeadingDigitsPattern(size - 1)) == 0) {
2273 /** @type {!RegExp} */
2274 var patternToMatch = new RegExp(numFormat.getPattern());
2275 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(patternToMatch,
2286 * Note that carrierCode is optional - if null or an empty string, no carrier
2287 * code replacement will take place.
2289 * @param {string} nationalNumber a string of characters representing a phone
2291 * @param {i18n.phonenumbers.NumberFormat} formattingPattern the formatting rule
2292 * the phone number should be formatted into.
2293 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2294 * phone number should be formatted into.
2295 * @param {string=} opt_carrierCode
2296 * @return {string} the formatted phone number.
2299 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNsnUsingPattern_ =
2300 function(nationalNumber, formattingPattern, numberFormat, opt_carrierCode) {
2302 /** @type {string} */
2303 var numberFormatRule = formattingPattern.getFormatOrDefault();
2304 /** @type {!RegExp} */
2305 var patternToMatch = new RegExp(formattingPattern.getPattern());
2306 /** @type {string} */
2307 var domesticCarrierCodeFormattingRule =
2308 formattingPattern.getDomesticCarrierCodeFormattingRuleOrDefault();
2309 /** @type {string} */
2310 var formattedNationalNumber = '';
2311 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
2312 opt_carrierCode != null && opt_carrierCode.length > 0 &&
2313 domesticCarrierCodeFormattingRule.length > 0) {
2314 // Replace the $CC in the formatting rule with the desired carrier code.
2315 /** @type {string} */
2316 var carrierCodeFormattingRule = domesticCarrierCodeFormattingRule
2317 .replace(i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_,
2319 // Now replace the $FG in the formatting rule with the first group and
2320 // the carrier code combined in the appropriate way.
2321 numberFormatRule = numberFormatRule.replace(
2322 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
2323 carrierCodeFormattingRule);
2324 formattedNationalNumber =
2325 nationalNumber.replace(patternToMatch, numberFormatRule);
2327 // Use the national prefix formatting rule instead.
2328 /** @type {string} */
2329 var nationalPrefixFormattingRule =
2330 formattingPattern.getNationalPrefixFormattingRuleOrDefault();
2331 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
2332 nationalPrefixFormattingRule != null &&
2333 nationalPrefixFormattingRule.length > 0) {
2334 formattedNationalNumber = nationalNumber.replace(patternToMatch,
2335 numberFormatRule.replace(
2336 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
2337 nationalPrefixFormattingRule));
2339 formattedNationalNumber =
2340 nationalNumber.replace(patternToMatch, numberFormatRule);
2343 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
2344 // Strip any leading punctuation.
2345 formattedNationalNumber = formattedNationalNumber.replace(
2346 new RegExp('^' + i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_),
2348 // Replace the rest with a dash between each number group.
2349 formattedNationalNumber = formattedNationalNumber.replace(
2350 new RegExp(i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_, 'g'),
2353 return formattedNationalNumber;
2358 * Gets a valid number for the specified region.
2360 * @param {string} regionCode the region for which an example number is needed.
2361 * @return {i18n.phonenumbers.PhoneNumber} a valid fixed-line number for the
2362 * specified region. Returns null when the metadata does not contain such
2363 * information, or the region 001 is passed in. For 001 (representing non-
2364 * geographical numbers), call {@link #getExampleNumberForNonGeoEntity}
2367 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumber =
2368 function(regionCode) {
2370 return this.getExampleNumberForType(regionCode,
2371 i18n.phonenumbers.PhoneNumberType.FIXED_LINE);
2376 * Gets a valid number for the specified region and number type.
2378 * @param {string} regionCode the region for which an example number is needed.
2379 * @param {i18n.phonenumbers.PhoneNumberType} type the type of number that is
2381 * @return {i18n.phonenumbers.PhoneNumber} a valid number for the specified
2382 * region and type. Returns null when the metadata does not contain such
2383 * information or if an invalid region or region 001 was entered.
2384 * For 001 (representing non-geographical numbers), call
2385 * {@link #getExampleNumberForNonGeoEntity} instead.
2387 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForType =
2388 function(regionCode, type) {
2390 // Check the region code is valid.
2391 if (!this.isValidRegionCode_(regionCode)) {
2394 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2395 var desc = this.getNumberDescByType_(
2396 this.getMetadataForRegion(regionCode), type);
2398 if (desc.hasExampleNumber()) {
2399 return this.parse(desc.getExampleNumberOrDefault(), regionCode);
2408 * Gets a valid number for the specified country calling code for a
2409 * non-geographical entity.
2411 * @param {number} countryCallingCode the country calling code for a
2412 * non-geographical entity.
2413 * @return {i18n.phonenumbers.PhoneNumber} a valid number for the
2414 * non-geographical entity. Returns null when the metadata does not contain
2415 * such information, or the country calling code passed in does not belong
2416 * to a non-geographical entity.
2418 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForNonGeoEntity =
2419 function(countryCallingCode) {
2420 /** @type {i18n.phonenumbers.PhoneMetadata} */
2422 this.getMetadataForNonGeographicalRegion(countryCallingCode);
2423 if (metadata != null) {
2424 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2425 var desc = metadata.getGeneralDesc();
2427 if (desc.hasExampleNumber()) {
2428 return this.parse('+' + countryCallingCode + desc.getExampleNumber(),
2439 * Gets the formatted extension of a phone number, if the phone number had an
2440 * extension specified. If not, it returns an empty string.
2442 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber that might have
2444 * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
2445 * region that we think this number is from.
2446 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2447 * phone number should be formatted into.
2448 * @return {string} the formatted extension if any.
2451 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeGetFormattedExtension_ =
2452 function(number, metadata, numberFormat) {
2454 if (!number.hasExtension() || number.getExtension().length == 0) {
2457 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
2458 return i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
2459 number.getExtension();
2461 if (metadata.hasPreferredExtnPrefix()) {
2462 return metadata.getPreferredExtnPrefix() +
2463 number.getExtensionOrDefault();
2465 return i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ +
2466 number.getExtensionOrDefault();
2474 * @param {i18n.phonenumbers.PhoneMetadata} metadata
2475 * @param {i18n.phonenumbers.PhoneNumberType} type
2476 * @return {i18n.phonenumbers.PhoneNumberDesc}
2479 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberDescByType_ =
2480 function(metadata, type) {
2483 case i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE:
2484 return metadata.getPremiumRate();
2485 case i18n.phonenumbers.PhoneNumberType.TOLL_FREE:
2486 return metadata.getTollFree();
2487 case i18n.phonenumbers.PhoneNumberType.MOBILE:
2488 return metadata.getMobile();
2489 case i18n.phonenumbers.PhoneNumberType.FIXED_LINE:
2490 case i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE:
2491 return metadata.getFixedLine();
2492 case i18n.phonenumbers.PhoneNumberType.SHARED_COST:
2493 return metadata.getSharedCost();
2494 case i18n.phonenumbers.PhoneNumberType.VOIP:
2495 return metadata.getVoip();
2496 case i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER:
2497 return metadata.getPersonalNumber();
2498 case i18n.phonenumbers.PhoneNumberType.PAGER:
2499 return metadata.getPager();
2500 case i18n.phonenumbers.PhoneNumberType.UAN:
2501 return metadata.getUan();
2502 case i18n.phonenumbers.PhoneNumberType.VOICEMAIL:
2503 return metadata.getVoicemail();
2505 return metadata.getGeneralDesc();
2511 * Gets the type of a phone number.
2513 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2515 * @return {i18n.phonenumbers.PhoneNumberType} the type of the phone number.
2517 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberType =
2520 /** @type {?string} */
2521 var regionCode = this.getRegionCodeForNumber(number);
2522 /** @type {i18n.phonenumbers.PhoneMetadata} */
2523 var metadata = this.getMetadataForRegionOrCallingCode_(
2524 number.getCountryCodeOrDefault(), regionCode);
2525 if (metadata == null) {
2526 return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2528 /** @type {string} */
2529 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
2530 return this.getNumberTypeHelper_(nationalSignificantNumber, metadata);
2535 * @param {string} nationalNumber
2536 * @param {i18n.phonenumbers.PhoneMetadata} metadata
2537 * @return {i18n.phonenumbers.PhoneNumberType}
2540 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberTypeHelper_ =
2541 function(nationalNumber, metadata) {
2543 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2544 var generalNumberDesc = metadata.getGeneralDesc();
2545 if (!generalNumberDesc.hasNationalNumberPattern() ||
2546 !this.isNumberMatchingDesc_(nationalNumber, generalNumberDesc)) {
2547 return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2550 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPremiumRate())) {
2551 return i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE;
2553 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getTollFree())) {
2554 return i18n.phonenumbers.PhoneNumberType.TOLL_FREE;
2556 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getSharedCost())) {
2557 return i18n.phonenumbers.PhoneNumberType.SHARED_COST;
2559 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoip())) {
2560 return i18n.phonenumbers.PhoneNumberType.VOIP;
2562 if (this.isNumberMatchingDesc_(nationalNumber,
2563 metadata.getPersonalNumber())) {
2564 return i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER;
2566 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPager())) {
2567 return i18n.phonenumbers.PhoneNumberType.PAGER;
2569 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getUan())) {
2570 return i18n.phonenumbers.PhoneNumberType.UAN;
2572 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoicemail())) {
2573 return i18n.phonenumbers.PhoneNumberType.VOICEMAIL;
2576 /** @type {boolean} */
2577 var isFixedLine = this.isNumberMatchingDesc_(nationalNumber, metadata
2580 if (metadata.getSameMobileAndFixedLinePattern()) {
2581 return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
2582 } else if (this.isNumberMatchingDesc_(nationalNumber,
2583 metadata.getMobile())) {
2584 return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
2586 return i18n.phonenumbers.PhoneNumberType.FIXED_LINE;
2588 // Otherwise, test to see if the number is mobile. Only do this if certain
2589 // that the patterns for mobile and fixed line aren't the same.
2590 if (!metadata.getSameMobileAndFixedLinePattern() &&
2591 this.isNumberMatchingDesc_(nationalNumber, metadata.getMobile())) {
2592 return i18n.phonenumbers.PhoneNumberType.MOBILE;
2594 return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2599 * Returns the metadata for the given region code or {@code null} if the region
2600 * code is invalid or unknown.
2602 * @param {?string} regionCode
2603 * @return {i18n.phonenumbers.PhoneMetadata}
2605 i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegion =
2606 function(regionCode) {
2608 if (regionCode == null) {
2611 regionCode = regionCode.toUpperCase();
2612 /** @type {i18n.phonenumbers.PhoneMetadata} */
2613 var metadata = this.regionToMetadataMap[regionCode];
2614 if (metadata == null) {
2615 /** @type {goog.proto2.PbLiteSerializer} */
2616 var serializer = new goog.proto2.PbLiteSerializer();
2617 /** @type {Array} */
2618 var metadataSerialized =
2619 i18n.phonenumbers.metadata.countryToMetadata[regionCode];
2620 if (metadataSerialized == null) {
2623 metadata = /** @type {i18n.phonenumbers.PhoneMetadata} */ (
2624 serializer.deserialize(i18n.phonenumbers.PhoneMetadata.getDescriptor(),
2625 metadataSerialized));
2626 this.regionToMetadataMap[regionCode] = metadata;
2633 * @param {number} countryCallingCode
2634 * @return {i18n.phonenumbers.PhoneMetadata}
2636 i18n.phonenumbers.PhoneNumberUtil.prototype.
2637 getMetadataForNonGeographicalRegion = function(countryCallingCode) {
2639 return this.getMetadataForRegion('' + countryCallingCode);
2644 * @param {string} nationalNumber
2645 * @param {i18n.phonenumbers.PhoneNumberDesc} numberDesc
2649 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatchingDesc_ =
2650 function(nationalNumber, numberDesc) {
2652 return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2653 numberDesc.getPossibleNumberPatternOrDefault(), nationalNumber) &&
2654 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2655 numberDesc.getNationalNumberPatternOrDefault(), nationalNumber);
2660 * Tests whether a phone number matches a valid pattern. Note this doesn't
2661 * verify the number is actually in use, which is impossible to tell by just
2662 * looking at a number itself.
2664 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2666 * @return {boolean} a boolean that indicates whether the number is of a valid
2669 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) {
2670 /** @type {?string} */
2671 var regionCode = this.getRegionCodeForNumber(number);
2672 return this.isValidNumberForRegion(number, regionCode);
2677 * Tests whether a phone number is valid for a certain region. Note this doesn't
2678 * verify the number is actually in use, which is impossible to tell by just
2679 * looking at a number itself. If the country calling code is not the same as
2680 * the country calling code for the region, this immediately exits with false.
2681 * After this, the specific number pattern rules for the region are examined.
2682 * This is useful for determining for example whether a particular number is
2683 * valid for Canada, rather than just a valid NANPA number.
2684 * Warning: In most cases, you want to use {@link #isValidNumber} instead. For
2685 * example, this method will mark numbers from British Crown dependencies such
2686 * as the Isle of Man as invalid for the region "GB" (United Kingdom), since it
2687 * has its own region code, "IM", which may be undesirable.
2689 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2691 * @param {?string} regionCode the region that we want to validate the phone
2693 * @return {boolean} a boolean that indicates whether the number is of a valid
2696 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumberForRegion =
2697 function(number, regionCode) {
2699 /** @type {number} */
2700 var countryCode = number.getCountryCodeOrDefault();
2701 /** @type {i18n.phonenumbers.PhoneMetadata} */
2703 this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
2704 if (metadata == null ||
2705 (i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY !=
2707 countryCode != this.getCountryCodeForValidRegion_(regionCode))) {
2708 // Either the region code was invalid, or the country calling code for this
2709 // number does not match that of the region code.
2712 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2713 var generalNumDesc = metadata.getGeneralDesc();
2714 /** @type {string} */
2715 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
2717 // For regions where we don't have metadata for PhoneNumberDesc, we treat any
2718 // number passed in as a valid number if its national significant number is
2719 // between the minimum and maximum lengths defined by ITU for a national
2720 // significant number.
2721 if (!generalNumDesc.hasNationalNumberPattern()) {
2722 /** @type {number} */
2723 var numberLength = nationalSignificantNumber.length;
2724 return numberLength >
2725 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ &&
2726 numberLength <= i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_;
2728 return this.getNumberTypeHelper_(nationalSignificantNumber, metadata) !=
2729 i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2734 * Returns the region where a phone number is from. This could be used for
2735 * geocoding at the region level.
2737 * @param {i18n.phonenumbers.PhoneNumber} number the phone number whose origin
2739 * @return {?string} the region where the phone number is from, or null
2740 * if no region matches this calling code.
2742 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForNumber =
2745 if (number == null) {
2748 /** @type {number} */
2749 var countryCode = number.getCountryCodeOrDefault();
2750 /** @type {Array.<string>} */
2752 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCode];
2753 if (regions == null) {
2756 if (regions.length == 1) {
2759 return this.getRegionCodeForNumberFromRegionList_(number, regions);
2765 * @param {i18n.phonenumbers.PhoneNumber} number
2766 * @param {Array.<string>} regionCodes
2770 i18n.phonenumbers.PhoneNumberUtil.prototype.
2771 getRegionCodeForNumberFromRegionList_ = function(number, regionCodes) {
2773 /** @type {string} */
2774 var nationalNumber = this.getNationalSignificantNumber(number);
2775 /** @type {string} */
2777 /** @type {number} */
2778 var regionCodesLength = regionCodes.length;
2779 for (var i = 0; i < regionCodesLength; i++) {
2780 regionCode = regionCodes[i];
2781 // If leadingDigits is present, use this. Otherwise, do full validation.
2782 // Metadata cannot be null because the region codes come from the country
2783 // calling code map.
2784 /** @type {i18n.phonenumbers.PhoneMetadata} */
2785 var metadata = this.getMetadataForRegion(regionCode);
2786 if (metadata.hasLeadingDigits()) {
2787 if (nationalNumber.search(metadata.getLeadingDigits()) == 0) {
2790 } else if (this.getNumberTypeHelper_(nationalNumber, metadata) !=
2791 i18n.phonenumbers.PhoneNumberType.UNKNOWN) {
2800 * Returns the region code that matches the specific country calling code. In
2801 * the case of no region code being found, ZZ will be returned. In the case of
2802 * multiple regions, the one designated in the metadata as the 'main' region for
2803 * this calling code will be returned.
2805 * @param {number} countryCallingCode the country calling code.
2808 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForCountryCode =
2809 function(countryCallingCode) {
2811 /** @type {Array.<string>} */
2813 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
2814 return regionCodes == null ?
2815 i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ : regionCodes[0];
2820 * Returns a list with the region codes that match the specific country calling
2821 * code. For non-geographical country calling codes, the region code 001 is
2822 * returned. Also, in the case of no region code being found, an empty list is
2825 * @param {number} countryCallingCode the country calling code.
2826 * @return {Array.<string>}
2828 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodesForCountryCode =
2829 function(countryCallingCode) {
2831 /** @type {Array.<string>} */
2833 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
2834 return regionCodes == null ? [] : regionCodes;
2839 * Returns the country calling code for a specific region. For example, this
2840 * would be 1 for the United States, and 64 for New Zealand.
2842 * @param {?string} regionCode the region that we want to get the country
2844 * @return {number} the country calling code for the region denoted by
2847 i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForRegion =
2848 function(regionCode) {
2850 if (!this.isValidRegionCode_(regionCode)) {
2853 return this.getCountryCodeForValidRegion_(regionCode);
2858 * Returns the country calling code for a specific region. For example, this
2859 * would be 1 for the United States, and 64 for New Zealand. Assumes the region
2862 * @param {?string} regionCode the region that we want to get the country
2864 * @return {number} the country calling code for the region denoted by
2866 * @throws {string} if the region is invalid
2869 i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForValidRegion_ =
2870 function(regionCode) {
2872 /** @type {i18n.phonenumbers.PhoneMetadata} */
2873 var metadata = this.getMetadataForRegion(regionCode);
2874 if (metadata == null) {
2875 throw 'Invalid region code: ' + regionCode;
2877 return metadata.getCountryCodeOrDefault();
2882 * Returns the national dialling prefix for a specific region. For example, this
2883 * would be 1 for the United States, and 0 for New Zealand. Set stripNonDigits
2884 * to true to strip symbols like '~' (which indicates a wait for a dialling
2885 * tone) from the prefix returned. If no national prefix is present, we return
2888 * <p>Warning: Do not use this method for do-your-own formatting - for some
2889 * regions, the national dialling prefix is used only for certain types of
2890 * numbers. Use the library's formatting functions to prefix the national prefix
2893 * @param {?string} regionCode the region that we want to get the dialling
2895 * @param {boolean} stripNonDigits true to strip non-digits from the national
2897 * @return {?string} the dialling prefix for the region denoted by
2900 i18n.phonenumbers.PhoneNumberUtil.prototype.getNddPrefixForRegion = function(
2901 regionCode, stripNonDigits) {
2902 /** @type {i18n.phonenumbers.PhoneMetadata} */
2903 var metadata = this.getMetadataForRegion(regionCode);
2904 if (metadata == null) {
2907 /** @type {string} */
2908 var nationalPrefix = metadata.getNationalPrefixOrDefault();
2909 // If no national prefix was found, we return null.
2910 if (nationalPrefix.length == 0) {
2913 if (stripNonDigits) {
2914 // Note: if any other non-numeric symbols are ever used in national
2915 // prefixes, these would have to be removed here as well.
2916 nationalPrefix = nationalPrefix.replace('~', '');
2918 return nationalPrefix;
2923 * Checks if this is a region under the North American Numbering Plan
2924 * Administration (NANPA).
2926 * @param {?string} regionCode the ISO 3166-1 two-letter region code.
2927 * @return {boolean} true if regionCode is one of the regions under NANPA.
2929 i18n.phonenumbers.PhoneNumberUtil.prototype.isNANPACountry =
2930 function(regionCode) {
2932 return regionCode != null && goog.array.contains(
2933 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[
2934 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_],
2935 regionCode.toUpperCase());
2940 * Checks whether countryCode represents the country calling code from a region
2941 * whose national significant number could contain a leading zero. An example of
2942 * such a region is Italy. Returns false if no metadata for the country is
2945 * @param {number} countryCallingCode the country calling code.
2948 i18n.phonenumbers.PhoneNumberUtil.prototype.isLeadingZeroPossible =
2949 function(countryCallingCode) {
2950 /** @type {i18n.phonenumbers.PhoneMetadata} */
2951 var mainMetadataForCallingCode = this.getMetadataForRegionOrCallingCode_(
2953 this.getRegionCodeForCountryCode(countryCallingCode));
2954 return mainMetadataForCallingCode != null &&
2955 mainMetadataForCallingCode.getLeadingZeroPossibleOrDefault();
2960 * Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT.
2961 * A valid vanity number will start with at least 3 digits and will have three
2962 * or more alpha characters. This does not do region-specific checks - to work
2963 * out if this number is actually valid for a region, it should be parsed and
2964 * methods such as {@link #isPossibleNumberWithReason} and
2965 * {@link #isValidNumber} should be used.
2967 * @param {string} number the number that needs to be checked.
2968 * @return {boolean} true if the number is a valid vanity number.
2970 i18n.phonenumbers.PhoneNumberUtil.prototype.isAlphaNumber = function(number) {
2971 if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(number)) {
2972 // Number is too short, or doesn't match the basic phone number pattern.
2975 /** @type {!goog.string.StringBuffer} */
2976 var strippedNumber = new goog.string.StringBuffer(number);
2977 this.maybeStripExtension(strippedNumber);
2978 return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2979 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_,
2980 strippedNumber.toString());
2985 * Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of
2986 * returning the reason for failure, this method returns a boolean value.
2988 * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
2990 * @return {boolean} true if the number is possible.
2992 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumber =
2995 return this.isPossibleNumberWithReason(number) ==
2996 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
3001 * Helper method to check a number against a particular pattern and determine
3002 * whether it matches, or is too short or too long. Currently, if a number
3003 * pattern suggests that numbers of length 7 and 10 are possible, and a number
3004 * in between these possible lengths is entered, such as of length 8, this will
3007 * @param {string} numberPattern
3008 * @param {string} number
3009 * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult}
3012 i18n.phonenumbers.PhoneNumberUtil.prototype.testNumberLengthAgainstPattern_ =
3013 function(numberPattern, number) {
3014 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(numberPattern,
3016 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
3018 if (number.search(numberPattern) == 0) {
3019 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG;
3021 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
3027 * Check whether a phone number is a possible number. It provides a more lenient
3028 * check than {@link #isValidNumber} in the following sense:
3030 * <li>It only checks the length of phone numbers. In particular, it doesn't
3031 * check starting digits of the number.
3032 * <li>It doesn't attempt to figure out the type of the number, but uses general
3033 * rules which applies to all types of phone numbers in a region. Therefore, it
3034 * is much faster than isValidNumber.
3035 * <li>For fixed line numbers, many regions have the concept of area code, which
3036 * together with subscriber number constitute the national significant number.
3037 * It is sometimes okay to dial the subscriber number only when dialing in the
3038 * same area. This function will return true if the subscriber-number-only
3039 * version is passed in. On the other hand, because isValidNumber validates
3040 * using information on both starting digits (for fixed line numbers, that would
3041 * most likely be area codes) and length (obviously includes the length of area
3042 * codes for fixed line numbers), it will return false for the
3043 * subscriber-number-only version.
3046 * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
3048 * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult} a
3049 * ValidationResult object which indicates whether the number is possible.
3051 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason =
3054 /** @type {string} */
3055 var nationalNumber = this.getNationalSignificantNumber(number);
3056 /** @type {number} */
3057 var countryCode = number.getCountryCodeOrDefault();
3058 // Note: For Russian Fed and NANPA numbers, we just use the rules from the
3059 // default region (US or Russia) since the getRegionCodeForNumber will not
3060 // work if the number is possible but not valid. This would need to be
3061 // revisited if the possible number pattern ever differed between various
3062 // regions within those plans.
3063 if (!this.hasValidCountryCallingCode_(countryCode)) {
3064 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult
3065 .INVALID_COUNTRY_CODE;
3067 /** @type {string} */
3068 var regionCode = this.getRegionCodeForCountryCode(countryCode);
3069 // Metadata cannot be null because the country calling code is valid.
3070 /** @type {i18n.phonenumbers.PhoneMetadata} */
3072 this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
3073 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
3074 var generalNumDesc = metadata.getGeneralDesc();
3075 // Handling case of numbers with no metadata.
3076 if (!generalNumDesc.hasNationalNumberPattern()) {
3077 /** @type {number} */
3078 var numberLength = nationalNumber.length;
3079 if (numberLength < i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3080 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
3081 } else if (numberLength >
3082 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_) {
3083 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG;
3085 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
3088 /** @type {string} */
3089 var possibleNumberPattern =
3090 generalNumDesc.getPossibleNumberPatternOrDefault();
3091 return this.testNumberLengthAgainstPattern_(possibleNumberPattern,
3097 * Check whether a phone number is a possible number given a number in the form
3098 * of a string, and the region where the number could be dialed from. It
3099 * provides a more lenient check than {@link #isValidNumber}. See
3100 * {@link #isPossibleNumber} for details.
3102 * <p>This method first parses the number, then invokes
3103 * {@link #isPossibleNumber} with the resultant PhoneNumber object.
3105 * @param {string} number the number that needs to be checked, in the form of a
3107 * @param {string} regionDialingFrom the region that we are expecting the number
3108 * to be dialed from.
3109 * Note this is different from the region where the number belongs.
3110 * For example, the number +1 650 253 0000 is a number that belongs to US.
3111 * When written in this form, it can be dialed from any region. When it is
3112 * written as 00 1 650 253 0000, it can be dialed from any region which uses
3113 * an international dialling prefix of 00. When it is written as
3114 * 650 253 0000, it can only be dialed from within the US, and when written
3115 * as 253 0000, it can only be dialed from within a smaller area in the US
3116 * (Mountain View, CA, to be more specific).
3117 * @return {boolean} true if the number is possible.
3119 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberString =
3120 function(number, regionDialingFrom) {
3123 return this.isPossibleNumber(this.parse(number, regionDialingFrom));
3131 * Attempts to extract a valid number from a phone number that is too long to be
3132 * valid, and resets the PhoneNumber object passed in to that valid version. If
3133 * no valid number could be extracted, the PhoneNumber object passed in will not
3135 * @param {i18n.phonenumbers.PhoneNumber} number a PhoneNumber object which
3136 * contains a number that is too long to be valid.
3137 * @return {boolean} true if a valid phone number can be successfully extracted.
3139 i18n.phonenumbers.PhoneNumberUtil.prototype.truncateTooLongNumber =
3142 if (this.isValidNumber(number)) {
3145 /** @type {i18n.phonenumbers.PhoneNumber} */
3146 var numberCopy = number.clone();
3147 /** @type {number} */
3148 var nationalNumber = number.getNationalNumberOrDefault();
3150 nationalNumber = Math.floor(nationalNumber / 10);
3151 numberCopy.setNationalNumber(nationalNumber);
3152 if (nationalNumber == 0 ||
3153 this.isPossibleNumberWithReason(numberCopy) ==
3154 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT) {
3157 } while (!this.isValidNumber(numberCopy));
3158 number.setNationalNumber(nationalNumber);
3164 * Extracts country calling code from fullNumber, returns it and places the
3165 * remaining number in nationalNumber. It assumes that the leading plus sign or
3166 * IDD has already been removed. Returns 0 if fullNumber doesn't start with a
3167 * valid country calling code, and leaves nationalNumber unmodified.
3169 * @param {!goog.string.StringBuffer} fullNumber
3170 * @param {!goog.string.StringBuffer} nationalNumber
3173 i18n.phonenumbers.PhoneNumberUtil.prototype.extractCountryCode =
3174 function(fullNumber, nationalNumber) {
3176 /** @type {string} */
3177 var fullNumberStr = fullNumber.toString();
3178 if ((fullNumberStr.length == 0) || (fullNumberStr.charAt(0) == '0')) {
3179 // Country codes do not begin with a '0'.
3182 /** @type {number} */
3183 var potentialCountryCode;
3184 /** @type {number} */
3185 var numberLength = fullNumberStr.length;
3187 i <= i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE_ &&
3188 i <= numberLength; ++i) {
3189 potentialCountryCode = parseInt(fullNumberStr.substring(0, i), 10);
3190 if (potentialCountryCode in
3191 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap) {
3192 nationalNumber.append(fullNumberStr.substring(i));
3193 return potentialCountryCode;
3201 * Tries to extract a country calling code from a number. This method will
3202 * return zero if no country calling code is considered to be present. Country
3203 * calling codes are extracted in the following ways:
3205 * <li>by stripping the international dialing prefix of the region the person is
3206 * dialing from, if this is present in the number, and looking at the next
3208 * <li>by stripping the '+' sign if present and then looking at the next digits
3209 * <li>by comparing the start of the number and the country calling code of the
3210 * default region. If the number is not considered possible for the numbering
3211 * plan of the default region initially, but starts with the country calling
3212 * code of this region, validation will be reattempted after stripping this
3213 * country calling code. If this number is considered a possible number, then
3214 * the first digits will be considered the country calling code and removed as
3218 * It will throw a i18n.phonenumbers.Error if the number starts with a '+' but
3219 * the country calling code supplied after this does not match that of any known
3222 * @param {string} number non-normalized telephone number that we wish to
3223 * extract a country calling code from - may begin with '+'.
3224 * @param {i18n.phonenumbers.PhoneMetadata} defaultRegionMetadata metadata
3225 * about the region this number may be from.
3226 * @param {!goog.string.StringBuffer} nationalNumber a string buffer to store
3227 * the national significant number in, in the case that a country calling
3228 * code was extracted. The number is appended to any existing contents. If
3229 * no country calling code was extracted, this will be left unchanged.
3230 * @param {boolean} keepRawInput true if the country_code_source and
3231 * preferred_carrier_code fields of phoneNumber should be populated.
3232 * @param {i18n.phonenumbers.PhoneNumber} phoneNumber the PhoneNumber object
3233 * where the country_code and country_code_source need to be populated.
3234 * Note the country_code is always populated, whereas country_code_source is
3235 * only populated when keepCountryCodeSource is true.
3236 * @return {number} the country calling code extracted or 0 if none could be
3238 * @throws {i18n.phonenumbers.Error}
3240 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode =
3241 function(number, defaultRegionMetadata, nationalNumber,
3242 keepRawInput, phoneNumber) {
3244 if (number.length == 0) {
3247 /** @type {!goog.string.StringBuffer} */
3248 var fullNumber = new goog.string.StringBuffer(number);
3249 // Set the default prefix to be something that will never match.
3250 /** @type {?string} */
3251 var possibleCountryIddPrefix;
3252 if (defaultRegionMetadata != null) {
3253 possibleCountryIddPrefix = defaultRegionMetadata.getInternationalPrefix();
3255 if (possibleCountryIddPrefix == null) {
3256 possibleCountryIddPrefix = 'NonMatch';
3259 /** @type {i18n.phonenumbers.PhoneNumber.CountryCodeSource} */
3260 var countryCodeSource = this.maybeStripInternationalPrefixAndNormalize(
3261 fullNumber, possibleCountryIddPrefix);
3263 phoneNumber.setCountryCodeSource(countryCodeSource);
3265 if (countryCodeSource !=
3266 i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY) {
3267 if (fullNumber.getLength() <=
3268 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3269 throw i18n.phonenumbers.Error.TOO_SHORT_AFTER_IDD;
3271 /** @type {number} */
3272 var potentialCountryCode = this.extractCountryCode(fullNumber,
3274 if (potentialCountryCode != 0) {
3275 phoneNumber.setCountryCode(potentialCountryCode);
3276 return potentialCountryCode;
3279 // If this fails, they must be using a strange country calling code that we
3280 // don't recognize, or that doesn't exist.
3281 throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
3282 } else if (defaultRegionMetadata != null) {
3283 // Check to see if the number starts with the country calling code for the
3284 // default region. If so, we remove the country calling code, and do some
3285 // checks on the validity of the number before and after.
3286 /** @type {number} */
3287 var defaultCountryCode = defaultRegionMetadata.getCountryCodeOrDefault();
3288 /** @type {string} */
3289 var defaultCountryCodeString = '' + defaultCountryCode;
3290 /** @type {string} */
3291 var normalizedNumber = fullNumber.toString();
3292 if (goog.string.startsWith(normalizedNumber, defaultCountryCodeString)) {
3293 /** @type {!goog.string.StringBuffer} */
3294 var potentialNationalNumber = new goog.string.StringBuffer(
3295 normalizedNumber.substring(defaultCountryCodeString.length));
3296 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
3297 var generalDesc = defaultRegionMetadata.getGeneralDesc();
3298 /** @type {!RegExp} */
3299 var validNumberPattern =
3300 new RegExp(generalDesc.getNationalNumberPatternOrDefault());
3301 // Passing null since we don't need the carrier code.
3302 this.maybeStripNationalPrefixAndCarrierCode(
3303 potentialNationalNumber, defaultRegionMetadata, null);
3304 /** @type {string} */
3305 var potentialNationalNumberStr = potentialNationalNumber.toString();
3306 /** @type {string} */
3307 var possibleNumberPattern =
3308 generalDesc.getPossibleNumberPatternOrDefault();
3309 // If the number was not valid before but is valid now, or if it was too
3310 // long before, we consider the number with the country calling code
3311 // stripped to be a better result and keep that instead.
3312 if ((!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3313 validNumberPattern, fullNumber.toString()) &&
3314 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3315 validNumberPattern, potentialNationalNumberStr)) ||
3316 this.testNumberLengthAgainstPattern_(possibleNumberPattern,
3317 fullNumber.toString()) ==
3318 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG) {
3319 nationalNumber.append(potentialNationalNumberStr);
3321 phoneNumber.setCountryCodeSource(
3322 i18n.phonenumbers.PhoneNumber.CountryCodeSource
3323 .FROM_NUMBER_WITHOUT_PLUS_SIGN);
3325 phoneNumber.setCountryCode(defaultCountryCode);
3326 return defaultCountryCode;
3330 // No country calling code present.
3331 phoneNumber.setCountryCode(0);
3337 * Strips the IDD from the start of the number if present. Helper function used
3338 * by maybeStripInternationalPrefixAndNormalize.
3340 * @param {!RegExp} iddPattern the regular expression for the international
3342 * @param {!goog.string.StringBuffer} number the phone number that we wish to
3343 * strip any international dialing prefix from.
3344 * @return {boolean} true if an international prefix was present.
3347 i18n.phonenumbers.PhoneNumberUtil.prototype.parsePrefixAsIdd_ =
3348 function(iddPattern, number) {
3350 /** @type {string} */
3351 var numberStr = number.toString();
3352 if (numberStr.search(iddPattern) == 0) {
3353 /** @type {number} */
3354 var matchEnd = numberStr.match(iddPattern)[0].length;
3355 /** @type {Array.<string>} */
3356 var matchedGroups = numberStr.substring(matchEnd).match(
3357 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN);
3358 if (matchedGroups && matchedGroups[1] != null &&
3359 matchedGroups[1].length > 0) {
3360 /** @type {string} */
3361 var normalizedGroup =
3362 i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(
3364 if (normalizedGroup == '0') {
3369 number.append(numberStr.substring(matchEnd));
3377 * Strips any international prefix (such as +, 00, 011) present in the number
3378 * provided, normalizes the resulting number, and indicates if an international
3379 * prefix was present.
3381 * @param {!goog.string.StringBuffer} number the non-normalized telephone number
3382 * that we wish to strip any international dialing prefix from.
3383 * @param {string} possibleIddPrefix the international direct dialing prefix
3384 * from the region we think this number may be dialed in.
3385 * @return {i18n.phonenumbers.PhoneNumber.CountryCodeSource} the corresponding
3386 * CountryCodeSource if an international dialing prefix could be removed
3387 * from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if
3388 * the number did not seem to be in international format.
3390 i18n.phonenumbers.PhoneNumberUtil.prototype.
3391 maybeStripInternationalPrefixAndNormalize = function(number,
3392 possibleIddPrefix) {
3393 /** @type {string} */
3394 var numberStr = number.toString();
3395 if (numberStr.length == 0) {
3396 return i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
3398 // Check to see if the number begins with one or more plus signs.
3399 if (i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_
3401 numberStr = numberStr.replace(
3402 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_, '');
3403 // Can now normalize the rest of the number since we've consumed the '+'
3404 // sign at the start.
3406 number.append(i18n.phonenumbers.PhoneNumberUtil.normalize(numberStr));
3407 return i18n.phonenumbers.PhoneNumber.CountryCodeSource
3408 .FROM_NUMBER_WITH_PLUS_SIGN;
3410 // Attempt to parse the first digits as an international prefix.
3411 /** @type {!RegExp} */
3412 var iddPattern = new RegExp(possibleIddPrefix);
3413 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(number);
3414 return this.parsePrefixAsIdd_(iddPattern, number) ?
3415 i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD :
3416 i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
3421 * Strips any national prefix (such as 0, 1) present in the number provided.
3423 * @param {!goog.string.StringBuffer} number the normalized telephone number
3424 * that we wish to strip any national dialing prefix from.
3425 * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
3426 * region that we think this number is from.
3427 * @param {goog.string.StringBuffer} carrierCode a place to insert the carrier
3428 * code if one is extracted.
3429 * @return {boolean} true if a national prefix or carrier code (or both) could
3432 i18n.phonenumbers.PhoneNumberUtil.prototype.
3433 maybeStripNationalPrefixAndCarrierCode = function(number, metadata,
3436 /** @type {string} */
3437 var numberStr = number.toString();
3438 /** @type {number} */
3439 var numberLength = numberStr.length;
3440 /** @type {?string} */
3441 var possibleNationalPrefix = metadata.getNationalPrefixForParsing();
3442 if (numberLength == 0 || possibleNationalPrefix == null ||
3443 possibleNationalPrefix.length == 0) {
3444 // Early return for numbers of zero length.
3447 // Attempt to parse the first digits as a national prefix.
3448 /** @type {!RegExp} */
3449 var prefixPattern = new RegExp('^(?:' + possibleNationalPrefix + ')');
3450 /** @type {Array.<string>} */
3451 var prefixMatcher = prefixPattern.exec(numberStr);
3452 if (prefixMatcher) {
3453 /** @type {!RegExp} */
3454 var nationalNumberRule = new RegExp(
3455 metadata.getGeneralDesc().getNationalNumberPatternOrDefault());
3456 // prefixMatcher[numOfGroups] == null implies nothing was captured by the
3457 // capturing groups in possibleNationalPrefix; therefore, no transformation
3458 // is necessary, and we just remove the national prefix.
3459 /** @type {number} */
3460 var numOfGroups = prefixMatcher.length - 1;
3461 /** @type {?string} */
3462 var transformRule = metadata.getNationalPrefixTransformRule();
3463 /** @type {string} */
3464 var transformedNumber;
3465 /** @type {boolean} */
3466 var noTransform = transformRule == null || transformRule.length == 0 ||
3467 prefixMatcher[numOfGroups] == null ||
3468 prefixMatcher[numOfGroups].length == 0;
3470 transformedNumber = numberStr.substring(prefixMatcher[0].length);
3472 transformedNumber = numberStr.replace(prefixPattern, transformRule);
3474 // If the original number was viable, and the resultant number is not,
3476 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3477 nationalNumberRule, numberStr) &&
3478 !i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3479 nationalNumberRule, transformedNumber)) {
3482 if ((noTransform && numOfGroups > 0 && prefixMatcher[1] != null) ||
3483 (!noTransform && numOfGroups > 1)) {
3484 if (carrierCode != null) {
3485 carrierCode.append(prefixMatcher[1]);
3489 number.append(transformedNumber);
3497 * Strips any extension (as in, the part of the number dialled after the call is
3498 * connected, usually indicated with extn, ext, x or similar) from the end of
3499 * the number, and returns it.
3501 * @param {!goog.string.StringBuffer} number the non-normalized telephone number
3502 * that we wish to strip the extension from.
3503 * @return {string} the phone extension.
3505 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeStripExtension =
3508 /** @type {string} */
3509 var numberStr = number.toString();
3510 /** @type {number} */
3512 numberStr.search(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
3513 // If we find a potential extension, and the number preceding this is a viable
3514 // number, we assume it is an extension.
3515 if (mStart >= 0 && i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(
3516 numberStr.substring(0, mStart))) {
3517 // The numbers are captured into groups in the regular expression.
3518 /** @type {Array.<string>} */
3520 numberStr.match(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
3521 /** @type {number} */
3522 var matchedGroupsLength = matchedGroups.length;
3523 for (var i = 1; i < matchedGroupsLength; ++i) {
3524 if (matchedGroups[i] != null && matchedGroups[i].length > 0) {
3525 // We go through the capturing groups until we find one that captured
3526 // some digits. If none did, then we will return the empty string.
3528 number.append(numberStr.substring(0, mStart));
3529 return matchedGroups[i];
3538 * Checks to see that the region code used is valid, or if it is not valid, that
3539 * the number to parse starts with a + symbol so that we can attempt to infer
3540 * the region from the number.
3541 * @param {string} numberToParse number that we are attempting to parse.
3542 * @param {?string} defaultRegion region that we are expecting the number to be
3544 * @return {boolean} false if it cannot use the region provided and the region
3545 * cannot be inferred.
3548 i18n.phonenumbers.PhoneNumberUtil.prototype.checkRegionForParsing_ = function(
3549 numberToParse, defaultRegion) {
3550 // If the number is null or empty, we can't infer the region.
3551 return this.isValidRegionCode_(defaultRegion) ||
3552 (numberToParse != null && numberToParse.length > 0 &&
3553 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_.test(
3559 * Parses a string and returns it in proto buffer format. This method will throw
3560 * a {@link i18n.phonenumbers.Error} if the number is not considered to be a
3561 * possible number. Note that validation of whether the number is actually a
3562 * valid number for a particular region is not performed. This can be done
3563 * separately with {@link #isValidNumber}.
3565 * @param {?string} numberToParse number that we are attempting to parse. This
3566 * can contain formatting such as +, ( and -, as well as a phone number
3567 * extension. It can also be provided in RFC3966 format.
3568 * @param {?string} defaultRegion region that we are expecting the number to be
3569 * from. This is only used if the number being parsed is not written in
3570 * international format. The country_code for the number in this case would
3571 * be stored as that of the default region supplied. If the number is
3572 * guaranteed to start with a '+' followed by the country calling code, then
3573 * 'ZZ' or null can be supplied.
3574 * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
3575 * with the parsed number.
3576 * @throws {i18n.phonenumbers.Error} if the string is not considered to be a
3577 * viable phone number or if no default region was supplied and the number
3578 * is not in international format (does not start with +).
3580 i18n.phonenumbers.PhoneNumberUtil.prototype.parse = function(numberToParse,
3582 return this.parseHelper_(numberToParse, defaultRegion, false, true);
3587 * Parses a string and returns it in proto buffer format. This method differs
3588 * from {@link #parse} in that it always populates the raw_input field of the
3589 * protocol buffer with numberToParse as well as the country_code_source field.
3591 * @param {string} numberToParse number that we are attempting to parse. This
3592 * can contain formatting such as +, ( and -, as well as a phone number
3594 * @param {?string} defaultRegion region that we are expecting the number to be
3595 * from. This is only used if the number being parsed is not written in
3596 * international format. The country calling code for the number in this
3597 * case would be stored as that of the default region supplied.
3598 * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
3599 * with the parsed number.
3600 * @throws {i18n.phonenumbers.Error} if the string is not considered to be a
3601 * viable phone number or if no default region was supplied.
3603 i18n.phonenumbers.PhoneNumberUtil.prototype.parseAndKeepRawInput =
3604 function(numberToParse, defaultRegion) {
3606 if (!this.isValidRegionCode_(defaultRegion)) {
3607 if (numberToParse.length > 0 && numberToParse.charAt(0) !=
3608 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) {
3609 throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
3612 return this.parseHelper_(numberToParse, defaultRegion, true, true);
3617 * Parses a string and returns it in proto buffer format. This method is the
3618 * same as the public {@link #parse} method, with the exception that it allows
3619 * the default region to be null, for use by {@link #isNumberMatch}.
3621 * @param {?string} numberToParse number that we are attempting to parse. This
3622 * can contain formatting such as +, ( and -, as well as a phone number
3624 * @param {?string} defaultRegion region that we are expecting the number to be
3625 * from. This is only used if the number being parsed is not written in
3626 * international format. The country calling code for the number in this
3627 * case would be stored as that of the default region supplied.
3628 * @param {boolean} keepRawInput whether to populate the raw_input field of the
3629 * phoneNumber with numberToParse.
3630 * @param {boolean} checkRegion should be set to false if it is permitted for
3631 * the default coregion to be null or unknown ('ZZ').
3632 * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
3633 * with the parsed number.
3634 * @throws {i18n.phonenumbers.Error}
3637 i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ =
3638 function(numberToParse, defaultRegion, keepRawInput, checkRegion) {
3640 if (numberToParse == null) {
3641 throw i18n.phonenumbers.Error.NOT_A_NUMBER;
3642 } else if (numberToParse.length >
3643 i18n.phonenumbers.PhoneNumberUtil.MAX_INPUT_STRING_LENGTH_) {
3644 throw i18n.phonenumbers.Error.TOO_LONG;
3647 /** @type {!goog.string.StringBuffer} */
3648 var nationalNumber = new goog.string.StringBuffer();
3649 this.buildNationalNumberForParsing_(numberToParse, nationalNumber);
3651 if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(
3652 nationalNumber.toString())) {
3653 throw i18n.phonenumbers.Error.NOT_A_NUMBER;
3656 // Check the region supplied is valid, or that the extracted number starts
3657 // with some sort of + sign so the number's region can be determined.
3659 !this.checkRegionForParsing_(nationalNumber.toString(), defaultRegion)) {
3660 throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
3663 /** @type {i18n.phonenumbers.PhoneNumber} */
3664 var phoneNumber = new i18n.phonenumbers.PhoneNumber();
3666 phoneNumber.setRawInput(numberToParse);
3668 // Attempt to parse extension first, since it doesn't require region-specific
3669 // data and we want to have the non-normalised number here.
3670 /** @type {string} */
3671 var extension = this.maybeStripExtension(nationalNumber);
3672 if (extension.length > 0) {
3673 phoneNumber.setExtension(extension);
3676 /** @type {i18n.phonenumbers.PhoneMetadata} */
3677 var regionMetadata = this.getMetadataForRegion(defaultRegion);
3678 // Check to see if the number is given in international format so we know
3679 // whether this number is from the default region or not.
3680 /** @type {!goog.string.StringBuffer} */
3681 var normalizedNationalNumber = new goog.string.StringBuffer();
3682 /** @type {number} */
3683 var countryCode = 0;
3684 /** @type {string} */
3685 var nationalNumberStr = nationalNumber.toString();
3687 countryCode = this.maybeExtractCountryCode(nationalNumberStr,
3688 regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber);
3690 if (e == i18n.phonenumbers.Error.INVALID_COUNTRY_CODE &&
3691 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_
3692 .test(nationalNumberStr)) {
3693 // Strip the plus-char, and try again.
3694 nationalNumberStr = nationalNumberStr.replace(
3695 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_, '');
3696 countryCode = this.maybeExtractCountryCode(nationalNumberStr,
3697 regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber);
3698 if (countryCode == 0) {
3705 if (countryCode != 0) {
3706 /** @type {string} */
3707 var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCode);
3708 if (phoneNumberRegion != defaultRegion) {
3709 // Metadata cannot be null because the country calling code is valid.
3710 regionMetadata = this.getMetadataForRegionOrCallingCode_(
3711 countryCode, phoneNumberRegion);
3714 // If no extracted country calling code, use the region supplied instead.
3715 // The national number is just the normalized version of the number we were
3717 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(nationalNumber);
3718 normalizedNationalNumber.append(nationalNumber.toString());
3719 if (defaultRegion != null) {
3720 countryCode = regionMetadata.getCountryCodeOrDefault();
3721 phoneNumber.setCountryCode(countryCode);
3722 } else if (keepRawInput) {
3723 phoneNumber.clearCountryCodeSource();
3726 if (normalizedNationalNumber.getLength() <
3727 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3728 throw i18n.phonenumbers.Error.TOO_SHORT_NSN;
3731 if (regionMetadata != null) {
3732 /** @type {goog.string.StringBuffer} */
3733 var carrierCode = new goog.string.StringBuffer();
3734 this.maybeStripNationalPrefixAndCarrierCode(
3735 normalizedNationalNumber, regionMetadata, carrierCode);
3737 phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString());
3740 /** @type {string} */
3741 var normalizedNationalNumberStr = normalizedNationalNumber.toString();
3742 /** @type {number} */
3743 var lengthOfNationalNumber = normalizedNationalNumberStr.length;
3744 if (lengthOfNationalNumber <
3745 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3746 throw i18n.phonenumbers.Error.TOO_SHORT_NSN;
3748 if (lengthOfNationalNumber >
3749 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_) {
3750 throw i18n.phonenumbers.Error.TOO_LONG;
3752 if (normalizedNationalNumberStr.charAt(0) == '0') {
3753 phoneNumber.setItalianLeadingZero(true);
3755 phoneNumber.setNationalNumber(parseInt(normalizedNationalNumberStr, 10));
3761 * Converts numberToParse to a form that we can parse and write it to
3762 * nationalNumber if it is written in RFC3966; otherwise extract a possible
3763 * number out of it and write to nationalNumber.
3765 * @param {?string} numberToParse number that we are attempting to parse. This
3766 * can contain formatting such as +, ( and -, as well as a phone number
3768 * @param {!goog.string.StringBuffer} nationalNumber a string buffer for storing
3769 * the national significant number.
3772 i18n.phonenumbers.PhoneNumberUtil.prototype.buildNationalNumberForParsing_ =
3773 function(numberToParse, nationalNumber) {
3775 /** @type {number} */
3776 var indexOfPhoneContext = numberToParse.indexOf(
3777 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_);
3778 if (indexOfPhoneContext > 0) {
3779 var phoneContextStart = indexOfPhoneContext +
3780 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_.length;
3781 // If the phone context contains a phone number prefix, we need to capture
3782 // it, whereas domains will be ignored.
3783 if (numberToParse.charAt(phoneContextStart) ==
3784 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) {
3785 // Additional parameters might follow the phone context. If so, we will
3786 // remove them here because the parameters after phone context are not
3787 // important for parsing the phone number.
3788 var phoneContextEnd = numberToParse.indexOf(';', phoneContextStart);
3789 if (phoneContextEnd > 0) {
3790 nationalNumber.append(numberToParse.substring(phoneContextStart,
3793 nationalNumber.append(numberToParse.substring(phoneContextStart));
3797 // Now append everything between the "tel:" prefix and the phone-context.
3798 // This should include the national number, an optional extension or
3799 // isdn-subaddress component.
3800 nationalNumber.append(numberToParse.substring(
3801 numberToParse.indexOf(
3802 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_) +
3803 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_.length,
3804 indexOfPhoneContext));
3806 // Extract a possible number from the string passed in (this strips leading
3807 // characters that could not be the start of a phone number.)
3808 nationalNumber.append(
3809 i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber(numberToParse));
3812 // Delete the isdn-subaddress and everything after it if it is present.
3813 // Note extension won't appear at the same time with isdn-subaddress
3814 // according to paragraph 5.3 of the RFC3966 spec,
3815 /** @type {string} */
3816 var nationalNumberStr = nationalNumber.toString();
3817 var indexOfIsdn = nationalNumberStr.indexOf(
3818 i18n.phonenumbers.PhoneNumberUtil.RFC3966_ISDN_SUBADDRESS_);
3819 if (indexOfIsdn > 0) {
3820 nationalNumber.clear();
3821 nationalNumber.append(nationalNumberStr.substring(0, indexOfIsdn));
3823 // If both phone context and isdn-subaddress are absent but other
3824 // parameters are present, the parameters are left in nationalNumber. This
3825 // is because we are concerned about deleting content from a potential
3826 // number string when there is no strong evidence that the number is
3827 // actually written in RFC3966.
3832 * Takes two phone numbers and compares them for equality.
3834 * <p>Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero
3835 * for Italian numbers and any extension present are the same. Returns NSN_MATCH
3836 * if either or both has no region specified, and the NSNs and extensions are
3837 * the same. Returns SHORT_NSN_MATCH if either or both has no region specified,
3838 * or the region specified is the same, and one NSN could be a shorter version
3839 * of the other number. This includes the case where one has an extension
3840 * specified, and the other does not. Returns NO_MATCH otherwise. For example,
3841 * the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH. The numbers
3842 * +1 345 657 1234 and 345 657 are a NO_MATCH.
3844 * @param {i18n.phonenumbers.PhoneNumber|string} firstNumberIn first number to
3845 * compare. If it is a string it can contain formatting, and can have
3846 * country calling code specified with + at the start.
3847 * @param {i18n.phonenumbers.PhoneNumber|string} secondNumberIn second number to
3848 * compare. If it is a string it can contain formatting, and can have
3849 * country calling code specified with + at the start.
3850 * @return {i18n.phonenumbers.PhoneNumberUtil.MatchType} NOT_A_NUMBER, NO_MATCH,
3851 * SHORT_NSN_MATCH, NSN_MATCH or EXACT_MATCH depending on the level of
3852 * equality of the two numbers, described in the method definition.
3854 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch =
3855 function(firstNumberIn, secondNumberIn) {
3857 // If the input arguements are strings parse them to a proto buffer format.
3858 // Else make copies of the phone numbers so that the numbers passed in are not
3860 /** @type {i18n.phonenumbers.PhoneNumber} */
3862 /** @type {i18n.phonenumbers.PhoneNumber} */
3864 if (typeof firstNumberIn == 'string') {
3865 // First see if the first number has an implicit country calling code, by
3866 // attempting to parse it.
3868 firstNumber = this.parse(
3869 firstNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
3871 if (e != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
3872 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3874 // The first number has no country calling code. EXACT_MATCH is no longer
3875 // possible. We parse it as if the region was the same as that for the
3876 // second number, and if EXACT_MATCH is returned, we replace this with
3878 if (typeof secondNumberIn != 'string') {
3879 /** @type {string} */
3880 var secondNumberRegion = this.getRegionCodeForCountryCode(
3881 secondNumberIn.getCountryCodeOrDefault());
3882 if (secondNumberRegion !=
3883 i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_) {
3885 firstNumber = this.parse(firstNumberIn, secondNumberRegion);
3887 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3889 /** @type {i18n.phonenumbers.PhoneNumberUtil.MatchType} */
3890 var match = this.isNumberMatch(firstNumber, secondNumberIn);
3892 i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH) {
3893 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
3898 // If the second number is a string or doesn't have a valid country
3899 // calling code, we parse the first number without country calling code.
3901 firstNumber = this.parseHelper_(firstNumberIn, null, false, false);
3903 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3907 firstNumber = firstNumberIn.clone();
3909 if (typeof secondNumberIn == 'string') {
3911 secondNumber = this.parse(
3912 secondNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
3913 return this.isNumberMatch(firstNumberIn, secondNumber);
3915 if (e != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
3916 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3918 return this.isNumberMatch(secondNumberIn, firstNumber);
3921 secondNumber = secondNumberIn.clone();
3923 // First clear raw_input, country_code_source and
3924 // preferred_domestic_carrier_code fields and any empty-string extensions so
3925 // that we can use the proto-buffer equality method.
3926 firstNumber.clearRawInput();
3927 firstNumber.clearCountryCodeSource();
3928 firstNumber.clearPreferredDomesticCarrierCode();
3929 secondNumber.clearRawInput();
3930 secondNumber.clearCountryCodeSource();
3931 secondNumber.clearPreferredDomesticCarrierCode();
3932 if (firstNumber.hasExtension() && firstNumber.getExtension().length == 0) {
3933 firstNumber.clearExtension();
3935 if (secondNumber.hasExtension() && secondNumber.getExtension().length == 0) {
3936 secondNumber.clearExtension();
3939 // Early exit if both had extensions and these are different.
3940 if (firstNumber.hasExtension() && secondNumber.hasExtension() &&
3941 firstNumber.getExtension() != secondNumber.getExtension()) {
3942 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
3944 /** @type {number} */
3945 var firstNumberCountryCode = firstNumber.getCountryCodeOrDefault();
3946 /** @type {number} */
3947 var secondNumberCountryCode = secondNumber.getCountryCodeOrDefault();
3948 // Both had country_code specified.
3949 if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) {
3950 if (firstNumber.equals(secondNumber)) {
3951 return i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH;
3952 } else if (firstNumberCountryCode == secondNumberCountryCode &&
3953 this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
3954 // A SHORT_NSN_MATCH occurs if there is a difference because of the
3955 // presence or absence of an 'Italian leading zero', the presence or
3956 // absence of an extension, or one NSN being a shorter variant of the
3958 return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
3960 // This is not a match.
3961 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
3963 // Checks cases where one or both country_code fields were not specified. To
3964 // make equality checks easier, we first set the country_code fields to be
3966 firstNumber.setCountryCode(0);
3967 secondNumber.setCountryCode(0);
3968 // If all else was the same, then this is an NSN_MATCH.
3969 if (firstNumber.equals(secondNumber)) {
3970 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
3972 if (this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
3973 return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
3975 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
3980 * Returns true when one national number is the suffix of the other or both are
3983 * @param {i18n.phonenumbers.PhoneNumber} firstNumber the first PhoneNumber
3985 * @param {i18n.phonenumbers.PhoneNumber} secondNumber the second PhoneNumber
3987 * @return {boolean} true if one PhoneNumber is the suffix of the other one.
3990 i18n.phonenumbers.PhoneNumberUtil.prototype.isNationalNumberSuffixOfTheOther_ =
3991 function(firstNumber, secondNumber) {
3993 /** @type {string} */
3994 var firstNumberNationalNumber = '' + firstNumber.getNationalNumber();
3995 /** @type {string} */
3996 var secondNumberNationalNumber = '' + secondNumber.getNationalNumber();
3997 // Note that endsWith returns true if the numbers are equal.
3998 return goog.string.endsWith(firstNumberNationalNumber,
3999 secondNumberNationalNumber) ||
4000 goog.string.endsWith(secondNumberNationalNumber,
4001 firstNumberNationalNumber);
4006 * Returns true if the number can be dialled from outside the region, or
4007 * unknown. If the number can only be dialled from within the region, returns
4008 * false. Does not check the number is a valid number.
4009 * TODO: Make this method public when we have enough metadata to make it
4010 * worthwhile. Currently visible for testing purposes only.
4012 * @param {i18n.phonenumbers.PhoneNumber} number the phone-number for which we
4013 * want to know whether it is diallable from outside the region.
4014 * @return {boolean} true if the number can only be dialled from within the
4017 i18n.phonenumbers.PhoneNumberUtil.prototype.canBeInternationallyDialled =
4019 /** @type {i18n.phonenumbers.PhoneMetadata} */
4020 var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
4021 if (metadata == null) {
4022 // Note numbers belonging to non-geographical entities (e.g. +800 numbers)
4023 // are always internationally diallable, and will be caught here.
4026 /** @type {string} */
4027 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
4028 return !this.isNumberMatchingDesc_(nationalSignificantNumber,
4029 metadata.getNoInternationalDialling());
4034 * Check whether the entire input sequence can be matched against the regular
4037 * @param {!RegExp|string} regex the regular expression to match against.
4038 * @param {string} str the string to test.
4039 * @return {boolean} true if str can be matched entirely against regex.
4042 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_ = function(regex, str) {
4043 /** @type {Array.<string>} */
4044 var matchedGroups = (typeof regex == 'string') ?
4045 str.match('^(?:' + regex + ')$') : str.match(regex);
4046 if (matchedGroups && matchedGroups[0].length == str.length) {