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_ = 17;
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 * Map of country calling codes that use a mobile token before the area code.
164 * One example of when this is relevant is when determining the length of the
165 * national destination code, which should be the length of the area code plus
166 * the length of the mobile token.
169 * @type {!Object.<number, string>}
172 i18n.phonenumbers.PhoneNumberUtil.MOBILE_TOKEN_MAPPINGS_ = {
179 * The PLUS_SIGN signifies the international prefix.
184 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN = '+';
192 i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ = '*';
196 * The RFC 3966 format for extensions.
202 i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ = ';ext=';
210 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_ = 'tel:';
218 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_ = ';phone-context=';
226 i18n.phonenumbers.PhoneNumberUtil.RFC3966_ISDN_SUBADDRESS_ = ';isub=';
230 * These mappings map a character (key) to a specific digit that should replace
231 * it for normalization purposes. Non-European digits that may be used in phone
232 * numbers are mapped to a European equivalent.
235 * @type {!Object.<string, string>}
237 i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS = {
248 '\uFF10': '0', // Fullwidth digit 0
249 '\uFF11': '1', // Fullwidth digit 1
250 '\uFF12': '2', // Fullwidth digit 2
251 '\uFF13': '3', // Fullwidth digit 3
252 '\uFF14': '4', // Fullwidth digit 4
253 '\uFF15': '5', // Fullwidth digit 5
254 '\uFF16': '6', // Fullwidth digit 6
255 '\uFF17': '7', // Fullwidth digit 7
256 '\uFF18': '8', // Fullwidth digit 8
257 '\uFF19': '9', // Fullwidth digit 9
258 '\u0660': '0', // Arabic-indic digit 0
259 '\u0661': '1', // Arabic-indic digit 1
260 '\u0662': '2', // Arabic-indic digit 2
261 '\u0663': '3', // Arabic-indic digit 3
262 '\u0664': '4', // Arabic-indic digit 4
263 '\u0665': '5', // Arabic-indic digit 5
264 '\u0666': '6', // Arabic-indic digit 6
265 '\u0667': '7', // Arabic-indic digit 7
266 '\u0668': '8', // Arabic-indic digit 8
267 '\u0669': '9', // Arabic-indic digit 9
268 '\u06F0': '0', // Eastern-Arabic digit 0
269 '\u06F1': '1', // Eastern-Arabic digit 1
270 '\u06F2': '2', // Eastern-Arabic digit 2
271 '\u06F3': '3', // Eastern-Arabic digit 3
272 '\u06F4': '4', // Eastern-Arabic digit 4
273 '\u06F5': '5', // Eastern-Arabic digit 5
274 '\u06F6': '6', // Eastern-Arabic digit 6
275 '\u06F7': '7', // Eastern-Arabic digit 7
276 '\u06F8': '8', // Eastern-Arabic digit 8
277 '\u06F9': '9' // Eastern-Arabic digit 9
282 * A map that contains characters that are essential when dialling. That means
283 * any of the characters in this map must not be removed from a number when
284 * dialling, otherwise the call will not reach the intended destination.
287 * @type {!Object.<string, string>}
290 i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_ = {
301 '+': i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN,
307 * Only upper-case variants of alpha characters are stored.
310 * @type {!Object.<string, string>}
313 i18n.phonenumbers.PhoneNumberUtil.ALPHA_MAPPINGS_ = {
344 * For performance reasons, amalgamate both into one map.
347 * @type {!Object.<string, string>}
350 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_ = {
361 '\uFF10': '0', // Fullwidth digit 0
362 '\uFF11': '1', // Fullwidth digit 1
363 '\uFF12': '2', // Fullwidth digit 2
364 '\uFF13': '3', // Fullwidth digit 3
365 '\uFF14': '4', // Fullwidth digit 4
366 '\uFF15': '5', // Fullwidth digit 5
367 '\uFF16': '6', // Fullwidth digit 6
368 '\uFF17': '7', // Fullwidth digit 7
369 '\uFF18': '8', // Fullwidth digit 8
370 '\uFF19': '9', // Fullwidth digit 9
371 '\u0660': '0', // Arabic-indic digit 0
372 '\u0661': '1', // Arabic-indic digit 1
373 '\u0662': '2', // Arabic-indic digit 2
374 '\u0663': '3', // Arabic-indic digit 3
375 '\u0664': '4', // Arabic-indic digit 4
376 '\u0665': '5', // Arabic-indic digit 5
377 '\u0666': '6', // Arabic-indic digit 6
378 '\u0667': '7', // Arabic-indic digit 7
379 '\u0668': '8', // Arabic-indic digit 8
380 '\u0669': '9', // Arabic-indic digit 9
381 '\u06F0': '0', // Eastern-Arabic digit 0
382 '\u06F1': '1', // Eastern-Arabic digit 1
383 '\u06F2': '2', // Eastern-Arabic digit 2
384 '\u06F3': '3', // Eastern-Arabic digit 3
385 '\u06F4': '4', // Eastern-Arabic digit 4
386 '\u06F5': '5', // Eastern-Arabic digit 5
387 '\u06F6': '6', // Eastern-Arabic digit 6
388 '\u06F7': '7', // Eastern-Arabic digit 7
389 '\u06F8': '8', // Eastern-Arabic digit 8
390 '\u06F9': '9', // Eastern-Arabic digit 9
421 * Separate map of all symbols that we wish to retain when formatting alpha
422 * numbers. This includes digits, ASCII letters and number grouping symbols such
426 * @type {!Object.<string, string>}
429 i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_ = {
512 * Pattern that makes it easy to distinguish whether a region has a unique
513 * international dialing prefix or not. If a region has a unique international
514 * prefix (e.g. 011 in USA), it will be represented as a string that contains a
515 * sequence of ASCII digits. If there are multiple available international
516 * prefixes in a region, they will be represented as a regex string that always
517 * contains character(s) other than ASCII digits. Note this regex also includes
518 * tilde, which signals waiting for the tone.
524 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_ =
525 /[\d]+(?:[~\u2053\u223C\uFF5E][\d]+)?/;
529 * Regular expression of acceptable punctuation found in phone numbers. This
530 * excludes punctuation found as a leading character only. This consists of dash
531 * characters, white space characters, full stops, slashes, square brackets,
532 * parentheses and tildes. It also includes the letter 'x' as that is found as a
533 * placeholder for carrier information in some phone numbers. Full-width
534 * variants are also present.
539 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION =
540 '-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F \u00A0\u00AD\u200B\u2060\u3000' +
541 '()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E';
545 * Digits accepted in phone numbers (ascii, fullwidth, arabic-indic, and eastern
552 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ =
553 '0-9\uFF10-\uFF19\u0660-\u0669\u06F0-\u06F9';
557 * We accept alpha characters in phone numbers, ASCII only, upper and lower
564 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ = 'A-Za-z';
572 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ = '+\uFF0B';
579 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN =
580 new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']+');
588 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_ =
589 new RegExp('^[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']+');
597 i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_ =
598 '[' + i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION + ']+';
605 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN =
606 new RegExp('([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + '])');
610 * Regular expression of acceptable characters that may start a phone number for
611 * the purposes of parsing. This allows us to strip away meaningless prefixes to
612 * phone numbers that may be mistakenly given to us. This consists of digits,
613 * the plus symbol and arabic-indic digits. This does not contain alpha
614 * characters, although they may be used later in the number. It also does not
615 * include other punctuation, as this will be stripped later during parsing and
616 * is of no information value when parsing a number.
622 i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN_ =
623 new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ +
624 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']');
628 * Regular expression of characters typically used to start a second phone
629 * number for the purposes of parsing. This allows us to strip off parts of the
630 * number that are actually the start of another number, such as for:
631 * (530) 583-6985 x302/x2303 -> the second extension here makes this actually
632 * two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove
633 * the second extension so that the first number is parsed correctly.
639 i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_ = /[\\\/] *x/;
643 * Regular expression of trailing characters that we want to remove. We remove
644 * all characters that are not alpha or numerical characters. The hash character
645 * is retained here, as it may signify the previous block was an extension.
651 i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_ =
652 new RegExp('[^' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ +
653 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ + '#]+$');
657 * We use this pattern to check if the phone number has at least three letters
658 * in it - if so, then we treat it as a number where some phone-number digits
659 * are represented by letters.
665 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_ =
666 /(?:.*?[A-Za-z]){3}.*/;
670 * Regular expression of viable phone numbers. This is location independent.
671 * Checks we have at least three leading digits, and only valid punctuation,
672 * alpha characters and digits in the phone number. Does not include extension
673 * data. The symbol 'x' is allowed here as valid punctuation since it is often
674 * used as a placeholder for carrier codes, for example in Brazilian phone
675 * numbers. We also allow multiple '+' characters at the start.
676 * Corresponds to the following:
677 * [digits]{minLengthNsn}|
679 * (([punctuation]|[star])*[digits]){3,}([punctuation]|[star]|[digits]|[alpha])*
681 * The first reg-ex is to allow short numbers (two digits long) to be parsed if
682 * they are entered as "15" etc, but only if there is no punctuation in them.
683 * The second expression restricts the number of digits to three or more, but
684 * then allows them to be in international form, and to have alpha-characters
685 * and punctuation. We split up the two reg-exes here and combine them when
686 * creating the reg-ex VALID_PHONE_NUMBER_PATTERN_ itself so we can prefix it
687 * with ^ and append $ to each branch.
689 * Note VALID_PUNCTUATION starts with a -, so must be the first in the range.
695 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_PHONE_NUMBER_PATTERN_ =
696 '[' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{' +
697 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ + '}';
701 * See MIN_LENGTH_PHONE_NUMBER_PATTERN_ for a full description of this reg-exp.
707 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ =
708 '[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']*(?:[' +
709 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
710 i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ + ']*[' +
711 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']){3,}[' +
712 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
713 i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ +
714 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ +
715 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']*';
719 * Default extension prefix to use when formatting. This will be put in front of
720 * any extension component of the number, after the main national number is
721 * formatted. For example, if you wish the default extension formatting to be
722 * ' extn: 3456', then you should specify ' extn: ' here as the default
723 * extension prefix. This can be overridden by region-specific preferences.
729 i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ = ' ext. ';
733 * Pattern to capture digits used in an extension.
734 * Places a maximum length of '7' for an extension.
740 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ =
741 '([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,7})';
745 * Regexp of all possible ways to write extensions, for use when parsing. This
746 * will be run as a case-insensitive regexp match. Wide character versions are
747 * also provided after each ASCII version. There are three regular expressions
748 * here. The first covers RFC 3966 format, where the extension is added using
749 * ';ext='. The second more generic one starts with optional white space and
750 * ends with an optional full stop (.), followed by zero or more spaces/tabs and
751 * then the numbers themselves. The other one covers the special case of
752 * American numbers where the extension is written with a hash at the end, such
753 * as '- 503#'. Note that the only capturing groups should be around the digits
754 * that you want to capture as part of the extension, or else parsing will fail!
755 * We allow two options for representing the accented o - the character itself,
756 * and one in the unicode decomposed form with the combining acute accent.
762 i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ =
763 i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
764 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '|' +
766 '(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|' +
767 '[,x\uFF58#\uFF03~\uFF5E]|int|anexo|\uFF49\uFF4E\uFF54)' +
768 '[:\\.\uFF0E]?[ \u00A0\\t,-]*' +
769 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '#?|' +
770 '[- ]+([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,5})#';
774 * Regexp of all known extension prefixes used by different regions followed by
775 * 1 or more valid digits, for use when parsing.
781 i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_ =
783 i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ +
788 * We append optionally the extension pattern to the end here, as a valid phone
789 * number may have an extension prefix appended, followed by 1 or more digits.
795 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_ =
798 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_PHONE_NUMBER_PATTERN_ +
800 '^' + i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ +
801 '(?:' + i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ +
810 i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_ = /\D+/;
814 * This was originally set to $1 but there are some countries for which the
815 * first group is not used in the national pattern (e.g. Argentina) so the $1
816 * group does not match correctly. Therefore, we use \d, so that the first
817 * group actually used in the pattern will be matched.
822 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_ = /(\$\d)/;
830 i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_ = /\$NP/;
838 i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_ = /\$FG/;
846 i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_ = /\$CC/;
850 * A pattern that is used to determine if the national prefix formatting rule
851 * has the first group only, i.e., does not start with the national prefix.
852 * Note that the pattern explicitly allows for unbalanced parentheses.
857 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_ONLY_PREFIX_PATTERN_ =
865 i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY = '001';
869 * INTERNATIONAL and NATIONAL formats are consistent with the definition in
870 * ITU-T Recommendation E123. For example, the number of the Google Switzerland
871 * office will be written as '+41 44 668 1800' in INTERNATIONAL format, and as
872 * '044 668 1800' in NATIONAL format. E164 format is as per INTERNATIONAL format
873 * but with no formatting applied, e.g. '+41446681800'. RFC3966 is as per
874 * INTERNATIONAL format, but with all spaces and other separating symbols
875 * replaced with a hyphen, and with any phone number extension appended with
876 * ';ext='. It also will have a prefix of 'tel:' added, e.g.
877 * 'tel:+41-44-668-1800'.
879 * Note: If you are considering storing the number in a neutral format, you are
880 * highly advised to use the PhoneNumber class.
883 i18n.phonenumbers.PhoneNumberFormat = {
892 * Type of phone numbers.
896 i18n.phonenumbers.PhoneNumberType = {
899 // In some regions (e.g. the USA), it is impossible to distinguish between
900 // fixed-line and mobile numbers by looking at the phone number itself.
901 FIXED_LINE_OR_MOBILE: 2,
905 // The cost of this call is shared between the caller and the recipient, and
906 // is hence typically less than PREMIUM_RATE calls. See
907 // http://en.wikipedia.org/wiki/Shared_Cost_Service for more information.
909 // Voice over IP numbers. This includes TSoIP (Telephony Service over IP).
911 // A personal number is associated with a particular person, and may be routed
912 // to either a MOBILE or FIXED_LINE number. Some more information can be found
913 // here: http://en.wikipedia.org/wiki/Personal_Numbers
916 // Used for 'Universal Access Numbers' or 'Company Numbers'. They may be
917 // further routed to specific offices, but allow one number to be used for a
920 // Used for 'Voice Mail Access Numbers'.
922 // A phone number is of type UNKNOWN when it does not fit any of the known
923 // patterns for a specific region.
929 * Types of phone number matches. See detailed description beside the
930 * isNumberMatch() method.
934 i18n.phonenumbers.PhoneNumberUtil.MatchType = {
944 * Possible outcomes when testing if a PhoneNumber is possible.
948 i18n.phonenumbers.PhoneNumberUtil.ValidationResult = {
950 INVALID_COUNTRY_CODE: 1,
957 * Attempts to extract a possible number from the string passed in. This
958 * currently strips all leading characters that cannot be used to start a phone
959 * number. Characters that can be used to start a phone number are defined in
960 * the VALID_START_CHAR_PATTERN. If none of these characters are found in the
961 * number passed in, an empty string is returned. This function also attempts to
962 * strip off any alternative extensions or endings if two or more are present,
963 * such as in the case of: (530) 583-6985 x302/x2303. The second extension here
964 * makes this actually two phone numbers, (530) 583-6985 x302 and (530) 583-6985
965 * x2303. We remove the second extension so that the first number is parsed
968 * @param {string} number the string that might contain a phone number.
969 * @return {string} the number, stripped of any non-phone-number prefix (such as
970 * 'Tel:') or an empty string if no character used to start phone numbers
971 * (such as + or any digit) is found in the number.
973 i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber = function(number) {
974 /** @type {string} */
977 /** @type {number} */
979 .search(i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN_);
981 possibleNumber = number.substring(start);
982 // Remove trailing non-alpha non-numerical characters.
983 possibleNumber = possibleNumber.replace(
984 i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_, '');
986 // Check for extra numbers at the end.
987 /** @type {number} */
988 var secondNumberStart = possibleNumber
989 .search(i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_);
990 if (secondNumberStart >= 0) {
991 possibleNumber = possibleNumber.substring(0, secondNumberStart);
996 return possibleNumber;
1001 * Checks to see if the string of characters could possibly be a phone number at
1002 * all. At the moment, checks to see that the string begins with at least 2
1003 * digits, ignoring any punctuation commonly found in phone numbers. This method
1004 * does not require the number to be normalized in advance - but does assume
1005 * that leading non-number symbols have been removed, such as by the method
1006 * extractPossibleNumber.
1008 * @param {string} number string to be checked for viability as a phone number.
1009 * @return {boolean} true if the number could be a phone number of some sort,
1012 i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber = function(number) {
1013 if (number.length < i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
1016 return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1017 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_, number);
1022 * Normalizes a string of characters representing a phone number. This performs
1023 * the following conversions:
1024 * Punctuation is stripped.
1025 * For ALPHA/VANITY numbers:
1026 * Letters are converted to their numeric representation on a telephone
1027 * keypad. The keypad used here is the one defined in ITU Recommendation
1028 * E.161. This is only done if there are 3 or more letters in the number,
1029 * to lessen the risk that such letters are typos.
1030 * For other numbers:
1031 * Wide-ascii digits are converted to normal ASCII (European) digits.
1032 * Arabic-Indic numerals are converted to European numerals.
1033 * Spurious alpha characters are stripped.
1035 * @param {string} number a string of characters representing a phone number.
1036 * @return {string} the normalized string version of the phone number.
1038 i18n.phonenumbers.PhoneNumberUtil.normalize = function(number) {
1039 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1040 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_, number)) {
1041 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
1042 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, true);
1044 return i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(number);
1050 * Normalizes a string of characters representing a phone number. This is a
1051 * wrapper for normalize(String number) but does in-place normalization of the
1052 * StringBuffer provided.
1054 * @param {!goog.string.StringBuffer} number a StringBuffer of characters
1055 * representing a phone number that will be normalized in place.
1058 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_ = function(number) {
1059 /** @type {string} */
1060 var normalizedNumber = i18n.phonenumbers.PhoneNumberUtil.normalize(number
1063 number.append(normalizedNumber);
1068 * Normalizes a string of characters representing a phone number. This converts
1069 * wide-ascii and arabic-indic numerals to European numerals, and strips
1070 * punctuation and alpha characters.
1072 * @param {string} number a string of characters representing a phone number.
1073 * @return {string} the normalized string version of the phone number.
1075 i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly = function(number) {
1076 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
1077 i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS, true);
1082 * Converts all alpha characters in a number to their respective digits on a
1083 * keypad, but retains existing formatting. Also converts wide-ascii digits to
1084 * normal ascii digits, and converts Arabic-Indic numerals to European numerals.
1086 * @param {string} number a string of characters representing a phone number.
1087 * @return {string} the normalized string version of the phone number.
1089 i18n.phonenumbers.PhoneNumberUtil.convertAlphaCharactersInNumber =
1092 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
1093 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, false);
1098 * Gets the length of the geographical area code from the
1099 * {@code national_number} field of the PhoneNumber object passed in, so that
1100 * clients could use it to split a national significant number into geographical
1101 * area code and subscriber number. It works in such a way that the resultant
1102 * subscriber number should be diallable, at least on some devices. An example
1103 * of how this could be used:
1106 * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
1107 * var number = phoneUtil.parse('16502530000', 'US');
1108 * var nationalSignificantNumber =
1109 * phoneUtil.getNationalSignificantNumber(number);
1111 * var subscriberNumber;
1113 * var areaCodeLength = phoneUtil.getLengthOfGeographicalAreaCode(number);
1114 * if (areaCodeLength > 0) {
1115 * areaCode = nationalSignificantNumber.substring(0, areaCodeLength);
1116 * subscriberNumber = nationalSignificantNumber.substring(areaCodeLength);
1119 * subscriberNumber = nationalSignificantNumber;
1123 * N.B.: area code is a very ambiguous concept, so the I18N team generally
1124 * recommends against using it for most purposes, but recommends using the more
1125 * general {@code national_number} instead. Read the following carefully before
1126 * deciding to use this method:
1128 * <li> geographical area codes change over time, and this method honors those
1129 * changes; therefore, it doesn't guarantee the stability of the result it
1131 * <li> subscriber numbers may not be diallable from all devices (notably
1132 * mobile devices, which typically requires the full national_number to be
1133 * dialled in most regions).
1134 * <li> most non-geographical numbers have no area codes, including numbers
1135 * from non-geographical entities.
1136 * <li> some geographical numbers have no area codes.
1139 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
1140 * which clients want to know the length of the area code.
1141 * @return {number} the length of area code of the PhoneNumber object passed in.
1143 i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfGeographicalAreaCode =
1145 /** @type {i18n.phonenumbers.PhoneMetadata} */
1146 var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
1147 if (metadata == null) {
1150 // If a country doesn't use a national prefix, and this number doesn't have
1151 // an Italian leading zero, we assume it is a closed dialling plan with no
1153 if (!metadata.hasNationalPrefix() && !number.hasItalianLeadingZero()) {
1157 if (!this.isNumberGeographical(number)) {
1161 return this.getLengthOfNationalDestinationCode(number);
1166 * Gets the length of the national destination code (NDC) from the PhoneNumber
1167 * object passed in, so that clients could use it to split a national
1168 * significant number into NDC and subscriber number. The NDC of a phone number
1169 * is normally the first group of digit(s) right after the country calling code
1170 * when the number is formatted in the international format, if there is a
1171 * subscriber number part that follows. An example of how this could be used:
1174 * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
1175 * var number = phoneUtil.parse('18002530000', 'US');
1176 * var nationalSignificantNumber =
1177 * phoneUtil.getNationalSignificantNumber(number);
1178 * var nationalDestinationCode;
1179 * var subscriberNumber;
1181 * var nationalDestinationCodeLength =
1182 * phoneUtil.getLengthOfNationalDestinationCode(number);
1183 * if (nationalDestinationCodeLength > 0) {
1184 * nationalDestinationCode =
1185 * nationalSignificantNumber.substring(0, nationalDestinationCodeLength);
1186 * subscriberNumber =
1187 * nationalSignificantNumber.substring(nationalDestinationCodeLength);
1189 * nationalDestinationCode = '';
1190 * subscriberNumber = nationalSignificantNumber;
1194 * Refer to the unittests to see the difference between this function and
1195 * {@link #getLengthOfGeographicalAreaCode}.
1197 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
1198 * which clients want to know the length of the NDC.
1199 * @return {number} the length of NDC of the PhoneNumber object passed in.
1201 i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfNationalDestinationCode =
1204 /** @type {i18n.phonenumbers.PhoneNumber} */
1206 if (number.hasExtension()) {
1207 // We don't want to alter the proto given to us, but we don't want to
1208 // include the extension when we format it, so we copy it and clear the
1210 copiedProto = number.clone();
1211 copiedProto.clearExtension();
1213 copiedProto = number;
1216 /** @type {string} */
1217 var nationalSignificantNumber = this.format(copiedProto,
1218 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1219 /** @type {!Array.<string>} */
1220 var numberGroups = nationalSignificantNumber.split(
1221 i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_);
1222 // The pattern will start with '+COUNTRY_CODE ' so the first group will always
1223 // be the empty string (before the + symbol) and the second group will be the
1224 // country calling code. The third group will be area code if it is not the
1226 // NOTE: On IE the first group that is supposed to be the empty string does
1227 // not appear in the array of number groups... so make the result on non-IE
1228 // browsers to be that of IE.
1229 if (numberGroups[0].length == 0) {
1230 numberGroups.shift();
1232 if (numberGroups.length <= 2) {
1236 if (this.getNumberType(number) == i18n.phonenumbers.PhoneNumberType.MOBILE) {
1237 // For example Argentinian mobile numbers, when formatted in the
1238 // international format, are in the form of +54 9 NDC XXXX.... As a result,
1239 // we take the length of the third group (NDC) and add the length of the
1240 // mobile token, which also forms part of the national significant number.
1241 // This assumes that the mobile token is always formatted separately from
1242 // the rest of the phone number.
1243 /** @type {string} */
1244 var mobileToken = i18n.phonenumbers.PhoneNumberUtil.getCountryMobileToken(
1245 number.getCountryCodeOrDefault());
1246 if (mobileToken != '') {
1247 return numberGroups[2].length + mobileToken.length;
1250 return numberGroups[1].length;
1255 * Returns the mobile token for the provided country calling code if it has
1256 * one, otherwise returns an empty string. A mobile token is a number inserted
1257 * before the area code when dialing a mobile number from that country from
1260 * @param {number} countryCallingCode the country calling code for which we
1261 * want the mobile token.
1262 * @return {string} the mobile token for the given country calling code.
1264 i18n.phonenumbers.PhoneNumberUtil.getCountryMobileToken =
1265 function(countryCallingCode) {
1266 return i18n.phonenumbers.PhoneNumberUtil.MOBILE_TOKEN_MAPPINGS_[
1267 countryCallingCode] || '';
1272 * Convenience method to get a list of what regions the library has metadata
1275 * @return {!Array<string>} region codes supported by the library.
1277 i18n.phonenumbers.PhoneNumberUtil.prototype.getSupportedRegions = function() {
1278 return goog.array.filter(
1279 Object.keys(i18n.phonenumbers.metadata.countryToMetadata),
1280 function(regionCode) {
1281 return isNaN(regionCode);
1287 * Convenience method to get a list of what global network calling codes the
1288 * library has metadata for.
1290 * @return {!Array<number>} global network calling codes supported by the
1293 i18n.phonenumbers.PhoneNumberUtil.prototype.
1294 getSupportedGlobalNetworkCallingCodes = function() {
1295 var callingCodesAsStrings = goog.array.filter(
1296 Object.keys(i18n.phonenumbers.metadata.countryToMetadata),
1297 function(regionCode) {
1298 return !isNaN(regionCode);
1300 return goog.array.map(callingCodesAsStrings,
1301 function(callingCode) {
1302 return parseInt(callingCode, 10);
1308 * Normalizes a string of characters representing a phone number by replacing
1309 * all characters found in the accompanying map with the values therein, and
1310 * stripping all other characters if removeNonMatches is true.
1312 * @param {string} number a string of characters representing a phone number.
1313 * @param {!Object.<string, string>} normalizationReplacements a mapping of
1314 * characters to what they should be replaced by in the normalized version
1315 * of the phone number.
1316 * @param {boolean} removeNonMatches indicates whether characters that are not
1317 * able to be replaced should be stripped from the number. If this is false,
1318 * they will be left unchanged in the number.
1319 * @return {string} the normalized string version of the phone number.
1322 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_ =
1323 function(number, normalizationReplacements, removeNonMatches) {
1325 /** @type {!goog.string.StringBuffer} */
1326 var normalizedNumber = new goog.string.StringBuffer();
1327 /** @type {string} */
1329 /** @type {string} */
1331 /** @type {number} */
1332 var numberLength = number.length;
1333 for (var i = 0; i < numberLength; ++i) {
1334 character = number.charAt(i);
1335 newDigit = normalizationReplacements[character.toUpperCase()];
1336 if (newDigit != null) {
1337 normalizedNumber.append(newDigit);
1338 } else if (!removeNonMatches) {
1339 normalizedNumber.append(character);
1341 // If neither of the above are true, we remove this character.
1343 return normalizedNumber.toString();
1348 * Helper function to check if the national prefix formatting rule has the first
1349 * group only, i.e., does not start with the national prefix.
1351 * @param {string} nationalPrefixFormattingRule The formatting rule for the
1353 * @return {boolean} true if the national prefix formatting rule has the first
1356 i18n.phonenumbers.PhoneNumberUtil.prototype.formattingRuleHasFirstGroupOnly =
1357 function(nationalPrefixFormattingRule) {
1358 return nationalPrefixFormattingRule.length == 0 ||
1359 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_ONLY_PREFIX_PATTERN_.
1360 test(nationalPrefixFormattingRule);
1365 * Tests whether a phone number has a geographical association. It checks if
1366 * the number is associated to a certain region in the country where it belongs
1367 * to. Note that this doesn't verify if the number is actually in use.
1369 * @param {i18n.phonenumbers.PhoneNumber} phoneNumber The phone number to test.
1370 * @return {boolean} true if the phone number has a geographical association.
1372 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberGeographical =
1373 function(phoneNumber) {
1374 /** @type {i18n.phonenumbers.PhoneNumberType} */
1375 var numberType = this.getNumberType(phoneNumber);
1376 // TODO: Include mobile phone numbers from countries like Indonesia, which
1377 // has some mobile numbers that are geographical.
1378 return numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE ||
1379 numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
1384 * Helper function to check region code is not unknown or null.
1386 * @param {?string} regionCode the ISO 3166-1 two-letter region code.
1387 * @return {boolean} true if region code is valid.
1390 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidRegionCode_ =
1391 function(regionCode) {
1393 // In Java we check whether the regionCode is contained in supportedRegions
1394 // that is built out of all the values of countryCallingCodeToRegionCodeMap
1395 // (countryCodeToRegionCodeMap in JS) minus REGION_CODE_FOR_NON_GEO_ENTITY.
1396 // In JS we check whether the regionCode is contained in the keys of
1397 // countryToMetadata but since for non-geographical country calling codes
1398 // (e.g. +800) we use the country calling codes instead of the region code as
1399 // key in the map we have to make sure regionCode is not a number to prevent
1400 // returning true for non-geographical country calling codes.
1401 return regionCode != null &&
1402 isNaN(regionCode) &&
1403 regionCode.toUpperCase() in i18n.phonenumbers.metadata.countryToMetadata;
1408 * Helper function to check the country calling code is valid.
1410 * @param {number} countryCallingCode the country calling code.
1411 * @return {boolean} true if country calling code code is valid.
1414 i18n.phonenumbers.PhoneNumberUtil.prototype.hasValidCountryCallingCode_ =
1415 function(countryCallingCode) {
1417 return countryCallingCode in
1418 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap;
1423 * Formats a phone number in the specified format using default rules. Note that
1424 * this does not promise to produce a phone number that the user can dial from
1425 * where they are - although we do format in either 'national' or
1426 * 'international' format depending on what the client asks for, we do not
1427 * currently support a more abbreviated format, such as for users in the same
1428 * 'area' who could potentially dial the number without area code. Note that if
1429 * the phone number has a country calling code of 0 or an otherwise invalid
1430 * country calling code, we cannot work out which formatting rules to apply so
1431 * we return the national significant number with no formatting applied.
1433 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1435 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1436 * phone number should be formatted into.
1437 * @return {string} the formatted phone number.
1439 i18n.phonenumbers.PhoneNumberUtil.prototype.format =
1440 function(number, numberFormat) {
1442 if (number.getNationalNumber() == 0 && number.hasRawInput()) {
1443 // Unparseable numbers that kept their raw input just use that.
1444 // This is the only case where a number can be formatted as E164 without a
1445 // leading '+' symbol (but the original number wasn't parseable anyway).
1446 // TODO: Consider removing the 'if' above so that unparseable strings
1447 // without raw input format to the empty string instead of "+00"
1448 /** @type {string} */
1449 var rawInput = number.getRawInputOrDefault();
1450 if (rawInput.length > 0) {
1454 /** @type {number} */
1455 var countryCallingCode = number.getCountryCodeOrDefault();
1456 /** @type {string} */
1457 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1458 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.E164) {
1459 // Early exit for E164 case (even if the country calling code is invalid)
1460 // since no formatting of the national number needs to be applied.
1461 // Extensions are not formatted.
1462 return this.prefixNumberWithCountryCallingCode_(
1463 countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.E164,
1464 nationalSignificantNumber, '');
1466 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1467 return nationalSignificantNumber;
1469 // Note getRegionCodeForCountryCode() is used because formatting information
1470 // for regions which share a country calling code is contained by only one
1471 // region for performance reasons. For example, for NANPA regions it will be
1472 // contained in the metadata for US.
1473 /** @type {string} */
1474 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1476 // Metadata cannot be null because the country calling code is valid (which
1477 // means that the region code cannot be ZZ and must be one of our supported
1479 /** @type {i18n.phonenumbers.PhoneMetadata} */
1481 this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1482 /** @type {string} */
1483 var formattedExtension =
1484 this.maybeGetFormattedExtension_(number, metadata, numberFormat);
1485 /** @type {string} */
1486 var formattedNationalNumber =
1487 this.formatNsn_(nationalSignificantNumber, metadata, numberFormat);
1488 return this.prefixNumberWithCountryCallingCode_(countryCallingCode,
1490 formattedNationalNumber,
1491 formattedExtension);
1496 * Formats a phone number in the specified format using client-defined
1497 * formatting rules. Note that if the phone number has a country calling code of
1498 * zero or an otherwise invalid country calling code, we cannot work out things
1499 * like whether there should be a national prefix applied, or how to format
1500 * extensions, so we return the national significant number with no formatting
1503 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1505 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1506 * phone number should be formatted into.
1507 * @param {Array.<i18n.phonenumbers.NumberFormat>} userDefinedFormats formatting
1508 * rules specified by clients.
1509 * @return {string} the formatted phone number.
1511 i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern =
1512 function(number, numberFormat, userDefinedFormats) {
1514 /** @type {number} */
1515 var countryCallingCode = number.getCountryCodeOrDefault();
1516 /** @type {string} */
1517 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1518 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1519 return nationalSignificantNumber;
1521 // Note getRegionCodeForCountryCode() is used because formatting information
1522 // for regions which share a country calling code is contained by only one
1523 // region for performance reasons. For example, for NANPA regions it will be
1524 // contained in the metadata for US.
1525 /** @type {string} */
1526 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1527 // Metadata cannot be null because the country calling code is valid
1528 /** @type {i18n.phonenumbers.PhoneMetadata} */
1530 this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1532 /** @type {string} */
1533 var formattedNumber = '';
1535 /** @type {i18n.phonenumbers.NumberFormat} */
1536 var formattingPattern = this.chooseFormattingPatternForNumber_(
1537 userDefinedFormats, nationalSignificantNumber);
1538 if (formattingPattern == null) {
1539 // If no pattern above is matched, we format the number as a whole.
1540 formattedNumber = nationalSignificantNumber;
1542 // Before we do a replacement of the national prefix pattern $NP with the
1543 // national prefix, we need to copy the rule so that subsequent replacements
1544 // for different numbers have the appropriate national prefix.
1545 /** @type {i18n.phonenumbers.NumberFormat} */
1546 var numFormatCopy = formattingPattern.clone();
1547 /** @type {string} */
1548 var nationalPrefixFormattingRule =
1549 formattingPattern.getNationalPrefixFormattingRuleOrDefault();
1550 if (nationalPrefixFormattingRule.length > 0) {
1551 /** @type {string} */
1552 var nationalPrefix = metadata.getNationalPrefixOrDefault();
1553 if (nationalPrefix.length > 0) {
1554 // Replace $NP with national prefix and $FG with the first group ($1).
1555 nationalPrefixFormattingRule = nationalPrefixFormattingRule
1556 .replace(i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_,
1558 .replace(i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_, '$1');
1559 numFormatCopy.setNationalPrefixFormattingRule(
1560 nationalPrefixFormattingRule);
1562 // We don't want to have a rule for how to format the national prefix if
1564 numFormatCopy.clearNationalPrefixFormattingRule();
1567 formattedNumber = this.formatNsnUsingPattern_(
1568 nationalSignificantNumber, numFormatCopy, numberFormat);
1571 /** @type {string} */
1572 var formattedExtension =
1573 this.maybeGetFormattedExtension_(number, metadata, numberFormat);
1574 return this.prefixNumberWithCountryCallingCode_(countryCallingCode,
1577 formattedExtension);
1582 * Formats a phone number in national format for dialing using the carrier as
1583 * specified in the {@code carrierCode}. The {@code carrierCode} will always be
1584 * used regardless of whether the phone number already has a preferred domestic
1585 * carrier code stored. If {@code carrierCode} contains an empty string, returns
1586 * the number in national format without any carrier code.
1588 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1590 * @param {string} carrierCode the carrier selection code to be used.
1591 * @return {string} the formatted phone number in national format for dialing
1592 * using the carrier as specified in the {@code carrierCode}.
1594 i18n.phonenumbers.PhoneNumberUtil.prototype.
1595 formatNationalNumberWithCarrierCode = function(number, carrierCode) {
1597 /** @type {number} */
1598 var countryCallingCode = number.getCountryCodeOrDefault();
1599 /** @type {string} */
1600 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1601 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1602 return nationalSignificantNumber;
1605 // Note getRegionCodeForCountryCode() is used because formatting information
1606 // for regions which share a country calling code is contained by only one
1607 // region for performance reasons. For example, for NANPA regions it will be
1608 // contained in the metadata for US.
1609 /** @type {string} */
1610 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1611 // Metadata cannot be null because the country calling code is valid.
1612 /** @type {i18n.phonenumbers.PhoneMetadata} */
1614 this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1615 /** @type {string} */
1616 var formattedExtension = this.maybeGetFormattedExtension_(
1617 number, metadata, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1618 /** @type {string} */
1619 var formattedNationalNumber = this.formatNsn_(
1620 nationalSignificantNumber, metadata,
1621 i18n.phonenumbers.PhoneNumberFormat.NATIONAL, carrierCode);
1622 return this.prefixNumberWithCountryCallingCode_(
1623 countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL,
1624 formattedNationalNumber, formattedExtension);
1629 * @param {number} countryCallingCode
1630 * @param {?string} regionCode
1631 * @return {i18n.phonenumbers.PhoneMetadata}
1634 i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegionOrCallingCode_ =
1635 function(countryCallingCode, regionCode) {
1636 return i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY ==
1638 this.getMetadataForNonGeographicalRegion(countryCallingCode) :
1639 this.getMetadataForRegion(regionCode);
1644 * Formats a phone number in national format for dialing using the carrier as
1645 * specified in the preferred_domestic_carrier_code field of the PhoneNumber
1646 * object passed in. If that is missing, use the {@code fallbackCarrierCode}
1647 * passed in instead. If there is no {@code preferred_domestic_carrier_code},
1648 * and the {@code fallbackCarrierCode} contains an empty string, return the
1649 * number in national format without any carrier code.
1651 * <p>Use {@link #formatNationalNumberWithCarrierCode} instead if the carrier
1652 * code passed in should take precedence over the number's
1653 * {@code preferred_domestic_carrier_code} when formatting.
1655 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1657 * @param {string} fallbackCarrierCode the carrier selection code to be used, if
1658 * none is found in the phone number itself.
1659 * @return {string} the formatted phone number in national format for dialing
1660 * using the number's preferred_domestic_carrier_code, or the
1661 * {@code fallbackCarrierCode} passed in if none is found.
1663 i18n.phonenumbers.PhoneNumberUtil.prototype.
1664 formatNationalNumberWithPreferredCarrierCode = function(
1665 number, fallbackCarrierCode) {
1666 return this.formatNationalNumberWithCarrierCode(
1668 number.hasPreferredDomesticCarrierCode() ?
1669 number.getPreferredDomesticCarrierCodeOrDefault() :
1670 fallbackCarrierCode);
1675 * Returns a number formatted in such a way that it can be dialed from a mobile
1676 * phone in a specific region. If the number cannot be reached from the region
1677 * (e.g. some countries block toll-free numbers from being called outside of the
1678 * country), the method returns an empty string.
1680 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1682 * @param {string} regionCallingFrom the region where the call is being placed.
1683 * @param {boolean} withFormatting whether the number should be returned with
1684 * formatting symbols, such as spaces and dashes.
1685 * @return {string} the formatted phone number.
1687 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberForMobileDialing =
1688 function(number, regionCallingFrom, withFormatting) {
1690 /** @type {number} */
1691 var countryCallingCode = number.getCountryCodeOrDefault();
1692 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1693 return number.hasRawInput() ? number.getRawInputOrDefault() : '';
1696 /** @type {string} */
1697 var formattedNumber = '';
1698 // Clear the extension, as that part cannot normally be dialed together with
1700 /** @type {i18n.phonenumbers.PhoneNumber} */
1701 var numberNoExt = number.clone();
1702 numberNoExt.clearExtension();
1703 /** @type {string} */
1704 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1705 /** @type {i18n.phonenumbers.PhoneNumberType} */
1706 var numberType = this.getNumberType(numberNoExt);
1707 /** @type {boolean} */
1708 var isValidNumber = (numberType != i18n.phonenumbers.PhoneNumberType.UNKNOWN);
1709 if (regionCallingFrom == regionCode) {
1710 /** @type {boolean} */
1711 var isFixedLineOrMobile =
1712 (numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) ||
1713 (numberType == i18n.phonenumbers.PhoneNumberType.MOBILE) ||
1714 (numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE);
1715 // Carrier codes may be needed in some countries. We handle this here.
1716 if (regionCode == 'CO' &&
1717 numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) {
1718 formattedNumber = this.formatNationalNumberWithCarrierCode(
1720 i18n.phonenumbers.PhoneNumberUtil
1721 .COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX_);
1722 } else if (regionCode == 'BR' && isFixedLineOrMobile) {
1723 formattedNumber = numberNoExt.hasPreferredDomesticCarrierCode() ?
1724 this.formatNationalNumberWithPreferredCarrierCode(numberNoExt, '') :
1725 // Brazilian fixed line and mobile numbers need to be dialed with a
1726 // carrier code when called within Brazil. Without that, most of the
1727 // carriers won't connect the call. Because of that, we return an
1728 // empty string here.
1730 } else if (isValidNumber && regionCode == 'HU') {
1731 // The national format for HU numbers doesn't contain the national prefix,
1732 // because that is how numbers are normally written down. However, the
1733 // national prefix is obligatory when dialing from a mobile phone. As a
1734 // result, we add it back here if it is a valid regular length phone
1737 this.getNddPrefixForRegion(regionCode, true /* strip non-digits */) +
1738 ' ' + this.format(numberNoExt,
1739 i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1740 } else if (countryCallingCode ==
1741 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
1742 // For NANPA countries, we output international format for numbers that
1743 // can be dialed internationally, since that always works, except for
1744 // numbers which might potentially be short numbers, which are always
1745 // dialled in national format.
1746 /** @type {i18n.phonenumbers.PhoneMetadata} */
1747 var regionMetadata = this.getMetadataForRegion(regionCallingFrom);
1748 if (this.canBeInternationallyDialled(numberNoExt) &&
1749 !this.isShorterThanPossibleNormalNumber_(
1750 regionMetadata, this.getNationalSignificantNumber(numberNoExt))) {
1751 formattedNumber = this.format(
1752 numberNoExt, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1754 formattedNumber = this.format(
1755 numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1758 // For non-geographical countries, Mexican and Chilean fixed line and
1759 // mobile numbers, we output international format for numbers that can be
1760 // dialed internationally, as that always works.
1762 i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY ||
1763 // MX fixed line and mobile numbers should always be formatted in
1764 // international format, even when dialed within MX. For national
1765 // format to work, a carrier code needs to be used, and the correct
1766 // carrier code depends on if the caller and callee are from the
1767 // same local area. It is trickier to get that to work correctly than
1768 // using international format, which is tested to work fine on all
1770 // CL fixed line numbers need the national prefix when dialing in the
1771 // national format, but don't have it when used for display. The
1772 // reverse is true for mobile numbers. As a result, we output them in
1773 // the international format to make it work.
1774 ((regionCode == 'MX' || regionCode == 'CL') &&
1775 isFixedLineOrMobile)) &&
1776 this.canBeInternationallyDialled(numberNoExt)) {
1777 formattedNumber = this.format(
1778 numberNoExt, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1780 formattedNumber = this.format(
1781 numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1784 } else if (isValidNumber && this.canBeInternationallyDialled(numberNoExt)) {
1785 // We assume that short numbers are not diallable from outside their region,
1786 // so if a number is not a valid regular length phone number, we treat it as
1787 // if it cannot be internationally dialled.
1788 return withFormatting ?
1789 this.format(numberNoExt,
1790 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL) :
1791 this.format(numberNoExt, i18n.phonenumbers.PhoneNumberFormat.E164);
1793 return withFormatting ?
1795 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
1796 i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_, true);
1801 * Formats a phone number for out-of-country dialing purposes. If no
1802 * regionCallingFrom is supplied, we format the number in its INTERNATIONAL
1803 * format. If the country calling code is the same as that of the region where
1804 * the number is from, then NATIONAL formatting will be applied.
1806 * <p>If the number itself has a country calling code of zero or an otherwise
1807 * invalid country calling code, then we return the number with no formatting
1810 * <p>Note this function takes care of the case for calling inside of NANPA and
1811 * between Russia and Kazakhstan (who share the same country calling code). In
1812 * those cases, no international prefix is used. For regions which have multiple
1813 * international prefixes, the number in its INTERNATIONAL format will be
1816 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1818 * @param {string} regionCallingFrom the region where the call is being placed.
1819 * @return {string} the formatted phone number.
1821 i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
1822 function(number, regionCallingFrom) {
1824 if (!this.isValidRegionCode_(regionCallingFrom)) {
1825 return this.format(number,
1826 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1828 /** @type {number} */
1829 var countryCallingCode = number.getCountryCodeOrDefault();
1830 /** @type {string} */
1831 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1832 if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
1833 return nationalSignificantNumber;
1835 if (countryCallingCode ==
1836 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
1837 if (this.isNANPACountry(regionCallingFrom)) {
1838 // For NANPA regions, return the national format for these regions but
1839 // prefix it with the country calling code.
1840 return countryCallingCode + ' ' +
1841 this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1843 } else if (countryCallingCode ==
1844 this.getCountryCodeForValidRegion_(regionCallingFrom)) {
1845 // If regions share a country calling code, the country calling code need
1846 // not be dialled. This also applies when dialling within a region, so this
1847 // if clause covers both these cases. Technically this is the case for
1848 // dialling from La Reunion to other overseas departments of France (French
1849 // Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover
1850 // this edge case for now and for those cases return the version including
1851 // country calling code. Details here:
1852 // http://www.petitfute.com/voyage/225-info-pratiques-reunion
1853 return this.format(number,
1854 i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1856 // Metadata cannot be null because we checked 'isValidRegionCode()' above.
1857 /** @type {i18n.phonenumbers.PhoneMetadata} */
1858 var metadataForRegionCallingFrom =
1859 this.getMetadataForRegion(regionCallingFrom);
1860 /** @type {string} */
1861 var internationalPrefix =
1862 metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
1864 // For regions that have multiple international prefixes, the international
1865 // format of the number is returned, unless there is a preferred international
1867 /** @type {string} */
1868 var internationalPrefixForFormatting = '';
1869 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1870 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
1871 internationalPrefix)) {
1872 internationalPrefixForFormatting = internationalPrefix;
1873 } else if (metadataForRegionCallingFrom.hasPreferredInternationalPrefix()) {
1874 internationalPrefixForFormatting =
1875 metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
1878 /** @type {string} */
1879 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1880 // Metadata cannot be null because the country calling code is valid.
1881 /** @type {i18n.phonenumbers.PhoneMetadata} */
1882 var metadataForRegion =
1883 this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
1884 /** @type {string} */
1885 var formattedNationalNumber = this.formatNsn_(
1886 nationalSignificantNumber, metadataForRegion,
1887 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1888 /** @type {string} */
1889 var formattedExtension = this.maybeGetFormattedExtension_(number,
1890 metadataForRegion, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1891 return internationalPrefixForFormatting.length > 0 ?
1892 internationalPrefixForFormatting + ' ' + countryCallingCode + ' ' +
1893 formattedNationalNumber + formattedExtension :
1894 this.prefixNumberWithCountryCallingCode_(
1895 countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
1896 formattedNationalNumber, formattedExtension);
1901 * Formats a phone number using the original phone number format that the number
1902 * is parsed from. The original format is embedded in the country_code_source
1903 * field of the PhoneNumber object passed in. If such information is missing,
1904 * the number will be formatted into the NATIONAL format by default. When the
1905 * number contains a leading zero and this is unexpected for this country, or we
1906 * don't have a formatting pattern for the number, the method returns the raw
1907 * input when it is available.
1909 * Note this method guarantees no digit will be inserted, removed or modified as
1910 * a result of formatting.
1912 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
1913 * be formatted in its original number format.
1914 * @param {string} regionCallingFrom the region whose IDD needs to be prefixed
1915 * if the original number has one.
1916 * @return {string} the formatted phone number in its original number format.
1918 i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat =
1919 function(number, regionCallingFrom) {
1921 if (number.hasRawInput() &&
1922 (this.hasUnexpectedItalianLeadingZero_(number) ||
1923 !this.hasFormattingPatternForNumber_(number))) {
1924 // We check if we have the formatting pattern because without that, we might
1925 // format the number as a group without national prefix.
1926 return number.getRawInputOrDefault();
1928 if (!number.hasCountryCodeSource()) {
1929 return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1931 /** @type {string} */
1932 var formattedNumber;
1933 switch (number.getCountryCodeSource()) {
1934 case i18n.phonenumbers.PhoneNumber.CountryCodeSource
1935 .FROM_NUMBER_WITH_PLUS_SIGN:
1936 formattedNumber = this.format(number,
1937 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1939 case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD:
1941 this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
1943 case i18n.phonenumbers.PhoneNumber.CountryCodeSource
1944 .FROM_NUMBER_WITHOUT_PLUS_SIGN:
1945 formattedNumber = this.format(number,
1946 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL).substring(1);
1948 case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY:
1949 // Fall-through to default case.
1951 /** @type {string} */
1953 this.getRegionCodeForCountryCode(number.getCountryCodeOrDefault());
1954 // We strip non-digits from the NDD here, and from the raw input later,
1955 // so that we can compare them easily.
1956 /** @type {?string} */
1957 var nationalPrefix = this.getNddPrefixForRegion(regionCode, true);
1958 /** @type {string} */
1959 var nationalFormat =
1960 this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1961 if (nationalPrefix == null || nationalPrefix.length == 0) {
1962 // If the region doesn't have a national prefix at all, we can safely
1963 // return the national format without worrying about a national prefix
1965 formattedNumber = nationalFormat;
1968 // Otherwise, we check if the original number was entered with a national
1970 if (this.rawInputContainsNationalPrefix_(
1971 number.getRawInputOrDefault(), nationalPrefix, regionCode)) {
1972 // If so, we can safely return the national format.
1973 formattedNumber = nationalFormat;
1976 // Metadata cannot be null here because getNddPrefixForRegion() (above)
1977 // returns null if there is no metadata for the region.
1978 /** @type {i18n.phonenumbers.PhoneMetadata} */
1979 var metadata = this.getMetadataForRegion(regionCode);
1980 /** @type {string} */
1981 var nationalNumber = this.getNationalSignificantNumber(number);
1982 /** @type {i18n.phonenumbers.NumberFormat} */
1983 var formatRule = this.chooseFormattingPatternForNumber_(
1984 metadata.numberFormatArray(), nationalNumber);
1985 // The format rule could still be null here if the national number was 0
1986 // and there was no raw input (this should not be possible for numbers
1987 // generated by the phonenumber library as they would also not have a
1988 // country calling code and we would have exited earlier).
1989 if (formatRule == null) {
1990 formattedNumber = nationalFormat;
1993 // When the format we apply to this number doesn't contain national
1994 // prefix, we can just return the national format.
1995 // TODO: Refactor the code below with the code in
1996 // isNationalPrefixPresentIfRequired.
1997 /** @type {string} */
1998 var candidateNationalPrefixRule =
1999 formatRule.getNationalPrefixFormattingRuleOrDefault();
2000 // We assume that the first-group symbol will never be _before_ the
2002 /** @type {number} */
2003 var indexOfFirstGroup = candidateNationalPrefixRule.indexOf('$1');
2004 if (indexOfFirstGroup <= 0) {
2005 formattedNumber = nationalFormat;
2008 candidateNationalPrefixRule =
2009 candidateNationalPrefixRule.substring(0, indexOfFirstGroup);
2010 candidateNationalPrefixRule = i18n.phonenumbers.PhoneNumberUtil
2011 .normalizeDigitsOnly(candidateNationalPrefixRule);
2012 if (candidateNationalPrefixRule.length == 0) {
2013 // National prefix not used when formatting this number.
2014 formattedNumber = nationalFormat;
2017 // Otherwise, we need to remove the national prefix from our output.
2018 /** @type {i18n.phonenumbers.NumberFormat} */
2019 var numFormatCopy = formatRule.clone();
2020 numFormatCopy.clearNationalPrefixFormattingRule();
2021 formattedNumber = this.formatByPattern(number,
2022 i18n.phonenumbers.PhoneNumberFormat.NATIONAL, [numFormatCopy]);
2025 /** @type {string} */
2026 var rawInput = number.getRawInputOrDefault();
2027 // If no digit is inserted/removed/modified as a result of our formatting, we
2028 // return the formatted phone number; otherwise we return the raw input the
2030 if (formattedNumber != null && rawInput.length > 0) {
2031 /** @type {string} */
2032 var normalizedFormattedNumber =
2033 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
2034 i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
2035 true /* remove non matches */);
2036 /** @type {string} */
2037 var normalizedRawInput =
2038 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(rawInput,
2039 i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
2040 true /* remove non matches */);
2041 if (normalizedFormattedNumber != normalizedRawInput) {
2042 formattedNumber = rawInput;
2045 return formattedNumber;
2050 * Check if rawInput, which is assumed to be in the national format, has a
2051 * national prefix. The national prefix is assumed to be in digits-only form.
2052 * @param {string} rawInput
2053 * @param {string} nationalPrefix
2054 * @param {string} regionCode
2058 i18n.phonenumbers.PhoneNumberUtil.prototype.rawInputContainsNationalPrefix_ =
2059 function(rawInput, nationalPrefix, regionCode) {
2061 /** @type {string} */
2062 var normalizedNationalNumber =
2063 i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(rawInput);
2064 if (goog.string.startsWith(normalizedNationalNumber, nationalPrefix)) {
2066 // Some Japanese numbers (e.g. 00777123) might be mistaken to contain the
2067 // national prefix when written without it (e.g. 0777123) if we just do
2068 // prefix matching. To tackle that, we check the validity of the number if
2069 // the assumed national prefix is removed (777123 won't be valid in
2071 return this.isValidNumber(
2072 this.parse(normalizedNationalNumber.substring(nationalPrefix.length),
2083 * Returns true if a number is from a region whose national significant number
2084 * couldn't contain a leading zero, but has the italian_leading_zero field set
2086 * @param {i18n.phonenumbers.PhoneNumber} number
2090 i18n.phonenumbers.PhoneNumberUtil.prototype.hasUnexpectedItalianLeadingZero_ =
2093 return number.hasItalianLeadingZero() &&
2094 !this.isLeadingZeroPossible(number.getCountryCodeOrDefault());
2099 * @param {i18n.phonenumbers.PhoneNumber} number
2103 i18n.phonenumbers.PhoneNumberUtil.prototype.hasFormattingPatternForNumber_ =
2106 /** @type {number} */
2107 var countryCallingCode = number.getCountryCodeOrDefault();
2108 /** @type {string} */
2109 var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCallingCode);
2110 /** @type {i18n.phonenumbers.PhoneMetadata} */
2111 var metadata = this.getMetadataForRegionOrCallingCode_(
2112 countryCallingCode, phoneNumberRegion);
2113 if (metadata == null) {
2116 /** @type {string} */
2117 var nationalNumber = this.getNationalSignificantNumber(number);
2118 /** @type {i18n.phonenumbers.NumberFormat} */
2119 var formatRule = this.chooseFormattingPatternForNumber_(
2120 metadata.numberFormatArray(), nationalNumber);
2121 return formatRule != null;
2126 * Formats a phone number for out-of-country dialing purposes.
2128 * Note that in this version, if the number was entered originally using alpha
2129 * characters and this version of the number is stored in raw_input, this
2130 * representation of the number will be used rather than the digit
2131 * representation. Grouping information, as specified by characters such as '-'
2132 * and ' ', will be retained.
2134 * <p><b>Caveats:</b></p>
2136 * <li>This will not produce good results if the country calling code is both
2137 * present in the raw input _and_ is the start of the national number. This is
2138 * not a problem in the regions which typically use alpha numbers.
2139 * <li>This will also not produce good results if the raw input has any grouping
2140 * information within the first three digits of the national number, and if the
2141 * function needs to strip preceding digits/words in the raw input before these
2142 * digits. Normally people group the first three digits together so this is not
2143 * a huge problem - and will be fixed if it proves to be so.
2146 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
2148 * @param {string} regionCallingFrom the region where the call is being placed.
2149 * @return {string} the formatted phone number.
2151 i18n.phonenumbers.PhoneNumberUtil.prototype.
2152 formatOutOfCountryKeepingAlphaChars = function(number, regionCallingFrom) {
2153 /** @type {string} */
2154 var rawInput = number.getRawInputOrDefault();
2155 // If there is no raw input, then we can't keep alpha characters because there
2156 // aren't any. In this case, we return formatOutOfCountryCallingNumber.
2157 if (rawInput.length == 0) {
2158 return this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
2160 /** @type {number} */
2161 var countryCode = number.getCountryCodeOrDefault();
2162 if (!this.hasValidCountryCallingCode_(countryCode)) {
2165 // Strip any prefix such as country calling code, IDD, that was present. We do
2166 // this by comparing the number in raw_input with the parsed number. To do
2167 // this, first we normalize punctuation. We retain number grouping symbols
2168 // such as ' ' only.
2169 rawInput = i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(
2171 i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_,
2173 // Now we trim everything before the first three digits in the parsed number.
2174 // We choose three because all valid alpha numbers have 3 digits at the start
2175 // - if it does not, then we don't trim anything at all. Similarly, if the
2176 // national number was less than three digits, we don't trim anything at all.
2177 /** @type {string} */
2178 var nationalNumber = this.getNationalSignificantNumber(number);
2179 if (nationalNumber.length > 3) {
2180 /** @type {number} */
2181 var firstNationalNumberDigit =
2182 rawInput.indexOf(nationalNumber.substring(0, 3));
2183 if (firstNationalNumberDigit != -1) {
2184 rawInput = rawInput.substring(firstNationalNumberDigit);
2187 /** @type {i18n.phonenumbers.PhoneMetadata} */
2188 var metadataForRegionCallingFrom =
2189 this.getMetadataForRegion(regionCallingFrom);
2190 if (countryCode == i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
2191 if (this.isNANPACountry(regionCallingFrom)) {
2192 return countryCode + ' ' + rawInput;
2194 } else if (metadataForRegionCallingFrom != null &&
2195 countryCode == this.getCountryCodeForValidRegion_(regionCallingFrom)) {
2196 /** @type {i18n.phonenumbers.NumberFormat} */
2197 var formattingPattern = this.chooseFormattingPatternForNumber_(
2198 metadataForRegionCallingFrom.numberFormatArray(), nationalNumber);
2199 if (formattingPattern == null) {
2200 // If no pattern above is matched, we format the original input.
2203 /** @type {i18n.phonenumbers.NumberFormat} */
2204 var newFormat = formattingPattern.clone();
2205 // The first group is the first group of digits that the user wrote
2207 newFormat.setPattern('(\\d+)(.*)');
2208 // Here we just concatenate them back together after the national prefix
2210 newFormat.setFormat('$1$2');
2211 // Now we format using this pattern instead of the default pattern, but
2212 // with the national prefix prefixed if necessary.
2213 // This will not work in the cases where the pattern (and not the leading
2214 // digits) decide whether a national prefix needs to be used, since we have
2215 // overridden the pattern to match anything, but that is not the case in the
2216 // metadata to date.
2217 return this.formatNsnUsingPattern_(rawInput, newFormat,
2218 i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
2220 /** @type {string} */
2221 var internationalPrefixForFormatting = '';
2222 // If an unsupported region-calling-from is entered, or a country with
2223 // multiple international prefixes, the international format of the number is
2224 // returned, unless there is a preferred international prefix.
2225 if (metadataForRegionCallingFrom != null) {
2226 /** @type {string} */
2227 var internationalPrefix =
2228 metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
2229 internationalPrefixForFormatting =
2230 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2231 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
2232 internationalPrefix) ?
2233 internationalPrefix :
2234 metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
2236 /** @type {string} */
2237 var regionCode = this.getRegionCodeForCountryCode(countryCode);
2238 // Metadata cannot be null because the country calling code is valid.
2239 /** @type {i18n.phonenumbers.PhoneMetadata} */
2240 var metadataForRegion =
2241 this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
2242 /** @type {string} */
2243 var formattedExtension = this.maybeGetFormattedExtension_(
2244 number, metadataForRegion,
2245 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
2246 if (internationalPrefixForFormatting.length > 0) {
2247 return internationalPrefixForFormatting + ' ' + countryCode + ' ' +
2248 rawInput + formattedExtension;
2250 // Invalid region entered as country-calling-from (so no metadata was found
2251 // for it) or the region chosen has multiple international dialling
2253 return this.prefixNumberWithCountryCallingCode_(
2254 countryCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
2255 rawInput, formattedExtension);
2261 * Gets the national significant number of the a phone number. Note a national
2262 * significant number doesn't contain a national prefix or any formatting.
2264 * @param {i18n.phonenumbers.PhoneNumber} number the phone number for which the
2265 * national significant number is needed.
2266 * @return {string} the national significant number of the PhoneNumber object
2269 i18n.phonenumbers.PhoneNumberUtil.prototype.getNationalSignificantNumber =
2272 // If leading zero(s) have been set, we prefix this now. Note this is not a
2274 /** @type {string} */
2275 var nationalNumber = '' + number.getNationalNumber();
2276 if (number.hasItalianLeadingZero() && number.getItalianLeadingZero()) {
2277 return Array(number.getNumberOfLeadingZerosOrDefault() + 1).join('0') +
2280 return nationalNumber;
2285 * A helper function that is used by format and formatByPattern.
2287 * @param {number} countryCallingCode the country calling code.
2288 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2289 * phone number should be formatted into.
2290 * @param {string} formattedNationalNumber
2291 * @param {string} formattedExtension
2292 * @return {string} the formatted phone number.
2295 i18n.phonenumbers.PhoneNumberUtil.prototype.
2296 prefixNumberWithCountryCallingCode_ = function(countryCallingCode,
2298 formattedNationalNumber,
2299 formattedExtension) {
2301 switch (numberFormat) {
2302 case i18n.phonenumbers.PhoneNumberFormat.E164:
2303 return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
2304 formattedNationalNumber + formattedExtension;
2305 case i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL:
2306 return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
2307 ' ' + formattedNationalNumber + formattedExtension;
2308 case i18n.phonenumbers.PhoneNumberFormat.RFC3966:
2309 return i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_ +
2310 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
2311 '-' + formattedNationalNumber + formattedExtension;
2312 case i18n.phonenumbers.PhoneNumberFormat.NATIONAL:
2314 return formattedNationalNumber + formattedExtension;
2320 * Note in some regions, the national number can be written in two completely
2321 * different ways depending on whether it forms part of the NATIONAL format or
2322 * INTERNATIONAL format. The numberFormat parameter here is used to specify
2323 * which format to use for those cases. If a carrierCode is specified, this will
2324 * be inserted into the formatted string to replace $CC.
2326 * @param {string} number a string of characters representing a phone number.
2327 * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
2328 * region that we think this number is from.
2329 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2330 * phone number should be formatted into.
2331 * @param {string=} opt_carrierCode
2332 * @return {string} the formatted phone number.
2335 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNsn_ =
2336 function(number, metadata, numberFormat, opt_carrierCode) {
2338 /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
2339 var intlNumberFormats = metadata.intlNumberFormatArray();
2340 // When the intlNumberFormats exists, we use that to format national number
2341 // for the INTERNATIONAL format instead of using the numberDesc.numberFormats.
2342 /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
2343 var availableFormats =
2344 (intlNumberFormats.length == 0 ||
2345 numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL) ?
2346 metadata.numberFormatArray() : metadata.intlNumberFormatArray();
2347 /** @type {i18n.phonenumbers.NumberFormat} */
2348 var formattingPattern = this.chooseFormattingPatternForNumber_(
2349 availableFormats, number);
2350 return (formattingPattern == null) ?
2352 this.formatNsnUsingPattern_(number, formattingPattern,
2353 numberFormat, opt_carrierCode);
2358 * @param {Array.<i18n.phonenumbers.NumberFormat>} availableFormats the
2359 * available formats the phone number could be formatted into.
2360 * @param {string} nationalNumber a string of characters representing a phone
2362 * @return {i18n.phonenumbers.NumberFormat}
2365 i18n.phonenumbers.PhoneNumberUtil.prototype.chooseFormattingPatternForNumber_ =
2366 function(availableFormats, nationalNumber) {
2368 /** @type {i18n.phonenumbers.NumberFormat} */
2370 /** @type {number} */
2371 var l = availableFormats.length;
2372 for (var i = 0; i < l; ++i) {
2373 numFormat = availableFormats[i];
2374 /** @type {number} */
2375 var size = numFormat.leadingDigitsPatternCount();
2377 // We always use the last leading_digits_pattern, as it is the most
2380 .search(numFormat.getLeadingDigitsPattern(size - 1)) == 0) {
2381 /** @type {!RegExp} */
2382 var patternToMatch = new RegExp(numFormat.getPattern());
2383 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(patternToMatch,
2394 * Note that carrierCode is optional - if null or an empty string, no carrier
2395 * code replacement will take place.
2397 * @param {string} nationalNumber a string of characters representing a phone
2399 * @param {i18n.phonenumbers.NumberFormat} formattingPattern the formatting rule
2400 * the phone number should be formatted into.
2401 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2402 * phone number should be formatted into.
2403 * @param {string=} opt_carrierCode
2404 * @return {string} the formatted phone number.
2407 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNsnUsingPattern_ =
2408 function(nationalNumber, formattingPattern, numberFormat, opt_carrierCode) {
2410 /** @type {string} */
2411 var numberFormatRule = formattingPattern.getFormatOrDefault();
2412 /** @type {!RegExp} */
2413 var patternToMatch = new RegExp(formattingPattern.getPattern());
2414 /** @type {string} */
2415 var domesticCarrierCodeFormattingRule =
2416 formattingPattern.getDomesticCarrierCodeFormattingRuleOrDefault();
2417 /** @type {string} */
2418 var formattedNationalNumber = '';
2419 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
2420 opt_carrierCode != null && opt_carrierCode.length > 0 &&
2421 domesticCarrierCodeFormattingRule.length > 0) {
2422 // Replace the $CC in the formatting rule with the desired carrier code.
2423 /** @type {string} */
2424 var carrierCodeFormattingRule = domesticCarrierCodeFormattingRule
2425 .replace(i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_,
2427 // Now replace the $FG in the formatting rule with the first group and
2428 // the carrier code combined in the appropriate way.
2429 numberFormatRule = numberFormatRule.replace(
2430 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
2431 carrierCodeFormattingRule);
2432 formattedNationalNumber =
2433 nationalNumber.replace(patternToMatch, numberFormatRule);
2435 // Use the national prefix formatting rule instead.
2436 /** @type {string} */
2437 var nationalPrefixFormattingRule =
2438 formattingPattern.getNationalPrefixFormattingRuleOrDefault();
2439 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
2440 nationalPrefixFormattingRule != null &&
2441 nationalPrefixFormattingRule.length > 0) {
2442 formattedNationalNumber = nationalNumber.replace(patternToMatch,
2443 numberFormatRule.replace(
2444 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
2445 nationalPrefixFormattingRule));
2447 formattedNationalNumber =
2448 nationalNumber.replace(patternToMatch, numberFormatRule);
2451 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
2452 // Strip any leading punctuation.
2453 formattedNationalNumber = formattedNationalNumber.replace(
2454 new RegExp('^' + i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_),
2456 // Replace the rest with a dash between each number group.
2457 formattedNationalNumber = formattedNationalNumber.replace(
2458 new RegExp(i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_, 'g'),
2461 return formattedNationalNumber;
2466 * Gets a valid number for the specified region.
2468 * @param {string} regionCode the region for which an example number is needed.
2469 * @return {i18n.phonenumbers.PhoneNumber} a valid fixed-line number for the
2470 * specified region. Returns null when the metadata does not contain such
2471 * information, or the region 001 is passed in. For 001 (representing non-
2472 * geographical numbers), call {@link #getExampleNumberForNonGeoEntity}
2475 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumber =
2476 function(regionCode) {
2478 return this.getExampleNumberForType(regionCode,
2479 i18n.phonenumbers.PhoneNumberType.FIXED_LINE);
2484 * Gets a valid number for the specified region and number type.
2486 * @param {string} regionCode the region for which an example number is needed.
2487 * @param {i18n.phonenumbers.PhoneNumberType} type the type of number that is
2489 * @return {i18n.phonenumbers.PhoneNumber} a valid number for the specified
2490 * region and type. Returns null when the metadata does not contain such
2491 * information or if an invalid region or region 001 was entered.
2492 * For 001 (representing non-geographical numbers), call
2493 * {@link #getExampleNumberForNonGeoEntity} instead.
2495 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForType =
2496 function(regionCode, type) {
2498 // Check the region code is valid.
2499 if (!this.isValidRegionCode_(regionCode)) {
2502 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2503 var desc = this.getNumberDescByType_(
2504 this.getMetadataForRegion(regionCode), type);
2506 if (desc.hasExampleNumber()) {
2507 return this.parse(desc.getExampleNumberOrDefault(), regionCode);
2516 * Gets a valid number for the specified country calling code for a
2517 * non-geographical entity.
2519 * @param {number} countryCallingCode the country calling code for a
2520 * non-geographical entity.
2521 * @return {i18n.phonenumbers.PhoneNumber} a valid number for the
2522 * non-geographical entity. Returns null when the metadata does not contain
2523 * such information, or the country calling code passed in does not belong
2524 * to a non-geographical entity.
2526 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForNonGeoEntity =
2527 function(countryCallingCode) {
2528 /** @type {i18n.phonenumbers.PhoneMetadata} */
2530 this.getMetadataForNonGeographicalRegion(countryCallingCode);
2531 if (metadata != null) {
2532 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2533 var desc = metadata.getGeneralDesc();
2535 if (desc.hasExampleNumber()) {
2536 return this.parse('+' + countryCallingCode + desc.getExampleNumber(),
2547 * Gets the formatted extension of a phone number, if the phone number had an
2548 * extension specified. If not, it returns an empty string.
2550 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber that might have
2552 * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
2553 * region that we think this number is from.
2554 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
2555 * phone number should be formatted into.
2556 * @return {string} the formatted extension if any.
2559 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeGetFormattedExtension_ =
2560 function(number, metadata, numberFormat) {
2562 if (!number.hasExtension() || number.getExtension().length == 0) {
2565 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
2566 return i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
2567 number.getExtension();
2569 if (metadata.hasPreferredExtnPrefix()) {
2570 return metadata.getPreferredExtnPrefix() +
2571 number.getExtensionOrDefault();
2573 return i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ +
2574 number.getExtensionOrDefault();
2582 * @param {i18n.phonenumbers.PhoneMetadata} metadata
2583 * @param {i18n.phonenumbers.PhoneNumberType} type
2584 * @return {i18n.phonenumbers.PhoneNumberDesc}
2587 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberDescByType_ =
2588 function(metadata, type) {
2591 case i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE:
2592 return metadata.getPremiumRate();
2593 case i18n.phonenumbers.PhoneNumberType.TOLL_FREE:
2594 return metadata.getTollFree();
2595 case i18n.phonenumbers.PhoneNumberType.MOBILE:
2596 return metadata.getMobile();
2597 case i18n.phonenumbers.PhoneNumberType.FIXED_LINE:
2598 case i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE:
2599 return metadata.getFixedLine();
2600 case i18n.phonenumbers.PhoneNumberType.SHARED_COST:
2601 return metadata.getSharedCost();
2602 case i18n.phonenumbers.PhoneNumberType.VOIP:
2603 return metadata.getVoip();
2604 case i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER:
2605 return metadata.getPersonalNumber();
2606 case i18n.phonenumbers.PhoneNumberType.PAGER:
2607 return metadata.getPager();
2608 case i18n.phonenumbers.PhoneNumberType.UAN:
2609 return metadata.getUan();
2610 case i18n.phonenumbers.PhoneNumberType.VOICEMAIL:
2611 return metadata.getVoicemail();
2613 return metadata.getGeneralDesc();
2619 * Gets the type of a phone number.
2621 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2623 * @return {i18n.phonenumbers.PhoneNumberType} the type of the phone number.
2625 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberType =
2628 /** @type {?string} */
2629 var regionCode = this.getRegionCodeForNumber(number);
2630 /** @type {i18n.phonenumbers.PhoneMetadata} */
2631 var metadata = this.getMetadataForRegionOrCallingCode_(
2632 number.getCountryCodeOrDefault(), regionCode);
2633 if (metadata == null) {
2634 return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2636 /** @type {string} */
2637 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
2638 return this.getNumberTypeHelper_(nationalSignificantNumber, metadata);
2643 * @param {string} nationalNumber
2644 * @param {i18n.phonenumbers.PhoneMetadata} metadata
2645 * @return {i18n.phonenumbers.PhoneNumberType}
2648 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberTypeHelper_ =
2649 function(nationalNumber, metadata) {
2651 if (!this.isNumberMatchingDesc_(nationalNumber, metadata.getGeneralDesc())) {
2652 return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2655 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPremiumRate())) {
2656 return i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE;
2658 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getTollFree())) {
2659 return i18n.phonenumbers.PhoneNumberType.TOLL_FREE;
2661 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getSharedCost())) {
2662 return i18n.phonenumbers.PhoneNumberType.SHARED_COST;
2664 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoip())) {
2665 return i18n.phonenumbers.PhoneNumberType.VOIP;
2667 if (this.isNumberMatchingDesc_(nationalNumber,
2668 metadata.getPersonalNumber())) {
2669 return i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER;
2671 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPager())) {
2672 return i18n.phonenumbers.PhoneNumberType.PAGER;
2674 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getUan())) {
2675 return i18n.phonenumbers.PhoneNumberType.UAN;
2677 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoicemail())) {
2678 return i18n.phonenumbers.PhoneNumberType.VOICEMAIL;
2681 /** @type {boolean} */
2682 var isFixedLine = this.isNumberMatchingDesc_(nationalNumber, metadata
2685 if (metadata.getSameMobileAndFixedLinePattern()) {
2686 return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
2687 } else if (this.isNumberMatchingDesc_(nationalNumber,
2688 metadata.getMobile())) {
2689 return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
2691 return i18n.phonenumbers.PhoneNumberType.FIXED_LINE;
2693 // Otherwise, test to see if the number is mobile. Only do this if certain
2694 // that the patterns for mobile and fixed line aren't the same.
2695 if (!metadata.getSameMobileAndFixedLinePattern() &&
2696 this.isNumberMatchingDesc_(nationalNumber, metadata.getMobile())) {
2697 return i18n.phonenumbers.PhoneNumberType.MOBILE;
2699 return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2704 * Returns the metadata for the given region code or {@code null} if the region
2705 * code is invalid or unknown.
2707 * @param {?string} regionCode
2708 * @return {i18n.phonenumbers.PhoneMetadata}
2710 i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegion =
2711 function(regionCode) {
2713 if (regionCode == null) {
2716 regionCode = regionCode.toUpperCase();
2717 /** @type {i18n.phonenumbers.PhoneMetadata} */
2718 var metadata = this.regionToMetadataMap[regionCode];
2719 if (metadata == null) {
2720 /** @type {goog.proto2.PbLiteSerializer} */
2721 var serializer = new goog.proto2.PbLiteSerializer();
2722 /** @type {Array} */
2723 var metadataSerialized =
2724 i18n.phonenumbers.metadata.countryToMetadata[regionCode];
2725 if (metadataSerialized == null) {
2728 metadata = /** @type {i18n.phonenumbers.PhoneMetadata} */ (
2729 serializer.deserialize(i18n.phonenumbers.PhoneMetadata.getDescriptor(),
2730 metadataSerialized));
2731 this.regionToMetadataMap[regionCode] = metadata;
2738 * @param {number} countryCallingCode
2739 * @return {i18n.phonenumbers.PhoneMetadata}
2741 i18n.phonenumbers.PhoneNumberUtil.prototype.
2742 getMetadataForNonGeographicalRegion = function(countryCallingCode) {
2744 return this.getMetadataForRegion('' + countryCallingCode);
2749 * @param {string} nationalNumber
2750 * @param {i18n.phonenumbers.PhoneNumberDesc} numberDesc
2754 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatchingDesc_ =
2755 function(nationalNumber, numberDesc) {
2757 return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2758 numberDesc.getPossibleNumberPatternOrDefault(), nationalNumber) &&
2759 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2760 numberDesc.getNationalNumberPatternOrDefault(), nationalNumber);
2765 * Tests whether a phone number matches a valid pattern. Note this doesn't
2766 * verify the number is actually in use, which is impossible to tell by just
2767 * looking at a number itself.
2769 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2771 * @return {boolean} a boolean that indicates whether the number is of a valid
2774 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) {
2775 /** @type {?string} */
2776 var regionCode = this.getRegionCodeForNumber(number);
2777 return this.isValidNumberForRegion(number, regionCode);
2782 * Tests whether a phone number is valid for a certain region. Note this doesn't
2783 * verify the number is actually in use, which is impossible to tell by just
2784 * looking at a number itself. If the country calling code is not the same as
2785 * the country calling code for the region, this immediately exits with false.
2786 * After this, the specific number pattern rules for the region are examined.
2787 * This is useful for determining for example whether a particular number is
2788 * valid for Canada, rather than just a valid NANPA number.
2789 * Warning: In most cases, you want to use {@link #isValidNumber} instead. For
2790 * example, this method will mark numbers from British Crown dependencies such
2791 * as the Isle of Man as invalid for the region "GB" (United Kingdom), since it
2792 * has its own region code, "IM", which may be undesirable.
2794 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2796 * @param {?string} regionCode the region that we want to validate the phone
2798 * @return {boolean} a boolean that indicates whether the number is of a valid
2801 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumberForRegion =
2802 function(number, regionCode) {
2804 /** @type {number} */
2805 var countryCode = number.getCountryCodeOrDefault();
2806 /** @type {i18n.phonenumbers.PhoneMetadata} */
2808 this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
2809 if (metadata == null ||
2810 (i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY !=
2812 countryCode != this.getCountryCodeForValidRegion_(regionCode))) {
2813 // Either the region code was invalid, or the country calling code for this
2814 // number does not match that of the region code.
2817 /** @type {string} */
2818 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
2820 return this.getNumberTypeHelper_(nationalSignificantNumber, metadata) !=
2821 i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2826 * Returns the region where a phone number is from. This could be used for
2827 * geocoding at the region level.
2829 * @param {i18n.phonenumbers.PhoneNumber} number the phone number whose origin
2831 * @return {?string} the region where the phone number is from, or null
2832 * if no region matches this calling code.
2834 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForNumber =
2837 if (number == null) {
2840 /** @type {number} */
2841 var countryCode = number.getCountryCodeOrDefault();
2842 /** @type {Array.<string>} */
2844 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCode];
2845 if (regions == null) {
2848 if (regions.length == 1) {
2851 return this.getRegionCodeForNumberFromRegionList_(number, regions);
2857 * @param {i18n.phonenumbers.PhoneNumber} number
2858 * @param {Array.<string>} regionCodes
2862 i18n.phonenumbers.PhoneNumberUtil.prototype.
2863 getRegionCodeForNumberFromRegionList_ = function(number, regionCodes) {
2865 /** @type {string} */
2866 var nationalNumber = this.getNationalSignificantNumber(number);
2867 /** @type {string} */
2869 /** @type {number} */
2870 var regionCodesLength = regionCodes.length;
2871 for (var i = 0; i < regionCodesLength; i++) {
2872 regionCode = regionCodes[i];
2873 // If leadingDigits is present, use this. Otherwise, do full validation.
2874 // Metadata cannot be null because the region codes come from the country
2875 // calling code map.
2876 /** @type {i18n.phonenumbers.PhoneMetadata} */
2877 var metadata = this.getMetadataForRegion(regionCode);
2878 if (metadata.hasLeadingDigits()) {
2879 if (nationalNumber.search(metadata.getLeadingDigits()) == 0) {
2882 } else if (this.getNumberTypeHelper_(nationalNumber, metadata) !=
2883 i18n.phonenumbers.PhoneNumberType.UNKNOWN) {
2892 * Returns the region code that matches the specific country calling code. In
2893 * the case of no region code being found, ZZ will be returned. In the case of
2894 * multiple regions, the one designated in the metadata as the 'main' region for
2895 * this calling code will be returned.
2897 * @param {number} countryCallingCode the country calling code.
2900 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForCountryCode =
2901 function(countryCallingCode) {
2903 /** @type {Array.<string>} */
2905 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
2906 return regionCodes == null ?
2907 i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ : regionCodes[0];
2912 * Returns a list with the region codes that match the specific country calling
2913 * code. For non-geographical country calling codes, the region code 001 is
2914 * returned. Also, in the case of no region code being found, an empty list is
2917 * @param {number} countryCallingCode the country calling code.
2918 * @return {Array.<string>}
2920 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodesForCountryCode =
2921 function(countryCallingCode) {
2923 /** @type {Array.<string>} */
2925 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
2926 return regionCodes == null ? [] : regionCodes;
2931 * Returns the country calling code for a specific region. For example, this
2932 * would be 1 for the United States, and 64 for New Zealand.
2934 * @param {?string} regionCode the region that we want to get the country
2936 * @return {number} the country calling code for the region denoted by
2939 i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForRegion =
2940 function(regionCode) {
2942 if (!this.isValidRegionCode_(regionCode)) {
2945 return this.getCountryCodeForValidRegion_(regionCode);
2950 * Returns the country calling code for a specific region. For example, this
2951 * would be 1 for the United States, and 64 for New Zealand. Assumes the region
2954 * @param {?string} regionCode the region that we want to get the country
2956 * @return {number} the country calling code for the region denoted by
2958 * @throws {string} if the region is invalid
2961 i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForValidRegion_ =
2962 function(regionCode) {
2964 /** @type {i18n.phonenumbers.PhoneMetadata} */
2965 var metadata = this.getMetadataForRegion(regionCode);
2966 if (metadata == null) {
2967 throw 'Invalid region code: ' + regionCode;
2969 return metadata.getCountryCodeOrDefault();
2974 * Returns the national dialling prefix for a specific region. For example, this
2975 * would be 1 for the United States, and 0 for New Zealand. Set stripNonDigits
2976 * to true to strip symbols like '~' (which indicates a wait for a dialling
2977 * tone) from the prefix returned. If no national prefix is present, we return
2980 * <p>Warning: Do not use this method for do-your-own formatting - for some
2981 * regions, the national dialling prefix is used only for certain types of
2982 * numbers. Use the library's formatting functions to prefix the national prefix
2985 * @param {?string} regionCode the region that we want to get the dialling
2987 * @param {boolean} stripNonDigits true to strip non-digits from the national
2989 * @return {?string} the dialling prefix for the region denoted by
2992 i18n.phonenumbers.PhoneNumberUtil.prototype.getNddPrefixForRegion = function(
2993 regionCode, stripNonDigits) {
2994 /** @type {i18n.phonenumbers.PhoneMetadata} */
2995 var metadata = this.getMetadataForRegion(regionCode);
2996 if (metadata == null) {
2999 /** @type {string} */
3000 var nationalPrefix = metadata.getNationalPrefixOrDefault();
3001 // If no national prefix was found, we return null.
3002 if (nationalPrefix.length == 0) {
3005 if (stripNonDigits) {
3006 // Note: if any other non-numeric symbols are ever used in national
3007 // prefixes, these would have to be removed here as well.
3008 nationalPrefix = nationalPrefix.replace('~', '');
3010 return nationalPrefix;
3015 * Checks if this is a region under the North American Numbering Plan
3016 * Administration (NANPA).
3018 * @param {?string} regionCode the ISO 3166-1 two-letter region code.
3019 * @return {boolean} true if regionCode is one of the regions under NANPA.
3021 i18n.phonenumbers.PhoneNumberUtil.prototype.isNANPACountry =
3022 function(regionCode) {
3024 return regionCode != null && goog.array.contains(
3025 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[
3026 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_],
3027 regionCode.toUpperCase());
3032 * Checks whether countryCode represents the country calling code from a region
3033 * whose national significant number could contain a leading zero. An example of
3034 * such a region is Italy. Returns false if no metadata for the country is
3037 * @param {number} countryCallingCode the country calling code.
3040 i18n.phonenumbers.PhoneNumberUtil.prototype.isLeadingZeroPossible =
3041 function(countryCallingCode) {
3042 /** @type {i18n.phonenumbers.PhoneMetadata} */
3043 var mainMetadataForCallingCode = this.getMetadataForRegionOrCallingCode_(
3045 this.getRegionCodeForCountryCode(countryCallingCode));
3046 return mainMetadataForCallingCode != null &&
3047 mainMetadataForCallingCode.getLeadingZeroPossibleOrDefault();
3052 * Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT.
3053 * A valid vanity number will start with at least 3 digits and will have three
3054 * or more alpha characters. This does not do region-specific checks - to work
3055 * out if this number is actually valid for a region, it should be parsed and
3056 * methods such as {@link #isPossibleNumberWithReason} and
3057 * {@link #isValidNumber} should be used.
3059 * @param {string} number the number that needs to be checked.
3060 * @return {boolean} true if the number is a valid vanity number.
3062 i18n.phonenumbers.PhoneNumberUtil.prototype.isAlphaNumber = function(number) {
3063 if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(number)) {
3064 // Number is too short, or doesn't match the basic phone number pattern.
3067 /** @type {!goog.string.StringBuffer} */
3068 var strippedNumber = new goog.string.StringBuffer(number);
3069 this.maybeStripExtension(strippedNumber);
3070 return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3071 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_,
3072 strippedNumber.toString());
3077 * Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of
3078 * returning the reason for failure, this method returns a boolean value.
3080 * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
3082 * @return {boolean} true if the number is possible.
3084 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumber =
3087 return this.isPossibleNumberWithReason(number) ==
3088 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
3093 * Helper method to check a number against a particular pattern and determine
3094 * whether it matches, or is too short or too long. Currently, if a number
3095 * pattern suggests that numbers of length 7 and 10 are possible, and a number
3096 * in between these possible lengths is entered, such as of length 8, this will
3099 * @param {string} numberPattern
3100 * @param {string} number
3101 * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult}
3104 i18n.phonenumbers.PhoneNumberUtil.prototype.testNumberLengthAgainstPattern_ =
3105 function(numberPattern, number) {
3106 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(numberPattern,
3108 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
3110 if (number.search(numberPattern) == 0) {
3111 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG;
3113 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
3119 * Helper method to check whether a number is too short to be a regular length
3120 * phone number in a region.
3122 * @param {i18n.phonenumbers.PhoneMetadata} regionMetadata
3123 * @param {string} number
3127 i18n.phonenumbers.PhoneNumberUtil.prototype.isShorterThanPossibleNormalNumber_ =
3128 function(regionMetadata, number) {
3129 /** @type {string} */
3130 var possibleNumberPattern =
3131 regionMetadata.getGeneralDesc().getPossibleNumberPatternOrDefault();
3132 return this.testNumberLengthAgainstPattern_(possibleNumberPattern, number) ==
3133 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
3138 * Check whether a phone number is a possible number. It provides a more lenient
3139 * check than {@link #isValidNumber} in the following sense:
3141 * <li>It only checks the length of phone numbers. In particular, it doesn't
3142 * check starting digits of the number.
3143 * <li>It doesn't attempt to figure out the type of the number, but uses general
3144 * rules which applies to all types of phone numbers in a region. Therefore, it
3145 * is much faster than isValidNumber.
3146 * <li>For fixed line numbers, many regions have the concept of area code, which
3147 * together with subscriber number constitute the national significant number.
3148 * It is sometimes okay to dial the subscriber number only when dialing in the
3149 * same area. This function will return true if the subscriber-number-only
3150 * version is passed in. On the other hand, because isValidNumber validates
3151 * using information on both starting digits (for fixed line numbers, that would
3152 * most likely be area codes) and length (obviously includes the length of area
3153 * codes for fixed line numbers), it will return false for the
3154 * subscriber-number-only version.
3157 * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
3159 * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult} a
3160 * ValidationResult object which indicates whether the number is possible.
3162 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason =
3165 /** @type {string} */
3166 var nationalNumber = this.getNationalSignificantNumber(number);
3167 /** @type {number} */
3168 var countryCode = number.getCountryCodeOrDefault();
3169 // Note: For Russian Fed and NANPA numbers, we just use the rules from the
3170 // default region (US or Russia) since the getRegionCodeForNumber will not
3171 // work if the number is possible but not valid. This would need to be
3172 // revisited if the possible number pattern ever differed between various
3173 // regions within those plans.
3174 if (!this.hasValidCountryCallingCode_(countryCode)) {
3175 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult
3176 .INVALID_COUNTRY_CODE;
3178 /** @type {string} */
3179 var regionCode = this.getRegionCodeForCountryCode(countryCode);
3180 // Metadata cannot be null because the country calling code is valid.
3181 /** @type {i18n.phonenumbers.PhoneMetadata} */
3183 this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
3184 /** @type {string} */
3185 var possibleNumberPattern =
3186 metadata.getGeneralDesc().getPossibleNumberPatternOrDefault();
3187 return this.testNumberLengthAgainstPattern_(possibleNumberPattern,
3193 * Check whether a phone number is a possible number given a number in the form
3194 * of a string, and the region where the number could be dialed from. It
3195 * provides a more lenient check than {@link #isValidNumber}. See
3196 * {@link #isPossibleNumber} for details.
3198 * <p>This method first parses the number, then invokes
3199 * {@link #isPossibleNumber} with the resultant PhoneNumber object.
3201 * @param {string} number the number that needs to be checked, in the form of a
3203 * @param {string} regionDialingFrom the region that we are expecting the number
3204 * to be dialed from.
3205 * Note this is different from the region where the number belongs.
3206 * For example, the number +1 650 253 0000 is a number that belongs to US.
3207 * When written in this form, it can be dialed from any region. When it is
3208 * written as 00 1 650 253 0000, it can be dialed from any region which uses
3209 * an international dialling prefix of 00. When it is written as
3210 * 650 253 0000, it can only be dialed from within the US, and when written
3211 * as 253 0000, it can only be dialed from within a smaller area in the US
3212 * (Mountain View, CA, to be more specific).
3213 * @return {boolean} true if the number is possible.
3215 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberString =
3216 function(number, regionDialingFrom) {
3219 return this.isPossibleNumber(this.parse(number, regionDialingFrom));
3227 * Attempts to extract a valid number from a phone number that is too long to be
3228 * valid, and resets the PhoneNumber object passed in to that valid version. If
3229 * no valid number could be extracted, the PhoneNumber object passed in will not
3231 * @param {i18n.phonenumbers.PhoneNumber} number a PhoneNumber object which
3232 * contains a number that is too long to be valid.
3233 * @return {boolean} true if a valid phone number can be successfully extracted.
3235 i18n.phonenumbers.PhoneNumberUtil.prototype.truncateTooLongNumber =
3238 if (this.isValidNumber(number)) {
3241 /** @type {i18n.phonenumbers.PhoneNumber} */
3242 var numberCopy = number.clone();
3243 /** @type {number} */
3244 var nationalNumber = number.getNationalNumberOrDefault();
3246 nationalNumber = Math.floor(nationalNumber / 10);
3247 numberCopy.setNationalNumber(nationalNumber);
3248 if (nationalNumber == 0 ||
3249 this.isPossibleNumberWithReason(numberCopy) ==
3250 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT) {
3253 } while (!this.isValidNumber(numberCopy));
3254 number.setNationalNumber(nationalNumber);
3260 * Extracts country calling code from fullNumber, returns it and places the
3261 * remaining number in nationalNumber. It assumes that the leading plus sign or
3262 * IDD has already been removed. Returns 0 if fullNumber doesn't start with a
3263 * valid country calling code, and leaves nationalNumber unmodified.
3265 * @param {!goog.string.StringBuffer} fullNumber
3266 * @param {!goog.string.StringBuffer} nationalNumber
3269 i18n.phonenumbers.PhoneNumberUtil.prototype.extractCountryCode =
3270 function(fullNumber, nationalNumber) {
3272 /** @type {string} */
3273 var fullNumberStr = fullNumber.toString();
3274 if ((fullNumberStr.length == 0) || (fullNumberStr.charAt(0) == '0')) {
3275 // Country codes do not begin with a '0'.
3278 /** @type {number} */
3279 var potentialCountryCode;
3280 /** @type {number} */
3281 var numberLength = fullNumberStr.length;
3283 i <= i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE_ &&
3284 i <= numberLength; ++i) {
3285 potentialCountryCode = parseInt(fullNumberStr.substring(0, i), 10);
3286 if (potentialCountryCode in
3287 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap) {
3288 nationalNumber.append(fullNumberStr.substring(i));
3289 return potentialCountryCode;
3297 * Tries to extract a country calling code from a number. This method will
3298 * return zero if no country calling code is considered to be present. Country
3299 * calling codes are extracted in the following ways:
3301 * <li>by stripping the international dialing prefix of the region the person is
3302 * dialing from, if this is present in the number, and looking at the next
3304 * <li>by stripping the '+' sign if present and then looking at the next digits
3305 * <li>by comparing the start of the number and the country calling code of the
3306 * default region. If the number is not considered possible for the numbering
3307 * plan of the default region initially, but starts with the country calling
3308 * code of this region, validation will be reattempted after stripping this
3309 * country calling code. If this number is considered a possible number, then
3310 * the first digits will be considered the country calling code and removed as
3314 * It will throw a i18n.phonenumbers.Error if the number starts with a '+' but
3315 * the country calling code supplied after this does not match that of any known
3318 * @param {string} number non-normalized telephone number that we wish to
3319 * extract a country calling code from - may begin with '+'.
3320 * @param {i18n.phonenumbers.PhoneMetadata} defaultRegionMetadata metadata
3321 * about the region this number may be from.
3322 * @param {!goog.string.StringBuffer} nationalNumber a string buffer to store
3323 * the national significant number in, in the case that a country calling
3324 * code was extracted. The number is appended to any existing contents. If
3325 * no country calling code was extracted, this will be left unchanged.
3326 * @param {boolean} keepRawInput true if the country_code_source and
3327 * preferred_carrier_code fields of phoneNumber should be populated.
3328 * @param {i18n.phonenumbers.PhoneNumber} phoneNumber the PhoneNumber object
3329 * where the country_code and country_code_source need to be populated.
3330 * Note the country_code is always populated, whereas country_code_source is
3331 * only populated when keepCountryCodeSource is true.
3332 * @return {number} the country calling code extracted or 0 if none could be
3334 * @throws {i18n.phonenumbers.Error}
3336 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode =
3337 function(number, defaultRegionMetadata, nationalNumber,
3338 keepRawInput, phoneNumber) {
3340 if (number.length == 0) {
3343 /** @type {!goog.string.StringBuffer} */
3344 var fullNumber = new goog.string.StringBuffer(number);
3345 // Set the default prefix to be something that will never match.
3346 /** @type {?string} */
3347 var possibleCountryIddPrefix;
3348 if (defaultRegionMetadata != null) {
3349 possibleCountryIddPrefix = defaultRegionMetadata.getInternationalPrefix();
3351 if (possibleCountryIddPrefix == null) {
3352 possibleCountryIddPrefix = 'NonMatch';
3355 /** @type {i18n.phonenumbers.PhoneNumber.CountryCodeSource} */
3356 var countryCodeSource = this.maybeStripInternationalPrefixAndNormalize(
3357 fullNumber, possibleCountryIddPrefix);
3359 phoneNumber.setCountryCodeSource(countryCodeSource);
3361 if (countryCodeSource !=
3362 i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY) {
3363 if (fullNumber.getLength() <=
3364 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3365 throw i18n.phonenumbers.Error.TOO_SHORT_AFTER_IDD;
3367 /** @type {number} */
3368 var potentialCountryCode = this.extractCountryCode(fullNumber,
3370 if (potentialCountryCode != 0) {
3371 phoneNumber.setCountryCode(potentialCountryCode);
3372 return potentialCountryCode;
3375 // If this fails, they must be using a strange country calling code that we
3376 // don't recognize, or that doesn't exist.
3377 throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
3378 } else if (defaultRegionMetadata != null) {
3379 // Check to see if the number starts with the country calling code for the
3380 // default region. If so, we remove the country calling code, and do some
3381 // checks on the validity of the number before and after.
3382 /** @type {number} */
3383 var defaultCountryCode = defaultRegionMetadata.getCountryCodeOrDefault();
3384 /** @type {string} */
3385 var defaultCountryCodeString = '' + defaultCountryCode;
3386 /** @type {string} */
3387 var normalizedNumber = fullNumber.toString();
3388 if (goog.string.startsWith(normalizedNumber, defaultCountryCodeString)) {
3389 /** @type {!goog.string.StringBuffer} */
3390 var potentialNationalNumber = new goog.string.StringBuffer(
3391 normalizedNumber.substring(defaultCountryCodeString.length));
3392 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
3393 var generalDesc = defaultRegionMetadata.getGeneralDesc();
3394 /** @type {!RegExp} */
3395 var validNumberPattern =
3396 new RegExp(generalDesc.getNationalNumberPatternOrDefault());
3397 // Passing null since we don't need the carrier code.
3398 this.maybeStripNationalPrefixAndCarrierCode(
3399 potentialNationalNumber, defaultRegionMetadata, null);
3400 /** @type {string} */
3401 var potentialNationalNumberStr = potentialNationalNumber.toString();
3402 /** @type {string} */
3403 var possibleNumberPattern =
3404 generalDesc.getPossibleNumberPatternOrDefault();
3405 // If the number was not valid before but is valid now, or if it was too
3406 // long before, we consider the number with the country calling code
3407 // stripped to be a better result and keep that instead.
3408 if ((!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3409 validNumberPattern, fullNumber.toString()) &&
3410 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3411 validNumberPattern, potentialNationalNumberStr)) ||
3412 this.testNumberLengthAgainstPattern_(possibleNumberPattern,
3413 fullNumber.toString()) ==
3414 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG) {
3415 nationalNumber.append(potentialNationalNumberStr);
3417 phoneNumber.setCountryCodeSource(
3418 i18n.phonenumbers.PhoneNumber.CountryCodeSource
3419 .FROM_NUMBER_WITHOUT_PLUS_SIGN);
3421 phoneNumber.setCountryCode(defaultCountryCode);
3422 return defaultCountryCode;
3426 // No country calling code present.
3427 phoneNumber.setCountryCode(0);
3433 * Strips the IDD from the start of the number if present. Helper function used
3434 * by maybeStripInternationalPrefixAndNormalize.
3436 * @param {!RegExp} iddPattern the regular expression for the international
3438 * @param {!goog.string.StringBuffer} number the phone number that we wish to
3439 * strip any international dialing prefix from.
3440 * @return {boolean} true if an international prefix was present.
3443 i18n.phonenumbers.PhoneNumberUtil.prototype.parsePrefixAsIdd_ =
3444 function(iddPattern, number) {
3446 /** @type {string} */
3447 var numberStr = number.toString();
3448 if (numberStr.search(iddPattern) == 0) {
3449 /** @type {number} */
3450 var matchEnd = numberStr.match(iddPattern)[0].length;
3451 /** @type {Array.<string>} */
3452 var matchedGroups = numberStr.substring(matchEnd).match(
3453 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN);
3454 if (matchedGroups && matchedGroups[1] != null &&
3455 matchedGroups[1].length > 0) {
3456 /** @type {string} */
3457 var normalizedGroup =
3458 i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(
3460 if (normalizedGroup == '0') {
3465 number.append(numberStr.substring(matchEnd));
3473 * Strips any international prefix (such as +, 00, 011) present in the number
3474 * provided, normalizes the resulting number, and indicates if an international
3475 * prefix was present.
3477 * @param {!goog.string.StringBuffer} number the non-normalized telephone number
3478 * that we wish to strip any international dialing prefix from.
3479 * @param {string} possibleIddPrefix the international direct dialing prefix
3480 * from the region we think this number may be dialed in.
3481 * @return {i18n.phonenumbers.PhoneNumber.CountryCodeSource} the corresponding
3482 * CountryCodeSource if an international dialing prefix could be removed
3483 * from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if
3484 * the number did not seem to be in international format.
3486 i18n.phonenumbers.PhoneNumberUtil.prototype.
3487 maybeStripInternationalPrefixAndNormalize = function(number,
3488 possibleIddPrefix) {
3489 /** @type {string} */
3490 var numberStr = number.toString();
3491 if (numberStr.length == 0) {
3492 return i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
3494 // Check to see if the number begins with one or more plus signs.
3495 if (i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_
3497 numberStr = numberStr.replace(
3498 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_, '');
3499 // Can now normalize the rest of the number since we've consumed the '+'
3500 // sign at the start.
3502 number.append(i18n.phonenumbers.PhoneNumberUtil.normalize(numberStr));
3503 return i18n.phonenumbers.PhoneNumber.CountryCodeSource
3504 .FROM_NUMBER_WITH_PLUS_SIGN;
3506 // Attempt to parse the first digits as an international prefix.
3507 /** @type {!RegExp} */
3508 var iddPattern = new RegExp(possibleIddPrefix);
3509 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(number);
3510 return this.parsePrefixAsIdd_(iddPattern, number) ?
3511 i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD :
3512 i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
3517 * Strips any national prefix (such as 0, 1) present in the number provided.
3519 * @param {!goog.string.StringBuffer} number the normalized telephone number
3520 * that we wish to strip any national dialing prefix from.
3521 * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
3522 * region that we think this number is from.
3523 * @param {goog.string.StringBuffer} carrierCode a place to insert the carrier
3524 * code if one is extracted.
3525 * @return {boolean} true if a national prefix or carrier code (or both) could
3528 i18n.phonenumbers.PhoneNumberUtil.prototype.
3529 maybeStripNationalPrefixAndCarrierCode = function(number, metadata,
3531 /** @type {string} */
3532 var numberStr = number.toString();
3533 /** @type {number} */
3534 var numberLength = numberStr.length;
3535 /** @type {?string} */
3536 var possibleNationalPrefix = metadata.getNationalPrefixForParsing();
3537 if (numberLength == 0 || possibleNationalPrefix == null ||
3538 possibleNationalPrefix.length == 0) {
3539 // Early return for numbers of zero length.
3542 // Attempt to parse the first digits as a national prefix.
3543 /** @type {!RegExp} */
3544 var prefixPattern = new RegExp('^(?:' + possibleNationalPrefix + ')');
3545 /** @type {Array.<string>} */
3546 var prefixMatcher = prefixPattern.exec(numberStr);
3547 if (prefixMatcher) {
3548 /** @type {!RegExp} */
3549 var nationalNumberRule = new RegExp(
3550 metadata.getGeneralDesc().getNationalNumberPatternOrDefault());
3551 // Check if the original number is viable.
3552 /** @type {boolean} */
3553 var isViableOriginalNumber =
3554 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3555 nationalNumberRule, numberStr);
3556 // prefixMatcher[numOfGroups] == null implies nothing was captured by the
3557 // capturing groups in possibleNationalPrefix; therefore, no transformation
3558 // is necessary, and we just remove the national prefix.
3559 /** @type {number} */
3560 var numOfGroups = prefixMatcher.length - 1;
3561 /** @type {?string} */
3562 var transformRule = metadata.getNationalPrefixTransformRule();
3563 /** @type {boolean} */
3564 var noTransform = transformRule == null || transformRule.length == 0 ||
3565 prefixMatcher[numOfGroups] == null ||
3566 prefixMatcher[numOfGroups].length == 0;
3568 // If the original number was viable, and the resultant number is not,
3570 if (isViableOriginalNumber &&
3571 !i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3573 numberStr.substring(prefixMatcher[0].length))) {
3576 if (carrierCode != null &&
3577 numOfGroups > 0 && prefixMatcher[numOfGroups] != null) {
3578 carrierCode.append(prefixMatcher[1]);
3580 number.set(numberStr.substring(prefixMatcher[0].length));
3583 // Check that the resultant number is still viable. If not, return. Check
3584 // this by copying the string buffer and making the transformation on the
3586 /** @type {string} */
3587 var transformedNumber;
3588 transformedNumber = numberStr.replace(prefixPattern, transformRule);
3589 if (isViableOriginalNumber &&
3590 !i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
3591 nationalNumberRule, transformedNumber)) {
3594 if (carrierCode != null && numOfGroups > 0) {
3595 carrierCode.append(prefixMatcher[1]);
3597 number.set(transformedNumber);
3606 * Strips any extension (as in, the part of the number dialled after the call is
3607 * connected, usually indicated with extn, ext, x or similar) from the end of
3608 * the number, and returns it.
3610 * @param {!goog.string.StringBuffer} number the non-normalized telephone number
3611 * that we wish to strip the extension from.
3612 * @return {string} the phone extension.
3614 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeStripExtension =
3617 /** @type {string} */
3618 var numberStr = number.toString();
3619 /** @type {number} */
3621 numberStr.search(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
3622 // If we find a potential extension, and the number preceding this is a viable
3623 // number, we assume it is an extension.
3624 if (mStart >= 0 && i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(
3625 numberStr.substring(0, mStart))) {
3626 // The numbers are captured into groups in the regular expression.
3627 /** @type {Array.<string>} */
3629 numberStr.match(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
3630 /** @type {number} */
3631 var matchedGroupsLength = matchedGroups.length;
3632 for (var i = 1; i < matchedGroupsLength; ++i) {
3633 if (matchedGroups[i] != null && matchedGroups[i].length > 0) {
3634 // We go through the capturing groups until we find one that captured
3635 // some digits. If none did, then we will return the empty string.
3637 number.append(numberStr.substring(0, mStart));
3638 return matchedGroups[i];
3647 * Checks to see that the region code used is valid, or if it is not valid, that
3648 * the number to parse starts with a + symbol so that we can attempt to infer
3649 * the region from the number.
3650 * @param {string} numberToParse number that we are attempting to parse.
3651 * @param {?string} defaultRegion region that we are expecting the number to be
3653 * @return {boolean} false if it cannot use the region provided and the region
3654 * cannot be inferred.
3657 i18n.phonenumbers.PhoneNumberUtil.prototype.checkRegionForParsing_ = function(
3658 numberToParse, defaultRegion) {
3659 // If the number is null or empty, we can't infer the region.
3660 return this.isValidRegionCode_(defaultRegion) ||
3661 (numberToParse != null && numberToParse.length > 0 &&
3662 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_.test(
3668 * Parses a string and returns it in proto buffer format. This method will throw
3669 * a {@link i18n.phonenumbers.Error} if the number is not considered to be a
3670 * possible number. Note that validation of whether the number is actually a
3671 * valid number for a particular region is not performed. This can be done
3672 * separately with {@link #isValidNumber}.
3674 * @param {?string} numberToParse number that we are attempting to parse. This
3675 * can contain formatting such as +, ( and -, as well as a phone number
3676 * extension. It can also be provided in RFC3966 format.
3677 * @param {?string} defaultRegion region that we are expecting the number to be
3678 * from. This is only used if the number being parsed is not written in
3679 * international format. The country_code for the number in this case would
3680 * be stored as that of the default region supplied. If the number is
3681 * guaranteed to start with a '+' followed by the country calling code, then
3682 * 'ZZ' or null can be supplied.
3683 * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
3684 * with the parsed number.
3685 * @throws {i18n.phonenumbers.Error} if the string is not considered to be a
3686 * viable phone number or if no default region was supplied and the number
3687 * is not in international format (does not start with +).
3689 i18n.phonenumbers.PhoneNumberUtil.prototype.parse = function(numberToParse,
3691 return this.parseHelper_(numberToParse, defaultRegion, false, true);
3696 * Parses a string and returns it in proto buffer format. This method differs
3697 * from {@link #parse} in that it always populates the raw_input field of the
3698 * protocol buffer with numberToParse as well as the country_code_source field.
3700 * @param {string} numberToParse number that we are attempting to parse. This
3701 * can contain formatting such as +, ( and -, as well as a phone number
3703 * @param {?string} defaultRegion region that we are expecting the number to be
3704 * from. This is only used if the number being parsed is not written in
3705 * international format. The country calling code for the number in this
3706 * case would be stored as that of the default region supplied.
3707 * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
3708 * with the parsed number.
3709 * @throws {i18n.phonenumbers.Error} if the string is not considered to be a
3710 * viable phone number or if no default region was supplied.
3712 i18n.phonenumbers.PhoneNumberUtil.prototype.parseAndKeepRawInput =
3713 function(numberToParse, defaultRegion) {
3715 if (!this.isValidRegionCode_(defaultRegion)) {
3716 if (numberToParse.length > 0 && numberToParse.charAt(0) !=
3717 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) {
3718 throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
3721 return this.parseHelper_(numberToParse, defaultRegion, true, true);
3726 * A helper function to set the values related to leading zeros in a
3729 * @param {string} nationalNumber the number we are parsing.
3730 * @param {i18n.phonenumbers.PhoneNumber} phoneNumber a phone number proto
3731 * buffer to fill in.
3734 i18n.phonenumbers.PhoneNumberUtil.prototype.setItalianLeadingZerosForPhoneNumber_ =
3735 function(nationalNumber, phoneNumber) {
3736 if (nationalNumber.length > 1 && nationalNumber.charAt(0) == '0') {
3737 phoneNumber.setItalianLeadingZero(true);
3738 var numberOfLeadingZeros = 1;
3739 // Note that if the national number is all "0"s, the last "0" is not counted
3740 // as a leading zero.
3741 while (numberOfLeadingZeros < nationalNumber.length - 1 &&
3742 nationalNumber.charAt(numberOfLeadingZeros) == '0') {
3743 numberOfLeadingZeros++;
3745 if (numberOfLeadingZeros != 1) {
3746 phoneNumber.setNumberOfLeadingZeros(numberOfLeadingZeros);
3753 * Parses a string and returns it in proto buffer format. This method is the
3754 * same as the public {@link #parse} method, with the exception that it allows
3755 * the default region to be null, for use by {@link #isNumberMatch}.
3757 * @param {?string} numberToParse number that we are attempting to parse. This
3758 * can contain formatting such as +, ( and -, as well as a phone number
3760 * @param {?string} defaultRegion region that we are expecting the number to be
3761 * from. This is only used if the number being parsed is not written in
3762 * international format. The country calling code for the number in this
3763 * case would be stored as that of the default region supplied.
3764 * @param {boolean} keepRawInput whether to populate the raw_input field of the
3765 * phoneNumber with numberToParse.
3766 * @param {boolean} checkRegion should be set to false if it is permitted for
3767 * the default coregion to be null or unknown ('ZZ').
3768 * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
3769 * with the parsed number.
3770 * @throws {i18n.phonenumbers.Error}
3773 i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ =
3774 function(numberToParse, defaultRegion, keepRawInput, checkRegion) {
3776 if (numberToParse == null) {
3777 throw i18n.phonenumbers.Error.NOT_A_NUMBER;
3778 } else if (numberToParse.length >
3779 i18n.phonenumbers.PhoneNumberUtil.MAX_INPUT_STRING_LENGTH_) {
3780 throw i18n.phonenumbers.Error.TOO_LONG;
3783 /** @type {!goog.string.StringBuffer} */
3784 var nationalNumber = new goog.string.StringBuffer();
3785 this.buildNationalNumberForParsing_(numberToParse, nationalNumber);
3787 if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(
3788 nationalNumber.toString())) {
3789 throw i18n.phonenumbers.Error.NOT_A_NUMBER;
3792 // Check the region supplied is valid, or that the extracted number starts
3793 // with some sort of + sign so the number's region can be determined.
3795 !this.checkRegionForParsing_(nationalNumber.toString(), defaultRegion)) {
3796 throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
3799 /** @type {i18n.phonenumbers.PhoneNumber} */
3800 var phoneNumber = new i18n.phonenumbers.PhoneNumber();
3802 phoneNumber.setRawInput(numberToParse);
3804 // Attempt to parse extension first, since it doesn't require region-specific
3805 // data and we want to have the non-normalised number here.
3806 /** @type {string} */
3807 var extension = this.maybeStripExtension(nationalNumber);
3808 if (extension.length > 0) {
3809 phoneNumber.setExtension(extension);
3812 /** @type {i18n.phonenumbers.PhoneMetadata} */
3813 var regionMetadata = this.getMetadataForRegion(defaultRegion);
3814 // Check to see if the number is given in international format so we know
3815 // whether this number is from the default region or not.
3816 /** @type {!goog.string.StringBuffer} */
3817 var normalizedNationalNumber = new goog.string.StringBuffer();
3818 /** @type {number} */
3819 var countryCode = 0;
3820 /** @type {string} */
3821 var nationalNumberStr = nationalNumber.toString();
3823 countryCode = this.maybeExtractCountryCode(nationalNumberStr,
3824 regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber);
3826 if (e == i18n.phonenumbers.Error.INVALID_COUNTRY_CODE &&
3827 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_
3828 .test(nationalNumberStr)) {
3829 // Strip the plus-char, and try again.
3830 nationalNumberStr = nationalNumberStr.replace(
3831 i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_, '');
3832 countryCode = this.maybeExtractCountryCode(nationalNumberStr,
3833 regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber);
3834 if (countryCode == 0) {
3841 if (countryCode != 0) {
3842 /** @type {string} */
3843 var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCode);
3844 if (phoneNumberRegion != defaultRegion) {
3845 // Metadata cannot be null because the country calling code is valid.
3846 regionMetadata = this.getMetadataForRegionOrCallingCode_(
3847 countryCode, phoneNumberRegion);
3850 // If no extracted country calling code, use the region supplied instead.
3851 // The national number is just the normalized version of the number we were
3853 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(nationalNumber);
3854 normalizedNationalNumber.append(nationalNumber.toString());
3855 if (defaultRegion != null) {
3856 countryCode = regionMetadata.getCountryCodeOrDefault();
3857 phoneNumber.setCountryCode(countryCode);
3858 } else if (keepRawInput) {
3859 phoneNumber.clearCountryCodeSource();
3862 if (normalizedNationalNumber.getLength() <
3863 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3864 throw i18n.phonenumbers.Error.TOO_SHORT_NSN;
3867 if (regionMetadata != null) {
3868 /** @type {!goog.string.StringBuffer} */
3869 var carrierCode = new goog.string.StringBuffer();
3870 /** @type {!goog.string.StringBuffer} */
3871 var potentialNationalNumber =
3872 new goog.string.StringBuffer(normalizedNationalNumber.toString());
3873 this.maybeStripNationalPrefixAndCarrierCode(
3874 potentialNationalNumber, regionMetadata, carrierCode);
3875 if (!this.isShorterThanPossibleNormalNumber_(
3876 regionMetadata, potentialNationalNumber.toString())) {
3877 normalizedNationalNumber = potentialNationalNumber;
3879 phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString());
3883 /** @type {string} */
3884 var normalizedNationalNumberStr = normalizedNationalNumber.toString();
3885 /** @type {number} */
3886 var lengthOfNationalNumber = normalizedNationalNumberStr.length;
3887 if (lengthOfNationalNumber <
3888 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3889 throw i18n.phonenumbers.Error.TOO_SHORT_NSN;
3891 if (lengthOfNationalNumber >
3892 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_) {
3893 throw i18n.phonenumbers.Error.TOO_LONG;
3895 this.setItalianLeadingZerosForPhoneNumber_(
3896 normalizedNationalNumberStr, phoneNumber);
3897 phoneNumber.setNationalNumber(parseInt(normalizedNationalNumberStr, 10));
3903 * Converts numberToParse to a form that we can parse and write it to
3904 * nationalNumber if it is written in RFC3966; otherwise extract a possible
3905 * number out of it and write to nationalNumber.
3907 * @param {?string} numberToParse number that we are attempting to parse. This
3908 * can contain formatting such as +, ( and -, as well as a phone number
3910 * @param {!goog.string.StringBuffer} nationalNumber a string buffer for storing
3911 * the national significant number.
3914 i18n.phonenumbers.PhoneNumberUtil.prototype.buildNationalNumberForParsing_ =
3915 function(numberToParse, nationalNumber) {
3917 /** @type {number} */
3918 var indexOfPhoneContext = numberToParse.indexOf(
3919 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_);
3920 if (indexOfPhoneContext > 0) {
3921 var phoneContextStart = indexOfPhoneContext +
3922 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_.length;
3923 // If the phone context contains a phone number prefix, we need to capture
3924 // it, whereas domains will be ignored.
3925 if (numberToParse.charAt(phoneContextStart) ==
3926 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) {
3927 // Additional parameters might follow the phone context. If so, we will
3928 // remove them here because the parameters after phone context are not
3929 // important for parsing the phone number.
3930 var phoneContextEnd = numberToParse.indexOf(';', phoneContextStart);
3931 if (phoneContextEnd > 0) {
3932 nationalNumber.append(numberToParse.substring(phoneContextStart,
3935 nationalNumber.append(numberToParse.substring(phoneContextStart));
3939 // Now append everything between the "tel:" prefix and the phone-context.
3940 // This should include the national number, an optional extension or
3941 // isdn-subaddress component. Note we also handle the case when "tel:" is
3942 // missing, as we have seen in some of the phone number inputs.
3943 // In that case, we append everything from the beginning.
3944 var indexOfRfc3966Prefix = numberToParse.indexOf(
3945 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_);
3946 var indexOfNationalNumber = (indexOfRfc3966Prefix >= 0) ?
3947 indexOfRfc3966Prefix +
3948 i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_.length : 0;
3949 nationalNumber.append(numberToParse.substring(indexOfNationalNumber,
3950 indexOfPhoneContext));
3952 // Extract a possible number from the string passed in (this strips leading
3953 // characters that could not be the start of a phone number.)
3954 nationalNumber.append(
3955 i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber(numberToParse));
3958 // Delete the isdn-subaddress and everything after it if it is present.
3959 // Note extension won't appear at the same time with isdn-subaddress
3960 // according to paragraph 5.3 of the RFC3966 spec,
3961 /** @type {string} */
3962 var nationalNumberStr = nationalNumber.toString();
3963 var indexOfIsdn = nationalNumberStr.indexOf(
3964 i18n.phonenumbers.PhoneNumberUtil.RFC3966_ISDN_SUBADDRESS_);
3965 if (indexOfIsdn > 0) {
3966 nationalNumber.clear();
3967 nationalNumber.append(nationalNumberStr.substring(0, indexOfIsdn));
3969 // If both phone context and isdn-subaddress are absent but other
3970 // parameters are present, the parameters are left in nationalNumber. This
3971 // is because we are concerned about deleting content from a potential
3972 // number string when there is no strong evidence that the number is
3973 // actually written in RFC3966.
3978 * Takes two phone numbers and compares them for equality.
3980 * <p>Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero
3981 * for Italian numbers and any extension present are the same. Returns NSN_MATCH
3982 * if either or both has no region specified, and the NSNs and extensions are
3983 * the same. Returns SHORT_NSN_MATCH if either or both has no region specified,
3984 * or the region specified is the same, and one NSN could be a shorter version
3985 * of the other number. This includes the case where one has an extension
3986 * specified, and the other does not. Returns NO_MATCH otherwise. For example,
3987 * the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH. The numbers
3988 * +1 345 657 1234 and 345 657 are a NO_MATCH.
3990 * @param {i18n.phonenumbers.PhoneNumber|string} firstNumberIn first number to
3991 * compare. If it is a string it can contain formatting, and can have
3992 * country calling code specified with + at the start.
3993 * @param {i18n.phonenumbers.PhoneNumber|string} secondNumberIn second number to
3994 * compare. If it is a string it can contain formatting, and can have
3995 * country calling code specified with + at the start.
3996 * @return {i18n.phonenumbers.PhoneNumberUtil.MatchType} NOT_A_NUMBER, NO_MATCH,
3997 * SHORT_NSN_MATCH, NSN_MATCH or EXACT_MATCH depending on the level of
3998 * equality of the two numbers, described in the method definition.
4000 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch =
4001 function(firstNumberIn, secondNumberIn) {
4003 // If the input arguements are strings parse them to a proto buffer format.
4004 // Else make copies of the phone numbers so that the numbers passed in are not
4006 /** @type {i18n.phonenumbers.PhoneNumber} */
4008 /** @type {i18n.phonenumbers.PhoneNumber} */
4010 if (typeof firstNumberIn == 'string') {
4011 // First see if the first number has an implicit country calling code, by
4012 // attempting to parse it.
4014 firstNumber = this.parse(
4015 firstNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
4017 if (e != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
4018 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
4020 // The first number has no country calling code. EXACT_MATCH is no longer
4021 // possible. We parse it as if the region was the same as that for the
4022 // second number, and if EXACT_MATCH is returned, we replace this with
4024 if (typeof secondNumberIn != 'string') {
4025 /** @type {string} */
4026 var secondNumberRegion = this.getRegionCodeForCountryCode(
4027 secondNumberIn.getCountryCodeOrDefault());
4028 if (secondNumberRegion !=
4029 i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_) {
4031 firstNumber = this.parse(firstNumberIn, secondNumberRegion);
4033 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
4035 /** @type {i18n.phonenumbers.PhoneNumberUtil.MatchType} */
4036 var match = this.isNumberMatch(firstNumber, secondNumberIn);
4038 i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH) {
4039 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
4044 // If the second number is a string or doesn't have a valid country
4045 // calling code, we parse the first number without country calling code.
4047 firstNumber = this.parseHelper_(firstNumberIn, null, false, false);
4049 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
4053 firstNumber = firstNumberIn.clone();
4055 if (typeof secondNumberIn == 'string') {
4057 secondNumber = this.parse(
4058 secondNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
4059 return this.isNumberMatch(firstNumberIn, secondNumber);
4061 if (e != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
4062 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
4064 return this.isNumberMatch(secondNumberIn, firstNumber);
4067 secondNumber = secondNumberIn.clone();
4069 // First clear raw_input, country_code_source and
4070 // preferred_domestic_carrier_code fields and any empty-string extensions so
4071 // that we can use the proto-buffer equality method.
4072 firstNumber.clearRawInput();
4073 firstNumber.clearCountryCodeSource();
4074 firstNumber.clearPreferredDomesticCarrierCode();
4075 secondNumber.clearRawInput();
4076 secondNumber.clearCountryCodeSource();
4077 secondNumber.clearPreferredDomesticCarrierCode();
4078 if (firstNumber.hasExtension() && firstNumber.getExtension().length == 0) {
4079 firstNumber.clearExtension();
4081 if (secondNumber.hasExtension() && secondNumber.getExtension().length == 0) {
4082 secondNumber.clearExtension();
4085 // Early exit if both had extensions and these are different.
4086 if (firstNumber.hasExtension() && secondNumber.hasExtension() &&
4087 firstNumber.getExtension() != secondNumber.getExtension()) {
4088 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
4090 /** @type {number} */
4091 var firstNumberCountryCode = firstNumber.getCountryCodeOrDefault();
4092 /** @type {number} */
4093 var secondNumberCountryCode = secondNumber.getCountryCodeOrDefault();
4094 // Both had country_code specified.
4095 if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) {
4096 if (firstNumber.equals(secondNumber)) {
4097 return i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH;
4098 } else if (firstNumberCountryCode == secondNumberCountryCode &&
4099 this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
4100 // A SHORT_NSN_MATCH occurs if there is a difference because of the
4101 // presence or absence of an 'Italian leading zero', the presence or
4102 // absence of an extension, or one NSN being a shorter variant of the
4104 return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
4106 // This is not a match.
4107 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
4109 // Checks cases where one or both country_code fields were not specified. To
4110 // make equality checks easier, we first set the country_code fields to be
4112 firstNumber.setCountryCode(0);
4113 secondNumber.setCountryCode(0);
4114 // If all else was the same, then this is an NSN_MATCH.
4115 if (firstNumber.equals(secondNumber)) {
4116 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
4118 if (this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
4119 return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
4121 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
4126 * Returns true when one national number is the suffix of the other or both are
4129 * @param {i18n.phonenumbers.PhoneNumber} firstNumber the first PhoneNumber
4131 * @param {i18n.phonenumbers.PhoneNumber} secondNumber the second PhoneNumber
4133 * @return {boolean} true if one PhoneNumber is the suffix of the other one.
4136 i18n.phonenumbers.PhoneNumberUtil.prototype.isNationalNumberSuffixOfTheOther_ =
4137 function(firstNumber, secondNumber) {
4139 /** @type {string} */
4140 var firstNumberNationalNumber = '' + firstNumber.getNationalNumber();
4141 /** @type {string} */
4142 var secondNumberNationalNumber = '' + secondNumber.getNationalNumber();
4143 // Note that endsWith returns true if the numbers are equal.
4144 return goog.string.endsWith(firstNumberNationalNumber,
4145 secondNumberNationalNumber) ||
4146 goog.string.endsWith(secondNumberNationalNumber,
4147 firstNumberNationalNumber);
4152 * Returns true if the number can be dialled from outside the region, or
4153 * unknown. If the number can only be dialled from within the region, returns
4154 * false. Does not check the number is a valid number.
4155 * TODO: Make this method public when we have enough metadata to make it
4156 * worthwhile. Currently visible for testing purposes only.
4158 * @param {i18n.phonenumbers.PhoneNumber} number the phone-number for which we
4159 * want to know whether it is diallable from outside the region.
4160 * @return {boolean} true if the number can only be dialled from within the
4163 i18n.phonenumbers.PhoneNumberUtil.prototype.canBeInternationallyDialled =
4165 /** @type {i18n.phonenumbers.PhoneMetadata} */
4166 var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
4167 if (metadata == null) {
4168 // Note numbers belonging to non-geographical entities (e.g. +800 numbers)
4169 // are always internationally diallable, and will be caught here.
4172 /** @type {string} */
4173 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
4174 return !this.isNumberMatchingDesc_(nationalSignificantNumber,
4175 metadata.getNoInternationalDialling());
4180 * Check whether the entire input sequence can be matched against the regular
4183 * @param {!RegExp|string} regex the regular expression to match against.
4184 * @param {string} str the string to test.
4185 * @return {boolean} true if str can be matched entirely against regex.
4188 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_ = function(regex, str) {
4189 /** @type {Array.<string>} */
4190 var matchedGroups = (typeof regex == 'string') ?
4191 str.match('^(?:' + regex + ')$') : str.match(regex);
4192 if (matchedGroups && matchedGroups[0].length == str.length) {