3 * Copyright (C) 2010 Google Inc.
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 * @author Nikolaos Trogkanis
26 goog.provide('i18n.phonenumbers.Error');
27 goog.provide('i18n.phonenumbers.PhoneNumberFormat');
28 goog.provide('i18n.phonenumbers.PhoneNumberType');
29 goog.provide('i18n.phonenumbers.PhoneNumberUtil');
31 goog.require('goog.array');
32 goog.require('goog.proto2.PbLiteSerializer');
33 goog.require('goog.string');
34 goog.require('goog.string.StringBuffer');
35 goog.require('i18n.phonenumbers.NumberFormat');
36 goog.require('i18n.phonenumbers.PhoneMetadata');
37 goog.require('i18n.phonenumbers.PhoneMetadataCollection');
38 goog.require('i18n.phonenumbers.PhoneNumber');
39 goog.require('i18n.phonenumbers.PhoneNumber.CountryCodeSource');
40 goog.require('i18n.phonenumbers.PhoneNumberDesc');
41 goog.require('i18n.phonenumbers.metadata');
49 i18n.phonenumbers.PhoneNumberUtil = function() {
51 * A mapping from a region code to the PhoneMetadata for that region.
52 * @type {Object.<string, i18n.phonenumbers.PhoneMetadata>}
54 this.regionToMetadataMap = {};
56 goog.addSingletonGetter(i18n.phonenumbers.PhoneNumberUtil);
60 * Errors encountered when parsing phone numbers.
64 i18n.phonenumbers.Error = {
65 INVALID_COUNTRY_CODE: 'Invalid country calling code',
66 // This generally indicates the string passed in had less than 3 digits in it.
67 // More specifically, the number failed to match the regular expression
68 // VALID_PHONE_NUMBER.
69 NOT_A_NUMBER: 'The string supplied did not seem to be a phone number',
70 // This indicates the string started with an international dialing prefix, but
71 // after this was stripped from the number, had less digits than any valid
72 // phone number (including country calling code) could have.
73 TOO_SHORT_AFTER_IDD: 'Phone number too short after IDD',
74 // This indicates the string, after any country calling code has been
75 // stripped, had less digits than any valid phone number could have.
76 TOO_SHORT_NSN: 'The string supplied is too short to be a phone number',
77 // This indicates the string had more digits than any valid phone number could
79 TOO_LONG: 'The string supplied is too long to be a phone number'
88 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_ = 1;
92 * The minimum length of the national significant number.
98 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ = 3;
102 * The maximum length of the national significant number.
108 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_ = 15;
112 * The maximum length of the country calling code.
118 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE_ = 3;
122 * Region-code for the unknown region.
128 i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ = 'ZZ';
132 * The PLUS_SIGN signifies the international prefix.
137 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN = '+';
141 * The RFC 3966 format for extensions.
147 i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ = ';ext=';
151 * These mappings map a character (key) to a specific digit that should replace
152 * it for normalization purposes. Non-European digits that may be used in phone
153 * numbers are mapped to a European equivalent.
156 * @type {!Object.<string, string>}
158 i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS = {
169 '\uFF10': '0', // Fullwidth digit 0
170 '\uFF11': '1', // Fullwidth digit 1
171 '\uFF12': '2', // Fullwidth digit 2
172 '\uFF13': '3', // Fullwidth digit 3
173 '\uFF14': '4', // Fullwidth digit 4
174 '\uFF15': '5', // Fullwidth digit 5
175 '\uFF16': '6', // Fullwidth digit 6
176 '\uFF17': '7', // Fullwidth digit 7
177 '\uFF18': '8', // Fullwidth digit 8
178 '\uFF19': '9', // Fullwidth digit 9
179 '\u0660': '0', // Arabic-indic digit 0
180 '\u0661': '1', // Arabic-indic digit 1
181 '\u0662': '2', // Arabic-indic digit 2
182 '\u0663': '3', // Arabic-indic digit 3
183 '\u0664': '4', // Arabic-indic digit 4
184 '\u0665': '5', // Arabic-indic digit 5
185 '\u0666': '6', // Arabic-indic digit 6
186 '\u0667': '7', // Arabic-indic digit 7
187 '\u0668': '8', // Arabic-indic digit 8
188 '\u0669': '9', // Arabic-indic digit 9
189 '\u06F0': '0', // Eastern-Arabic digit 0
190 '\u06F1': '1', // Eastern-Arabic digit 1
191 '\u06F2': '2', // Eastern-Arabic digit 2
192 '\u06F3': '3', // Eastern-Arabic digit 3
193 '\u06F4': '4', // Eastern-Arabic digit 4
194 '\u06F5': '5', // Eastern-Arabic digit 5
195 '\u06F6': '6', // Eastern-Arabic digit 6
196 '\u06F7': '7', // Eastern-Arabic digit 7
197 '\u06F8': '8', // Eastern-Arabic digit 8
198 '\u06F9': '9' // Eastern-Arabic digit 9
203 * Only upper-case variants of alpha characters are stored.
206 * @type {!Object.<string, string>}
209 i18n.phonenumbers.PhoneNumberUtil.ALPHA_MAPPINGS_ = {
240 * For performance reasons, amalgamate both into one map.
243 * @type {!Object.<string, string>}
246 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_ = {
257 '\uFF10': '0', // Fullwidth digit 0
258 '\uFF11': '1', // Fullwidth digit 1
259 '\uFF12': '2', // Fullwidth digit 2
260 '\uFF13': '3', // Fullwidth digit 3
261 '\uFF14': '4', // Fullwidth digit 4
262 '\uFF15': '5', // Fullwidth digit 5
263 '\uFF16': '6', // Fullwidth digit 6
264 '\uFF17': '7', // Fullwidth digit 7
265 '\uFF18': '8', // Fullwidth digit 8
266 '\uFF19': '9', // Fullwidth digit 9
267 '\u0660': '0', // Arabic-indic digit 0
268 '\u0661': '1', // Arabic-indic digit 1
269 '\u0662': '2', // Arabic-indic digit 2
270 '\u0663': '3', // Arabic-indic digit 3
271 '\u0664': '4', // Arabic-indic digit 4
272 '\u0665': '5', // Arabic-indic digit 5
273 '\u0666': '6', // Arabic-indic digit 6
274 '\u0667': '7', // Arabic-indic digit 7
275 '\u0668': '8', // Arabic-indic digit 8
276 '\u0669': '9', // Arabic-indic digit 9
277 '\u06F0': '0', // Eastern-Arabic digit 0
278 '\u06F1': '1', // Eastern-Arabic digit 1
279 '\u06F2': '2', // Eastern-Arabic digit 2
280 '\u06F3': '3', // Eastern-Arabic digit 3
281 '\u06F4': '4', // Eastern-Arabic digit 4
282 '\u06F5': '5', // Eastern-Arabic digit 5
283 '\u06F6': '6', // Eastern-Arabic digit 6
284 '\u06F7': '7', // Eastern-Arabic digit 7
285 '\u06F8': '8', // Eastern-Arabic digit 8
286 '\u06F9': '9', // Eastern-Arabic digit 9
317 * Separate map of all symbols that we wish to retain when formatting alpha
318 * numbers. This includes digits, ASCII letters and number grouping symbols such
322 * @type {!Object.<string, string>}
325 i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_ = {
408 * Pattern that makes it easy to distinguish whether a region has a unique
409 * international dialing prefix or not. If a region has a unique international
410 * prefix (e.g. 011 in USA), it will be represented as a string that contains a
411 * sequence of ASCII digits. If there are multiple available international
412 * prefixes in a region, they will be represented as a regex string that always
413 * contains character(s) other than ASCII digits. Note this regex also includes
414 * tilde, which signals waiting for the tone.
420 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_ =
421 /[\d]+(?:[~\u2053\u223C\uFF5E][\d]+)?/;
425 * Regular expression of acceptable punctuation found in phone numbers. This
426 * excludes punctuation found as a leading character only. This consists of dash
427 * characters, white space characters, full stops, slashes, square brackets,
428 * parentheses and tildes. It also includes the letter 'x' as that is found as a
429 * placeholder for carrier information in some phone numbers.
434 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION =
435 '-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F \u00A0\u200B\u2060\u3000()' +
436 '\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E';
440 * Digits accepted in phone numbers (ascii, fullwidth, arabic-indic, and eastern
447 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ =
448 '0-9\uFF10-\uFF19\u0660-\u0669\u06F0-\u06F9';
452 * We accept alpha characters in phone numbers, ASCII only, upper and lower
459 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ = 'A-Za-z';
467 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ = '+\uFF0B';
475 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN_ =
476 new RegExp('^[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']+');
484 i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_ =
485 new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
494 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN_ =
495 new RegExp('([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + '])');
499 * Regular expression of acceptable characters that may start a phone number for
500 * the purposes of parsing. This allows us to strip away meaningless prefixes to
501 * phone numbers that may be mistakenly given to us. This consists of digits,
502 * the plus symbol and arabic-indic digits. This does not contain alpha
503 * characters, although they may be used later in the number. It also does not
504 * include other punctuation, as this will be stripped later during parsing and
505 * is of no information value when parsing a number.
510 i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN =
511 new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ +
512 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']');
516 * Regular expression of characters typically used to start a second phone
517 * number for the purposes of parsing. This allows us to strip off parts of the
518 * number that are actually the start of another number, such as for:
519 * (530) 583-6985 x302/x2303 -> the second extension here makes this actually
520 * two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove
521 * the second extension so that the first number is parsed correctly.
527 i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_ = /[\\\/] *x/;
531 * Regular expression of trailing characters that we want to remove. We remove
532 * all characters that are not alpha or numerical characters. The hash character
533 * is retained here, as it may signify the previous block was an extension.
539 i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_ =
540 new RegExp('[^' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ +
541 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ + '#]+$');
545 * We use this pattern to check if the phone number has at least three letters
546 * in it - if so, then we treat it as a number where some phone-number digits
547 * are represented by letters.
553 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_ =
554 /(?:.*?[A-Za-z]){3}.*/;
558 * Regular expression of viable phone numbers. This is location independent.
559 * Checks we have at least three leading digits, and only valid punctuation,
560 * alpha characters and digits in the phone number. Does not include extension
561 * data. The symbol 'x' is allowed here as valid punctuation since it is often
562 * used as a placeholder for carrier codes, for example in Brazilian phone
563 * numbers. We also allow multiple '+' characters at the start.
564 * Corresponds to the following:
565 * plus_sign*([punctuation]*[digits]){3,}([punctuation]|[digits]|[alpha])*
566 * Note VALID_PUNCTUATION starts with a -, so must be the first in the range.
572 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ =
573 '[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']*(?:[' +
574 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION + ']*[' +
575 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']){3,}[' +
576 i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
577 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ +
578 i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']*';
582 * Default extension prefix to use when formatting. This will be put in front of
583 * any extension component of the number, after the main national number is
584 * formatted. For example, if you wish the default extension formatting to be
585 * ' extn: 3456', then you should specify ' extn: ' here as the default
586 * extension prefix. This can be overridden by region-specific preferences.
592 i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ = ' ext. ';
600 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ =
601 '([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,7})';
605 * Regexp of all possible ways to write extensions, for use when parsing. This
606 * will be run as a case-insensitive regexp match. Wide character versions are
607 * also provided after each ASCII version. There are three regular expressions
608 * here. The first covers RFC 3966 format, where the extension is added using
609 * ';ext='. The second more generic one starts with optional white space and
610 * ends with an optional full stop (.), followed by zero or more spaces/tabs and
611 * then the numbers themselves. The other one covers the special case of
612 * American numbers where the extension is written with a hash at the end, such
613 * as '- 503#'. Note that the only capturing groups should be around the digits
614 * that you want to capture as part of the extension, or else parsing will fail!
615 * We allow two options for representing the accented o - the character itself,
616 * and one in the unicode decomposed form with the combining acute accent.
622 i18n.phonenumbers.PhoneNumberUtil.KNOWN_EXTN_PATTERNS_ =
623 i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
624 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '|' +
626 '(?:ext(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45\uFF58\uFF54\uFF4E?|' +
627 '[,x\uFF58#\uFF03~\uFF5E]|int|anexo|\uFF49\uFF4E\uFF54)' +
628 '[:\\.\uFF0E]?[ \u00A0\\t,-]*' +
629 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '#?|' +
630 '[- ]+([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,5})#';
634 * Regexp of all known extension prefixes used by different regions followed by
635 * 1 or more valid digits, for use when parsing.
641 i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_ =
642 new RegExp('(?:' + i18n.phonenumbers.PhoneNumberUtil.KNOWN_EXTN_PATTERNS_ +
647 * We append optionally the extension pattern to the end here, as a valid phone
648 * number may have an extension prefix appended, followed by 1 or more digits.
654 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_ =
655 new RegExp('^' + i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ +
656 '(?:' + i18n.phonenumbers.PhoneNumberUtil.KNOWN_EXTN_PATTERNS_ +
665 i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_ = /\D+/;
669 * This was originally set to $1 but there are some countries for which the
670 * first group is not used in the national pattern (e.g. Argentina) so the $1
671 * group does not match correctly. Therefore, we use \d, so that the first
672 * group actually used in the pattern will be matched.
677 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_ = /(\$\d)/;
685 i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_ = /\$NP/;
693 i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_ = /\$FG/;
701 i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_ = /\$CC/;
705 * INTERNATIONAL and NATIONAL formats are consistent with the definition in
706 * ITU-T Recommendation E. 123. For example, the number of the Google Zurich
707 * office will be written as '+41 44 668 1800' in INTERNATIONAL format, and as
708 * '044 668 1800' in NATIONAL format. E164 format is as per INTERNATIONAL format
709 * but with no formatting applied, e.g. +41446681800. RFC3966 is as per
710 * INTERNATIONAL format, but with all spaces and other separating symbols
711 * replaced with a hyphen, and with any phone number extension appended with
714 * Note: If you are considering storing the number in a neutral format, you are
715 * highly advised to use the PhoneNumber class.
718 i18n.phonenumbers.PhoneNumberFormat = {
727 * Type of phone numbers.
731 i18n.phonenumbers.PhoneNumberType = {
734 // In some regions (e.g. the USA), it is impossible to distinguish between
735 // fixed-line and mobile numbers by looking at the phone number itself.
736 FIXED_LINE_OR_MOBILE: 2,
740 // The cost of this call is shared between the caller and the recipient, and
741 // is hence typically less than PREMIUM_RATE calls. See
742 // http://en.wikipedia.org/wiki/Shared_Cost_Service for more information.
744 // Voice over IP numbers. This includes TSoIP (Telephony Service over IP).
746 // A personal number is associated with a particular person, and may be routed
747 // to either a MOBILE or FIXED_LINE number. Some more information can be found
748 // here: http://en.wikipedia.org/wiki/Personal_Numbers
751 // Used for 'Universal Access Numbers' or 'Company Numbers'. They may be
752 // further routed to specific offices, but allow one number to be used for a
755 // A phone number is of type UNKNOWN when it does not fit any of the known
756 // patterns for a specific region.
762 * Types of phone number matches. See detailed description beside the
763 * isNumberMatch() method.
767 i18n.phonenumbers.PhoneNumberUtil.MatchType = {
777 * Possible outcomes when testing if a PhoneNumber is possible.
781 i18n.phonenumbers.PhoneNumberUtil.ValidationResult = {
783 INVALID_COUNTRY_CODE: 1,
790 * Attempts to extract a possible number from the string passed in. This
791 * currently strips all leading characters that cannot be used to start a phone
792 * number. Characters that can be used to start a phone number are defined in
793 * the VALID_START_CHAR_PATTERN. If none of these characters are found in the
794 * number passed in, an empty string is returned. This function also attempts to
795 * strip off any alternative extensions or endings if two or more are present,
796 * such as in the case of: (530) 583-6985 x302/x2303. The second extension here
797 * makes this actually two phone numbers, (530) 583-6985 x302 and (530) 583-6985
798 * x2303. We remove the second extension so that the first number is parsed
801 * @param {string} number the string that might contain a phone number.
802 * @return {string} the number, stripped of any non-phone-number prefix (such as
803 * 'Tel:') or an empty string if no character used to start phone numbers
804 * (such as + or any digit) is found in the number.
806 i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber = function(number) {
807 /** @type {string} */
810 /** @type {number} */
812 .search(i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN);
814 possibleNumber = number.substring(start);
815 // Remove trailing non-alpha non-numerical characters.
816 possibleNumber = possibleNumber.replace(
817 i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_, '');
819 // Check for extra numbers at the end.
820 /** @type {number} */
821 var secondNumberStart = possibleNumber
822 .search(i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_);
823 if (secondNumberStart >= 0) {
824 possibleNumber = possibleNumber.substring(0, secondNumberStart);
829 return possibleNumber;
834 * Checks to see if the string of characters could possibly be a phone number at
835 * all. At the moment, checks to see that the string begins with at least 3
836 * digits, ignoring any punctuation commonly found in phone numbers. This method
837 * does not require the number to be normalized in advance - but does assume
838 * that leading non-number symbols have been removed, such as by the method
839 * extractPossibleNumber.
841 * @param {string} number string to be checked for viability as a phone number.
842 * @return {boolean} true if the number could be a phone number of some sort,
845 i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber = function(number) {
846 if (number.length < i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
849 return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
850 i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_, number);
855 * Normalizes a string of characters representing a phone number. This performs
856 * the following conversions:
857 * - Wide-ascii digits are converted to normal ASCII (European) digits.
858 * - Letters are converted to their numeric representation on a telephone
859 * keypad. The keypad used here is the one defined in ITU Recommendation E.161.
860 * This is only done if there are 3 or more letters in the number, to lessen the
861 * risk that such letters are typos - otherwise alpha characters are stripped.
862 * - Punctuation is stripped.
863 * - Arabic-Indic numerals are converted to European numerals.
865 * @param {string} number a string of characters representing a phone number.
866 * @return {string} the normalized string version of the phone number.
868 i18n.phonenumbers.PhoneNumberUtil.normalize = function(number) {
869 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
870 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_, number)) {
871 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
872 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, true);
874 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
875 i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS, true);
881 * Normalizes a string of characters representing a phone number. This is a
882 * wrapper for normalize(String number) but does in-place normalization of the
883 * StringBuffer provided.
885 * @param {!goog.string.StringBuffer} number a StringBuffer of characters
886 * representing a phone number that will be normalized in place.
889 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_ = function(number) {
890 /** @type {string} */
891 var normalizedNumber = i18n.phonenumbers.PhoneNumberUtil.normalize(number
894 number.append(normalizedNumber);
899 * Normalizes a string of characters representing a phone number. This converts
900 * wide-ascii and arabic-indic numerals to European numerals, and strips
901 * punctuation and alpha characters.
903 * @param {string} number a string of characters representing a phone number.
904 * @return {string} the normalized string version of the phone number.
906 i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly = function(number) {
907 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
908 i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS, true);
913 * Converts all alpha characters in a number to their respective digits on a
914 * keypad, but retains existing formatting. Also converts wide-ascii digits to
915 * normal ascii digits, and converts Arabic-Indic numerals to European numerals.
917 * @param {string} number a string of characters representing a phone number.
918 * @return {string} the normalized string version of the phone number.
920 i18n.phonenumbers.PhoneNumberUtil.convertAlphaCharactersInNumber =
923 return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
924 i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, false);
929 * Gets the length of the geographical area code in the {@code national_number}
930 * field of the PhoneNumber object passed in, so that clients could use it to
931 * split a national significant number into geographical area code and
932 * subscriber number. It works in such a way that the resultant subscriber
933 * number should be diallable, at least on some devices. An example of how this
937 * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
938 * var number = phoneUtil.parse('16502530000', 'US');
939 * var nationalSignificantNumber =
940 * phoneUtil.getNationalSignificantNumber(number);
942 * var subscriberNumber;
944 * var areaCodeLength = phoneUtil.getLengthOfGeographicalAreaCode(number);
945 * if (areaCodeLength > 0) {
946 * areaCode = nationalSignificantNumber.substring(0, areaCodeLength);
947 * subscriberNumber = nationalSignificantNumber.substring(areaCodeLength);
950 * subscriberNumber = nationalSignificantNumber;
954 * N.B.: area code is a very ambiguous concept, so the I18N team generally
955 * recommends against using it for most purposes. Read the following carefully
956 * before deciding to use this method:
958 * - geographical area codes change over time, and this method honors those
959 * changes; therefore, it doesn't guarantee the stability of the result it
961 * - subscriber numbers may not be diallable from all devices (notably mobile
962 * devices, which typically requires the full national_number to be dialled in
964 * - most non-geographical numbers have no area codes.
965 * - some geographical numbers have no area codes.
967 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
968 * which clients want to know the length of the area code.
969 * @return {number} the length of area code of the PhoneNumber object passed in.
971 i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfGeographicalAreaCode =
974 if (number == null) {
977 /** @type {?string} */
978 var regionCode = this.getRegionCodeForNumber(number);
979 if (!this.isValidRegionCode_(regionCode)) {
982 /** @type {i18n.phonenumbers.PhoneMetadata} */
983 var metadata = this.getMetadataForRegion(regionCode);
984 if (!metadata.hasNationalPrefix()) {
988 /** @type {i18n.phonenumbers.PhoneNumberType} */
989 var type = this.getNumberTypeHelper_(
990 this.getNationalSignificantNumber(number), metadata);
991 // Most numbers other than the two types below have to be dialled in full.
992 if (type != i18n.phonenumbers.PhoneNumberType.FIXED_LINE &&
993 type != i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE) {
997 return this.getLengthOfNationalDestinationCode(number);
1002 * Gets the length of the national destination code (NDC) from the PhoneNumber
1003 * object passed in, so that clients could use it to split a national
1004 * significant number into NDC and subscriber number. The NDC of a phone number
1005 * is normally the first group of digit(s) right after the country calling code
1006 * when the number is formatted in the international format, if there is a
1007 * subscriber number part that follows. An example of how this could be used:
1010 * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
1011 * var number = phoneUtil.parse('18002530000', 'US');
1012 * var nationalSignificantNumber =
1013 * phoneUtil.getNationalSignificantNumber(number);
1014 * var nationalDestinationCode;
1015 * var subscriberNumber;
1017 * var nationalDestinationCodeLength =
1018 * phoneUtil.getLengthOfNationalDestinationCode(number);
1019 * if (nationalDestinationCodeLength > 0) {
1020 * nationalDestinationCode =
1021 * nationalSignificantNumber.substring(0, nationalDestinationCodeLength);
1022 * subscriberNumber =
1023 * nationalSignificantNumber.substring(nationalDestinationCodeLength);
1025 * nationalDestinationCode = '';
1026 * subscriberNumber = nationalSignificantNumber;
1030 * Refer to the unittests to see the difference between this function and
1031 * {@link #getLengthOfGeographicalAreaCode}.
1033 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
1034 * which clients want to know the length of the NDC.
1035 * @return {number} the length of NDC of the PhoneNumber object passed in.
1037 i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfNationalDestinationCode =
1040 /** @type {i18n.phonenumbers.PhoneNumber} */
1042 if (number.hasExtension()) {
1043 // We don't want to alter the proto given to us, but we don't want to
1044 // include the extension when we format it, so we copy it and clear the
1046 copiedProto = number.clone();
1047 copiedProto.clearExtension();
1049 copiedProto = number;
1052 /** @type {string} */
1053 var nationalSignificantNumber = this.format(copiedProto,
1054 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1055 /** @type {!Array.<string>} */
1056 var numberGroups = nationalSignificantNumber.split(
1057 i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_);
1058 // The pattern will start with '+COUNTRY_CODE ' so the first group will always
1059 // be the empty string (before the + symbol) and the second group will be the
1060 // country calling code. The third group will be area code if it is not the
1062 // NOTE: On IE the first group that is supposed to be the empty string does
1063 // not appear in the array of number groups... so make the result on non-IE
1064 // browsers to be that of IE.
1065 if (numberGroups[0].length == 0) {
1066 numberGroups.shift();
1068 if (numberGroups.length <= 2) {
1072 if (this.getRegionCodeForNumber(number) == 'AR' &&
1073 this.getNumberType(number) == i18n.phonenumbers.PhoneNumberType.MOBILE) {
1074 // Argentinian mobile numbers, when formatted in the international format,
1075 // are in the form of +54 9 NDC XXXX.... As a result, we take the length of
1076 // the third group (NDC) and add 1 for the digit 9, which also forms part of
1077 // the national significant number.
1079 // TODO: Investigate the possibility of better modeling the metadata to make
1080 // it easier to obtain the NDC.
1081 return numberGroups[2].length + 1;
1083 return numberGroups[1].length;
1088 * Normalizes a string of characters representing a phone number by replacing
1089 * all characters found in the accompanying map with the values therein, and
1090 * stripping all other characters if removeNonMatches is true.
1092 * @param {string} number a string of characters representing a phone number.
1093 * @param {!Object.<string, string>} normalizationReplacements a mapping of
1094 * characters to what they should be replaced by in the normalized version
1095 * of the phone number.
1096 * @param {boolean} removeNonMatches indicates whether characters that are not
1097 * able to be replaced should be stripped from the number. If this is false,
1098 * they will be left unchanged in the number.
1099 * @return {string} the normalized string version of the phone number.
1102 i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_ =
1103 function(number, normalizationReplacements, removeNonMatches) {
1105 /** @type {!goog.string.StringBuffer} */
1106 var normalizedNumber = new goog.string.StringBuffer();
1107 /** @type {string} */
1109 /** @type {string} */
1111 /** @type {number} */
1112 var numberLength = number.length;
1113 for (var i = 0; i < numberLength; ++i) {
1114 character = number.charAt(i);
1115 newDigit = normalizationReplacements[character.toUpperCase()];
1116 if (newDigit != null) {
1117 normalizedNumber.append(newDigit);
1118 } else if (!removeNonMatches) {
1119 normalizedNumber.append(character);
1121 // If neither of the above are true, we remove this character.
1123 return normalizedNumber.toString();
1128 * Helper function to check region code is not unknown or null.
1130 * @param {?string} regionCode the ISO 3166-1 two-letter region code.
1131 * @return {boolean} true if region code is valid.
1134 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidRegionCode_ =
1135 function(regionCode) {
1137 return regionCode != null &&
1138 regionCode.toUpperCase() in i18n.phonenumbers.metadata.countryToMetadata;
1143 * Formats a phone number in the specified format using default rules. Note that
1144 * this does not promise to produce a phone number that the user can dial from
1145 * where they are - although we do format in either 'national' or
1146 * 'international' format depending on what the client asks for, we do not
1147 * currently support a more abbreviated format, such as for users in the same
1148 * 'area' who could potentially dial the number without area code. Note that if
1149 * the phone number has a country calling code of 0 or an otherwise invalid
1150 * country calling code, we cannot work out which formatting rules to apply so
1151 * we return the national significant number with no formatting applied.
1153 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1155 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1156 * phone number should be formatted into.
1157 * @return {string} the formatted phone number.
1159 i18n.phonenumbers.PhoneNumberUtil.prototype.format =
1160 function(number, numberFormat) {
1162 /** @type {number} */
1163 var countryCode = number.getCountryCodeOrDefault();
1164 /** @type {string} */
1165 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1166 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.E164) {
1167 // Early exit for E164 case since no formatting of the national number needs
1168 // to be applied. Extensions are not formatted.
1169 return this.formatNumberByFormat_(countryCode,
1170 i18n.phonenumbers.PhoneNumberFormat.E164,
1171 nationalSignificantNumber, '');
1173 // Note getRegionCodeForCountryCode() is used because formatting information
1174 // for regions which share a country calling code is contained by only one
1175 // region for performance reasons. For example, for NANPA regions it will be
1176 // contained in the metadata for US.
1177 /** @type {string} */
1178 var regionCode = this.getRegionCodeForCountryCode(countryCode);
1179 if (!this.isValidRegionCode_(regionCode)) {
1180 return nationalSignificantNumber;
1183 /** @type {string} */
1184 var formattedExtension =
1185 this.maybeGetFormattedExtension_(number, regionCode, numberFormat);
1186 /** @type {string} */
1187 var formattedNationalNumber =
1188 this.formatNationalNumber_(nationalSignificantNumber,
1191 return this.formatNumberByFormat_(countryCode,
1193 formattedNationalNumber,
1194 formattedExtension);
1199 * Formats a phone number in the specified format using client-defined
1200 * formatting rules. Note that if the phone number has a country calling code of
1201 * zero or an otherwise invalid country calling code, we cannot work out things
1202 * like whether there should be a national prefix applied, or how to format
1203 * extensions, so we return the national significant number with no formatting
1206 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1208 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1209 * phone number should be formatted into.
1210 * @param {Array.<i18n.phonenumbers.NumberFormat>} userDefinedFormats formatting
1211 * rules specified by clients.
1212 * @return {string} the formatted phone number.
1214 i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern =
1215 function(number, numberFormat, userDefinedFormats) {
1217 /** @type {number} */
1218 var countryCallingCode = number.getCountryCodeOrDefault();
1219 /** @type {string} */
1220 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1221 // Note getRegionCodeForCountryCode() is used because formatting information
1222 // for regions which share a country calling code is contained by only one
1223 // region for performance reasons. For example, for NANPA regions it will be
1224 // contained in the metadata for US.
1225 /** @type {string} */
1226 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1227 if (!this.isValidRegionCode_(regionCode)) {
1228 return nationalSignificantNumber;
1230 /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
1231 var userDefinedFormatsCopy = [];
1232 /** @type {number} */
1233 var size = userDefinedFormats.length;
1234 for (var i = 0; i < size; ++i) {
1235 /** @type {i18n.phonenumbers.NumberFormat} */
1236 var numFormat = userDefinedFormats[i];
1237 /** @type {string} */
1238 var nationalPrefixFormattingRule =
1239 numFormat.getNationalPrefixFormattingRuleOrDefault();
1240 if (nationalPrefixFormattingRule.length > 0) {
1241 // Before we do a replacement of the national prefix pattern $NP with the
1242 // national prefix, we need to copy the rule so that subsequent
1243 // replacements for different numbers have the appropriate national
1245 /** type {i18n.phonenumbers.NumberFormat} */
1246 var numFormatCopy = numFormat.clone();
1247 /** @type {string} */
1248 var nationalPrefix =
1249 this.getMetadataForRegion(regionCode).getNationalPrefixOrDefault();
1250 if (nationalPrefix.length > 0) {
1251 // Replace $NP with national prefix and $FG with the first group ($1).
1252 nationalPrefixFormattingRule = nationalPrefixFormattingRule
1253 .replace(i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_,
1255 .replace(i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_, '$1');
1256 numFormatCopy.setNationalPrefixFormattingRule(
1257 nationalPrefixFormattingRule);
1259 // We don't want to have a rule for how to format the national prefix if
1261 numFormatCopy.clearNationalPrefixFormattingRule();
1263 userDefinedFormatsCopy.push(numFormatCopy);
1265 // Otherwise, we just add the original rule to the modified list of
1267 userDefinedFormatsCopy.push(numFormat);
1271 /** @type {string} */
1272 var formattedExtension =
1273 this.maybeGetFormattedExtension_(number, regionCode, numberFormat);
1274 /** @type {string} */
1275 var formattedNationalNumber =
1276 this.formatAccordingToFormats_(nationalSignificantNumber,
1277 userDefinedFormatsCopy,
1279 return this.formatNumberByFormat_(countryCallingCode,
1281 formattedNationalNumber,
1282 formattedExtension);
1287 * Formats a phone number in national format for dialing using the carrier as
1288 * specified in the {@code carrierCode}. The {@code carrierCode} will always be
1289 * used regardless of whether the phone number already has a preferred domestic
1290 * carrier code stored. If {@code carrierCode} contains an empty string, returns
1291 * the number in national format without any carrier code.
1293 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1295 * @param {string} carrierCode the carrier selection code to be used.
1296 * @return {string} the formatted phone number in national format for dialing
1297 * using the carrier as specified in the {@code carrierCode}.
1299 i18n.phonenumbers.PhoneNumberUtil.prototype.
1300 formatNationalNumberWithCarrierCode = function(number, carrierCode) {
1302 /** @type {number} */
1303 var countryCallingCode = number.getCountryCodeOrDefault();
1304 /** @type {string} */
1305 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1306 // Note getRegionCodeForCountryCode() is used because formatting information
1307 // for regions which share a country calling code is contained by only one
1308 // region for performance reasons. For example, for NANPA regions it will be
1309 // contained in the metadata for US.
1310 /** @type {string} */
1311 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1312 if (!this.isValidRegionCode_(regionCode)) {
1313 return nationalSignificantNumber;
1316 /** @type {string} */
1317 var formattedExtension = this.maybeGetFormattedExtension_(
1318 number, regionCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1319 /** @type {string} */
1320 var formattedNationalNumber =
1321 this.formatNationalNumber_(nationalSignificantNumber,
1323 i18n.phonenumbers.PhoneNumberFormat.NATIONAL,
1325 return this.formatNumberByFormat_(
1326 countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL,
1327 formattedNationalNumber, formattedExtension);
1332 * Formats a phone number in national format for dialing using the carrier as
1333 * specified in the preferred_domestic_carrier_code field of the PhoneNumber
1334 * object passed in. If that is missing, use the {@code fallbackCarrierCode}
1335 * passed in instead. If there is no {@code preferred_domestic_carrier_code},
1336 * and the {@code fallbackCarrierCode} contains an empty string, return the
1337 * number in national format without any carrier code.
1339 * <p>Use {@link #formatNationalNumberWithCarrierCode} instead if the carrier
1340 * code passed in should take precedence over the number's
1341 * {@code preferred_domestic_carrier_code} when formatting.
1343 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1345 * @param {string} fallbackCarrierCode the carrier selection code to be used, if
1346 * none is found in the phone number itself.
1347 * @return {string} the formatted phone number in national format for dialing
1348 * using the number's preferred_domestic_carrier_code, or the
1349 * {@code fallbackCarrierCode} passed in if none is found.
1351 i18n.phonenumbers.PhoneNumberUtil.prototype.
1352 formatNationalNumberWithPreferredCarrierCode = function(
1353 number, fallbackCarrierCode) {
1354 return this.formatNationalNumberWithCarrierCode(
1356 number.hasPreferredDomesticCarrierCode() ?
1357 number.getPreferredDomesticCarrierCodeOrDefault() :
1358 fallbackCarrierCode);
1363 * Formats a phone number for out-of-country dialing purposes. If no
1364 * regionCallingFrom is supplied, we format the number in its INTERNATIONAL
1365 * format. If the country calling code is the same as the region where the
1366 * number is from, then NATIONAL formatting will be applied.
1368 * <p>If the number itself has a country calling code of zero or an otherwise
1369 * invalid country calling code, then we return the number with no formatting
1372 * <p>Note this function takes care of the case for calling inside of NANPA and
1373 * between Russia and Kazakhstan (who share the same country calling code). In
1374 * those cases, no international prefix is used. For regions which have multiple
1375 * international prefixes, the number in its INTERNATIONAL format will be
1378 * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
1380 * @param {string} regionCallingFrom the ISO 3166-1 two-letter region code
1381 * that denotes the region where the call is being placed.
1382 * @return {string} the formatted phone number.
1384 i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
1385 function(number, regionCallingFrom) {
1387 if (!this.isValidRegionCode_(regionCallingFrom)) {
1388 return this.format(number,
1389 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1391 /** @type {number} */
1392 var countryCallingCode = number.getCountryCodeOrDefault();
1393 /** @type {string} */
1394 var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
1395 /** @type {string} */
1396 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1397 if (!this.isValidRegionCode_(regionCode)) {
1398 return nationalSignificantNumber;
1400 if (countryCallingCode ==
1401 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
1402 if (this.isNANPACountry(regionCallingFrom)) {
1403 // For NANPA regions, return the national format for these regions but
1404 // prefix it with the country calling code.
1405 return countryCallingCode + ' ' +
1406 this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1408 } else if (countryCallingCode ==
1409 this.getCountryCodeForRegion(regionCallingFrom)) {
1410 // For regions that share a country calling code, the country calling code
1411 // need not be dialled. This also applies when dialling within a region, so
1412 // this if clause covers both these cases. Technically this is the case for
1413 // dialling from La Reunion to other overseas departments of France (French
1414 // Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover
1415 // this edge case for now and for those cases return the version including
1416 // country calling code. Details here:
1417 // http://www.petitfute.com/voyage/225-info-pratiques-reunion
1418 return this.format(number,
1419 i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1421 /** @type {string} */
1422 var formattedNationalNumber =
1423 this.formatNationalNumber_(nationalSignificantNumber, regionCode,
1424 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1425 /** @type {i18n.phonenumbers.PhoneMetadata} */
1426 var metadata = this.getMetadataForRegion(regionCallingFrom);
1427 /** @type {string} */
1428 var internationalPrefix = metadata.getInternationalPrefixOrDefault();
1429 /** @type {string} */
1430 var formattedExtension = this.maybeGetFormattedExtension_(
1431 number, regionCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1433 // For regions that have multiple international prefixes, the international
1434 // format of the number is returned, unless there is a preferred international
1436 /** @type {string} */
1437 var internationalPrefixForFormatting = '';
1438 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1439 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
1440 internationalPrefix)) {
1441 internationalPrefixForFormatting = internationalPrefix;
1442 } else if (metadata.hasPreferredInternationalPrefix()) {
1443 internationalPrefixForFormatting =
1444 metadata.getPreferredInternationalPrefixOrDefault();
1447 return internationalPrefixForFormatting.length > 0 ?
1448 internationalPrefixForFormatting + ' ' + countryCallingCode + ' ' +
1449 formattedNationalNumber + formattedExtension :
1450 this.formatNumberByFormat_(
1451 countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
1452 formattedNationalNumber, formattedExtension);
1457 * Formats a phone number using the original phone number format that the number
1458 * is parsed from. The original format is embedded in the country_code_source
1459 * field of the PhoneNumber object passed in. If such information is missing,
1460 * the number will be formatted into the NATIONAL format by default.
1462 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
1463 * be formatted in its original number format.
1464 * @param {string} regionCallingFrom the region whose IDD needs to be prefixed
1465 * if the original number has one.
1466 * @return {string} the formatted phone number in its original number format.
1468 i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat =
1469 function(number, regionCallingFrom) {
1471 if (!number.hasCountryCodeSource()) {
1472 return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1474 switch (number.getCountryCodeSource()) {
1475 case i18n.phonenumbers.PhoneNumber.CountryCodeSource
1476 .FROM_NUMBER_WITH_PLUS_SIGN:
1477 return this.format(number,
1478 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1479 case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD:
1480 return this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
1481 case i18n.phonenumbers.PhoneNumber.CountryCodeSource
1482 .FROM_NUMBER_WITHOUT_PLUS_SIGN:
1483 return this.format(number,
1484 i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL).substring(1);
1485 case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY:
1487 return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1493 * Formats a phone number for out-of-country dialing purposes.
1495 * Note that in this version, if the number was entered originally using alpha
1496 * characters and this version of the number is stored in raw_input, this
1497 * representation of the number will be used rather than the digit
1498 * representation. Grouping information, as specified by characters such as '-'
1499 * and ' ', will be retained.
1501 * <p><b>Caveats:</b></p>
1503 * <li>This will not produce good results if the country calling code is both
1504 * present in the raw input _and_ is the start of the national number. This is
1505 * not a problem in the regions which typically use alpha numbers.
1506 * <li>This will also not produce good results if the raw input has any grouping
1507 * information within the first three digits of the national number, and if the
1508 * function needs to strip preceding digits/words in the raw input before these
1509 * digits. Normally people group the first three digits together so this is not
1510 * a huge problem - and will be fixed if it proves to be so.
1513 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
1515 * @param {string} regionCallingFrom the region where the call is being placed.
1516 * @return {string} the formatted phone number.
1518 i18n.phonenumbers.PhoneNumberUtil.prototype.
1519 formatOutOfCountryKeepingAlphaChars = function(number, regionCallingFrom) {
1520 /** @type {string} */
1521 var rawInput = number.getRawInputOrDefault();
1522 // If there is no raw input, then we can't keep alpha characters because there
1523 // aren't any. In this case, we return formatOutOfCountryCallingNumber.
1524 if (rawInput.length == 0) {
1525 return this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
1527 /** @type {number} */
1528 var countryCode = number.getCountryCodeOrDefault();
1529 /** @type {string} */
1530 var regionCode = this.getRegionCodeForCountryCode(countryCode);
1531 if (!this.isValidRegionCode_(regionCode)) {
1534 // Strip any prefix such as country calling code, IDD, that was present. We do
1535 // this by comparing the number in raw_input with the parsed number. To do
1536 // this, first we normalize punctuation. We retain number grouping symbols
1537 // such as ' ' only.
1538 rawInput = i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(
1540 i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_,
1542 // Now we trim everything before the first three digits in the parsed number.
1543 // We choose three because all valid alpha numbers have 3 digits at the start
1544 // - if it does not, then we don't trim anything at all. Similarly, if the
1545 // national number was less than three digits, we don't trim anything at all.
1546 /** @type {string} */
1547 var nationalNumber = this.getNationalSignificantNumber(number);
1548 if (nationalNumber.length > 3) {
1549 /** @type {number} */
1550 var firstNationalNumberDigit =
1551 rawInput.indexOf(nationalNumber.substring(0, 3));
1552 if (firstNationalNumberDigit != -1) {
1553 rawInput = rawInput.substring(firstNationalNumberDigit);
1556 /** @type {i18n.phonenumbers.PhoneMetadata} */
1557 var metadata = this.getMetadataForRegion(regionCallingFrom);
1558 if (countryCode == i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
1559 if (this.isNANPACountry(regionCallingFrom)) {
1560 return countryCode + ' ' + rawInput;
1562 } else if (countryCode == this.getCountryCodeForRegion(regionCallingFrom)) {
1563 // Here we copy the formatting rules so we can modify the pattern we expect
1564 // to match against.
1565 /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
1566 var availableFormats = [];
1567 for (var i = 0; i < metadata.numberFormatArray().length; ++i) {
1568 /** @type {i18n.phonenumbers.NumberFormat} */
1569 var newFormat = metadata.numberFormatArray()[i].clone();
1570 // The first group is the first group of digits that the user determined.
1571 newFormat.setPattern('(\\d+)(.*)');
1572 // Here we just concatenate them back together after the national prefix
1574 newFormat.setFormat('$1$2');
1575 availableFormats.push(newFormat);
1577 // Now we format using these patterns instead of the default pattern, but
1578 // with the national prefix prefixed if necessary, by choosing the format
1579 // rule based on the leading digits present in the unformatted national
1580 // number. This will not work in the cases where the pattern (and not the
1581 // leading digits) decide whether a national prefix needs to be used, since
1582 // we have overridden the pattern to match anything, but that is not the
1583 // case in the metadata to date.
1584 return this.formatAccordingToFormats_(rawInput, availableFormats,
1585 i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
1587 /** @type {string} */
1588 var internationalPrefix = metadata.getInternationalPrefixOrDefault();
1589 // For countries that have multiple international prefixes, the international
1590 // format of the number is returned, unless there is a preferred international
1592 /** @type {string} */
1593 var internationalPrefixForFormatting =
1594 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
1595 i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
1596 internationalPrefix) ?
1597 internationalPrefix : metadata.getPreferredInternationalPrefixOrDefault();
1598 /** @type {string} */
1599 var formattedExtension = this.maybeGetFormattedExtension_(
1600 number, regionCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
1601 return internationalPrefixForFormatting.length > 0 ?
1602 internationalPrefixForFormatting + ' ' + countryCode + ' ' +
1603 rawInput + formattedExtension :
1604 this.formatNumberByFormat_(
1605 countryCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
1606 rawInput, formattedExtension);
1611 * Gets the national significant number of the a phone number. Note a national
1612 * significant number doesn't contain a national prefix or any formatting.
1614 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
1615 * which the national significant number is needed.
1616 * @return {string} the national significant number of the PhoneNumber object
1619 i18n.phonenumbers.PhoneNumberUtil.prototype.getNationalSignificantNumber =
1622 // The leading zero in the national (significant) number of an Italian phone
1623 // number has a special meaning. Unlike the rest of the world, it indicates
1624 // the number is a landline number. There have been plans to migrate landline
1625 // numbers to start with the digit two since December 2000, but it has not yet
1626 // happened. See http://en.wikipedia.org/wiki/%2B39 for more details. Other
1627 // regions such as Cote d'Ivoire and Gabon use this for their mobile numbers.
1628 /** @type {string} */
1629 var nationalNumber = '' + number.getNationalNumber();
1630 if (number.hasItalianLeadingZero() && number.getItalianLeadingZero() &&
1631 this.isLeadingZeroPossible(number.getCountryCodeOrDefault())) {
1632 return '0' + nationalNumber;
1634 return nationalNumber;
1639 * A helper function that is used by format and formatByPattern.
1641 * @param {number} countryCallingCode the country calling code.
1642 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1643 * phone number should be formatted into.
1644 * @param {string} formattedNationalNumber
1645 * @param {string} formattedExtension
1646 * @return {string} the formatted phone number.
1649 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberByFormat_ =
1650 function(countryCallingCode, numberFormat,
1651 formattedNationalNumber, formattedExtension) {
1653 switch (numberFormat) {
1654 case i18n.phonenumbers.PhoneNumberFormat.E164:
1655 return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
1656 formattedNationalNumber + formattedExtension;
1657 case i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL:
1658 return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
1659 ' ' + formattedNationalNumber + formattedExtension;
1660 case i18n.phonenumbers.PhoneNumberFormat.RFC3966:
1661 return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
1662 '-' + formattedNationalNumber + formattedExtension;
1663 case i18n.phonenumbers.PhoneNumberFormat.NATIONAL:
1665 return formattedNationalNumber + formattedExtension;
1671 * Note in some regions, the national number can be written in two completely
1672 * different ways depending on whether it forms part of the NATIONAL format or
1673 * INTERNATIONAL format. The numberFormat parameter here is used to specify
1674 * which format to use for those cases. If a carrierCode is specified, this will
1675 * be inserted into the formatted string to replace $CC.
1677 * @param {string} number a string of characters representing a phone number.
1678 * @param {string} regionCode the ISO 3166-1 two-letter region code.
1679 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1680 * phone number should be formatted into.
1681 * @param {string=} opt_carrierCode
1682 * @return {string} the formatted phone number.
1685 i18n.phonenumbers.PhoneNumberUtil.prototype.formatNationalNumber_ =
1686 function(number, regionCode, numberFormat, opt_carrierCode) {
1688 /** @type {i18n.phonenumbers.PhoneMetadata} */
1689 var metadata = this.getMetadataForRegion(regionCode);
1690 /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
1691 var intlNumberFormats = metadata.intlNumberFormatArray();
1692 // When the intlNumberFormats exists, we use that to format national number
1693 // for the INTERNATIONAL format instead of using the numberDesc.numberFormats.
1694 /** @type {Array.<i18n.phonenumbers.NumberFormat>} */
1695 var availableFormats =
1696 (intlNumberFormats.length == 0 ||
1697 numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL) ?
1698 metadata.numberFormatArray() : metadata.intlNumberFormatArray();
1699 /** @type {string} */
1700 var formattedNationalNumber = this.formatAccordingToFormats_(
1701 number, availableFormats, numberFormat, opt_carrierCode);
1702 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
1703 formattedNationalNumber = formattedNationalNumber.replace(
1704 i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_, '-');
1706 return formattedNationalNumber;
1711 * Note that carrierCode is optional - if NULL or an empty string, no carrier
1712 * code replacement will take place.
1714 * @param {string} nationalNumber a string of characters representing a phone
1716 * @param {Array.<i18n.phonenumbers.NumberFormat>} availableFormats the
1717 * available formats the phone number could be formatted into.
1718 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1719 * phone number should be formatted into.
1720 * @param {string=} opt_carrierCode
1721 * @return {string} the formatted phone number.
1724 i18n.phonenumbers.PhoneNumberUtil.prototype.formatAccordingToFormats_ =
1725 function(nationalNumber, availableFormats, numberFormat, opt_carrierCode) {
1727 /** @type {i18n.phonenumbers.NumberFormat} */
1729 /** @type {number} */
1730 var l = availableFormats.length;
1731 for (var i = 0; i < l; ++i) {
1732 numFormat = availableFormats[i];
1733 /** @type {number} */
1734 var size = numFormat.leadingDigitsPatternCount();
1736 // We always use the last leading_digits_pattern, as it is the most
1739 .search(numFormat.getLeadingDigitsPattern(size - 1)) == 0) {
1740 /** @type {!RegExp} */
1741 var patternToMatch = new RegExp(numFormat.getPattern());
1742 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(patternToMatch,
1744 /** @type {string} */
1745 var numberFormatRule = numFormat.getFormatOrDefault();
1746 /** @type {string} */
1747 var domesticCarrierCodeFormattingRule =
1748 numFormat.getDomesticCarrierCodeFormattingRuleOrDefault();
1749 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
1750 opt_carrierCode != null && opt_carrierCode.length > 0 &&
1751 domesticCarrierCodeFormattingRule.length > 0) {
1752 // Replace the $CC in the formatting rule with the desired carrier
1754 /** @type {string} */
1755 var carrierCodeFormattingRule = domesticCarrierCodeFormattingRule
1756 .replace(i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_,
1758 // Now replace the $FG in the formatting rule with the first group and
1759 // the carrier code combined in the appropriate way.
1760 numberFormatRule = numberFormatRule.replace(
1761 i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
1762 carrierCodeFormattingRule);
1763 return nationalNumber.replace(patternToMatch, numberFormatRule);
1765 // Use the national prefix formatting rule instead.
1766 /** @type {string} */
1767 var nationalPrefixFormattingRule =
1768 numFormat.getNationalPrefixFormattingRuleOrDefault();
1769 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
1770 nationalPrefixFormattingRule != null &&
1771 nationalPrefixFormattingRule.length > 0) {
1772 return nationalNumber.replace(patternToMatch, numberFormatRule
1773 .replace(i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
1774 nationalPrefixFormattingRule));
1776 return nationalNumber.replace(patternToMatch, numberFormatRule);
1783 // If no pattern above is matched, we format the number as a whole.
1784 return nationalNumber;
1789 * Gets a valid number for the specified region.
1791 * @param {string} regionCode the ISO 3166-1 two-letter region code that
1792 * denotes the region for which an example number is needed.
1793 * @return {i18n.phonenumbers.PhoneNumber} a valid fixed-line number for the
1794 * specified region. Returns null when the metadata does not contain such
1797 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumber =
1798 function(regionCode) {
1800 return this.getExampleNumberForType(regionCode,
1801 i18n.phonenumbers.PhoneNumberType.FIXED_LINE);
1806 * Gets a valid number for the specified region and number type.
1808 * @param {string} regionCode the ISO 3166-1 two-letter region code that
1809 * denotes the region for which an example number is needed.
1810 * @param {i18n.phonenumbers.PhoneNumberType} type the type of number that is
1812 * @return {i18n.phonenumbers.PhoneNumber} a valid number for the specified
1813 * region and type. Returns null when the metadata does not contain such
1816 i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForType =
1817 function(regionCode, type) {
1819 // Check the region code is valid.
1820 if (!this.isValidRegionCode_(regionCode)) {
1823 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
1824 var desc = this.getNumberDescByType_(
1825 this.getMetadataForRegion(regionCode), type);
1827 if (desc.hasExampleNumber()) {
1828 return this.parse(desc.getExampleNumberOrDefault(), regionCode);
1837 * Gets the formatted extension of a phone number, if the phone number had an
1838 * extension specified. If not, it returns an empty string.
1840 * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber that might have
1842 * @param {string} regionCode the ISO 3166-1 two-letter region code.
1843 * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
1844 * phone number should be formatted into.
1845 * @return {string} the formatted extension if any.
1848 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeGetFormattedExtension_ =
1849 function(number, regionCode, numberFormat) {
1851 if (!number.hasExtension() || number.getExtension().length == 0) {
1854 if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
1855 return i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
1856 number.getExtension();
1858 return this.formatExtension_(number.getExtensionOrDefault(), regionCode);
1864 * Formats the extension part of the phone number by prefixing it with the
1865 * appropriate extension prefix. This will be the default extension prefix,
1866 * unless overridden by a preferred extension prefix for this region.
1868 * @param {string} extensionDigits the extension digits.
1869 * @param {string} regionCode the ISO 3166-1 two-letter region code.
1870 * @return {string} the formatted extension.
1873 i18n.phonenumbers.PhoneNumberUtil.prototype.formatExtension_ =
1874 function(extensionDigits, regionCode) {
1876 /** @type {i18n.phonenumbers.PhoneMetadata} */
1877 var metadata = this.getMetadataForRegion(regionCode);
1878 if (metadata.hasPreferredExtnPrefix()) {
1879 return metadata.getPreferredExtnPrefix() + extensionDigits;
1881 return i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ +
1888 * @param {i18n.phonenumbers.PhoneMetadata} metadata
1889 * @param {i18n.phonenumbers.PhoneNumberType} type
1890 * @return {i18n.phonenumbers.PhoneNumberDesc}
1893 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberDescByType_ =
1894 function(metadata, type) {
1897 case i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE:
1898 return metadata.getPremiumRate();
1899 case i18n.phonenumbers.PhoneNumberType.TOLL_FREE:
1900 return metadata.getTollFree();
1901 case i18n.phonenumbers.PhoneNumberType.MOBILE:
1902 return metadata.getMobile();
1903 case i18n.phonenumbers.PhoneNumberType.FIXED_LINE:
1904 case i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE:
1905 return metadata.getFixedLine();
1906 case i18n.phonenumbers.PhoneNumberType.SHARED_COST:
1907 return metadata.getSharedCost();
1908 case i18n.phonenumbers.PhoneNumberType.VOIP:
1909 return metadata.getVoip();
1910 case i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER:
1911 return metadata.getPersonalNumber();
1912 case i18n.phonenumbers.PhoneNumberType.PAGER:
1913 return metadata.getPager();
1914 case i18n.phonenumbers.PhoneNumberType.UAN:
1915 return metadata.getUan();
1917 return metadata.getGeneralDesc();
1923 * Gets the type of a phone number.
1925 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
1927 * @return {i18n.phonenumbers.PhoneNumberType} the type of the phone number.
1929 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberType =
1932 /** @type {?string} */
1933 var regionCode = this.getRegionCodeForNumber(number);
1934 if (!this.isValidRegionCode_(regionCode)) {
1935 return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
1937 /** @type {string} */
1938 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
1939 return this.getNumberTypeHelper_(nationalSignificantNumber,
1940 this.getMetadataForRegion(regionCode));
1945 * @param {string} nationalNumber
1946 * @param {i18n.phonenumbers.PhoneMetadata} metadata
1947 * @return {i18n.phonenumbers.PhoneNumberType}
1950 i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberTypeHelper_ =
1951 function(nationalNumber, metadata) {
1953 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
1954 var generalNumberDesc = metadata.getGeneralDesc();
1955 if (!generalNumberDesc.hasNationalNumberPattern() ||
1956 !this.isNumberMatchingDesc_(nationalNumber, generalNumberDesc)) {
1957 return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
1960 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPremiumRate())) {
1961 return i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE;
1963 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getTollFree())) {
1964 return i18n.phonenumbers.PhoneNumberType.TOLL_FREE;
1966 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getSharedCost())) {
1967 return i18n.phonenumbers.PhoneNumberType.SHARED_COST;
1969 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoip())) {
1970 return i18n.phonenumbers.PhoneNumberType.VOIP;
1972 if (this.isNumberMatchingDesc_(nationalNumber,
1973 metadata.getPersonalNumber())) {
1974 return i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER;
1976 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPager())) {
1977 return i18n.phonenumbers.PhoneNumberType.PAGER;
1979 if (this.isNumberMatchingDesc_(nationalNumber, metadata.getUan())) {
1980 return i18n.phonenumbers.PhoneNumberType.UAN;
1983 /** @type {boolean} */
1984 var isFixedLine = this.isNumberMatchingDesc_(nationalNumber, metadata
1987 if (metadata.getSameMobileAndFixedLinePattern()) {
1988 return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
1989 } else if (this.isNumberMatchingDesc_(nationalNumber,
1990 metadata.getMobile())) {
1991 return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
1993 return i18n.phonenumbers.PhoneNumberType.FIXED_LINE;
1995 // Otherwise, test to see if the number is mobile. Only do this if certain
1996 // that the patterns for mobile and fixed line aren't the same.
1997 if (!metadata.getSameMobileAndFixedLinePattern() &&
1998 this.isNumberMatchingDesc_(nationalNumber, metadata.getMobile())) {
1999 return i18n.phonenumbers.PhoneNumberType.MOBILE;
2001 return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2006 * @param {?string} regionCode
2007 * @return {i18n.phonenumbers.PhoneMetadata}
2009 i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegion =
2010 function(regionCode) {
2012 if (regionCode == null) {
2015 regionCode = regionCode.toUpperCase();
2016 /** @type {i18n.phonenumbers.PhoneMetadata} */
2017 var metadata = this.regionToMetadataMap[regionCode];
2018 if (metadata == null) {
2019 /** @type {goog.proto2.PbLiteSerializer} */
2020 var serializer = new goog.proto2.PbLiteSerializer();
2021 /** @type {Array} */
2022 var metadataSerialized =
2023 i18n.phonenumbers.metadata.countryToMetadata[regionCode];
2024 if (metadataSerialized == null) {
2027 metadata = /** @type {i18n.phonenumbers.PhoneMetadata} */ (
2028 serializer.deserialize(i18n.phonenumbers.PhoneMetadata.getDescriptor(),
2029 metadataSerialized));
2030 this.regionToMetadataMap[regionCode] = metadata;
2037 * @param {string} nationalNumber
2038 * @param {i18n.phonenumbers.PhoneNumberDesc} numberDesc
2042 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatchingDesc_ =
2043 function(nationalNumber, numberDesc) {
2045 return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2046 numberDesc.getPossibleNumberPatternOrDefault(), nationalNumber) &&
2047 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2048 numberDesc.getNationalNumberPatternOrDefault(), nationalNumber);
2053 * Tests whether a phone number matches a valid pattern. Note this doesn't
2054 * verify the number is actually in use, which is impossible to tell by just
2055 * looking at a number itself.
2057 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2059 * @return {boolean} a boolean that indicates whether the number is of a valid
2062 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) {
2063 /** @type {?string} */
2064 var regionCode = this.getRegionCodeForNumber(number);
2065 return this.isValidRegionCode_(regionCode) &&
2066 this.isValidNumberForRegion(number, /** @type {string} */ (regionCode));
2071 * Tests whether a phone number is valid for a certain region. Note this doesn't
2072 * verify the number is actually in use, which is impossible to tell by just
2073 * looking at a number itself. If the country calling code is not the same as
2074 * the country calling code for the region, this immediately exits with false.
2075 * After this, the specific number pattern rules for the region are examined.
2076 * This is useful for determining for example whether a particular number is
2077 * valid for Canada, rather than just a valid NANPA number.
2079 * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
2081 * @param {string} regionCode the ISO 3166-1 two-letter region code that
2082 * denotes the region that we want to validate the phone number for.
2083 * @return {boolean} a boolean that indicates whether the number is of a valid
2086 i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumberForRegion =
2087 function(number, regionCode) {
2089 if (number.getCountryCodeOrDefault() !=
2090 this.getCountryCodeForRegion(regionCode)) {
2093 /** @type {i18n.phonenumbers.PhoneMetadata} */
2094 var metadata = this.getMetadataForRegion(regionCode);
2095 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2096 var generalNumDesc = metadata.getGeneralDesc();
2097 /** @type {string} */
2098 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
2100 // For regions where we don't have metadata for PhoneNumberDesc, we treat any
2101 // number passed in as a valid number if its national significant number is
2102 // between the minimum and maximum lengths defined by ITU for a national
2103 // significant number.
2104 if (!generalNumDesc.hasNationalNumberPattern()) {
2105 /** @type {number} */
2106 var numberLength = nationalSignificantNumber.length;
2107 return numberLength >
2108 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ &&
2109 numberLength <= i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_;
2111 return this.getNumberTypeHelper_(nationalSignificantNumber, metadata) !=
2112 i18n.phonenumbers.PhoneNumberType.UNKNOWN;
2117 * Returns the region where a phone number is from. This could be used for
2118 * geocoding at the region level.
2120 * @param {i18n.phonenumbers.PhoneNumber} number the phone number whose origin
2122 * @return {?string} the region where the phone number is from, or null
2123 * if no region matches this calling code.
2125 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForNumber =
2128 if (number == null) {
2131 /** @type {number} */
2132 var countryCode = number.getCountryCodeOrDefault();
2133 /** @type {Array.<string>} */
2135 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCode];
2136 if (regions == null) {
2139 if (regions.length == 1) {
2142 return this.getRegionCodeForNumberFromRegionList_(number, regions);
2148 * @param {i18n.phonenumbers.PhoneNumber} number
2149 * @param {Array.<string>} regionCodes
2153 i18n.phonenumbers.PhoneNumberUtil.prototype.
2154 getRegionCodeForNumberFromRegionList_ = function(number, regionCodes) {
2156 /** @type {string} */
2157 var nationalNumber = this.getNationalSignificantNumber(number);
2158 /** @type {string} */
2160 /** @type {number} */
2161 var regionCodesLength = regionCodes.length;
2162 for (var i = 0; i < regionCodesLength; i++) {
2163 regionCode = regionCodes[i];
2164 // If leadingDigits is present, use this. Otherwise, do full validation.
2165 /** @type {i18n.phonenumbers.PhoneMetadata} */
2166 var metadata = this.getMetadataForRegion(regionCode);
2167 if (metadata.hasLeadingDigits()) {
2168 if (nationalNumber.search(metadata.getLeadingDigits()) == 0) {
2171 } else if (this.getNumberTypeHelper_(nationalNumber, metadata) !=
2172 i18n.phonenumbers.PhoneNumberType.UNKNOWN) {
2181 * Returns the region code that matches the specific country calling code. In
2182 * the case of no region code being found, ZZ will be returned. In the case of
2183 * multiple regions, the one designated in the metadata as the 'main' region for
2184 * this calling code will be returned.
2186 * @param {number} countryCallingCode the country calling code.
2189 i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForCountryCode =
2190 function(countryCallingCode) {
2192 /** @type {Array.<string>} */
2194 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
2195 return regionCodes == null ?
2196 i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ : regionCodes[0];
2201 * Returns the country calling code for a specific region. For example, this
2202 * would be 1 for the United States, and 64 for New Zealand.
2204 * @param {?string} regionCode the ISO 3166-1 two-letter region code that
2205 * denotes the region that we want to get the country calling code for.
2206 * @return {number} the country calling code for the region denoted by
2209 i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForRegion =
2210 function(regionCode) {
2212 if (!this.isValidRegionCode_(regionCode)) {
2215 /** @type {i18n.phonenumbers.PhoneMetadata} */
2216 var metadata = this.getMetadataForRegion(regionCode);
2217 return metadata.getCountryCodeOrDefault();
2222 * Returns the national dialling prefix for a specific region. For example, this
2223 * would be 1 for the United States, and 0 for New Zealand. Set stripNonDigits
2224 * to true to strip symbols like '~' (which indicates a wait for a dialling
2225 * tone) from the prefix returned. If no national prefix is present, we return
2228 * <p>Warning: Do not use this method for do-your-own formatting - for some
2229 * regions, the national dialling prefix is used only for certain types of
2230 * numbers. Use the library's formatting functions to prefix the national prefix
2233 * @param {?string} regionCode the ISO 3166-1 two-letter region code that
2234 * denotes the region that we want to get the dialling prefix for.
2235 * @param {boolean} stripNonDigits true to strip non-digits from the national
2237 * @return {?string} the dialling prefix for the region denoted by
2240 i18n.phonenumbers.PhoneNumberUtil.prototype.getNddPrefixForRegion = function(
2241 regionCode, stripNonDigits) {
2242 if (!this.isValidRegionCode_(regionCode)) {
2245 /** @type {i18n.phonenumbers.PhoneMetadata} */
2246 var metadata = this.getMetadataForRegion(regionCode);
2247 /** @type {string} */
2248 var nationalPrefix = metadata.getNationalPrefixOrDefault();
2249 // If no national prefix was found, we return null.
2250 if (nationalPrefix.length == 0) {
2253 if (stripNonDigits) {
2254 // Note: if any other non-numeric symbols are ever used in national
2255 // prefixes, these would have to be removed here as well.
2256 nationalPrefix = nationalPrefix.replace('~', '');
2258 return nationalPrefix;
2263 * Checks if this is a region under the North American Numbering Plan
2264 * Administration (NANPA).
2266 * @param {string} regionCode the ISO 3166-1 two-letter region code.
2267 * @return {boolean} true if regionCode is one of the regions under NANPA.
2269 i18n.phonenumbers.PhoneNumberUtil.prototype.isNANPACountry =
2270 function(regionCode) {
2272 return goog.array.contains(
2273 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[
2274 i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_],
2275 regionCode.toUpperCase());
2280 * Checks whether countryCode represents the country calling code from a region
2281 * whose national significant number could contain a leading zero. An example of
2282 * such a region is Italy. Returns false if no metadata for the country is
2285 * @param {number} countryCallingCode the country calling code.
2288 i18n.phonenumbers.PhoneNumberUtil.prototype.isLeadingZeroPossible =
2289 function(countryCallingCode) {
2290 /** @type {i18n.phonenumbers.PhoneMetadata} */
2291 var mainMetadataForCallingCode = this.getMetadataForRegion(
2292 this.getRegionCodeForCountryCode(countryCallingCode));
2293 return mainMetadataForCallingCode != null &&
2294 mainMetadataForCallingCode.getLeadingZeroPossibleOrDefault();
2299 * Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT.
2300 * A valid vanity number will start with at least 3 digits and will have three
2301 * or more alpha characters. This does not do region-specific checks - to work
2302 * out if this number is actually valid for a region, it should be parsed and
2303 * methods such as {@link #isPossibleNumberWithReason} and
2304 * {@link #isValidNumber} should be used.
2306 * @param {string} number the number that needs to be checked.
2307 * @return {boolean} true if the number is a valid vanity number.
2309 i18n.phonenumbers.PhoneNumberUtil.prototype.isAlphaNumber = function(number) {
2310 if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(number)) {
2311 // Number is too short, or doesn't match the basic phone number pattern.
2314 /** @type {!goog.string.StringBuffer} */
2315 var strippedNumber = new goog.string.StringBuffer(number);
2316 this.maybeStripExtension(strippedNumber);
2317 return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2318 i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_,
2319 strippedNumber.toString());
2324 * Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of
2325 * returning the reason for failure, this method returns a boolean value.
2327 * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
2329 * @return {boolean} true if the number is possible.
2331 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumber =
2334 return this.isPossibleNumberWithReason(number) ==
2335 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
2340 * Helper method to check a number against a particular pattern and determine
2341 * whether it matches, or is too short or too long. Currently, if a number
2342 * pattern suggests that numbers of length 7 and 10 are possible, and a number
2343 * in between these possible lengths is entered, such as of length 8, this will
2346 * @param {string} numberPattern
2347 * @param {string} number
2348 * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult}
2351 i18n.phonenumbers.PhoneNumberUtil.prototype.testNumberLengthAgainstPattern_ =
2352 function(numberPattern, number) {
2353 if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(numberPattern,
2355 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
2357 if (number.search(numberPattern) == 0) {
2358 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG;
2360 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
2366 * Check whether a phone number is a possible number. It provides a more lenient
2367 * check than {@link #isValidNumber} in the following sense:
2369 * <li>It only checks the length of phone numbers. In particular, it doesn't
2370 * check starting digits of the number.
2371 * <li>It doesn't attempt to figure out the type of the number, but uses general
2372 * rules which applies to all types of phone numbers in a region. Therefore, it
2373 * is much faster than isValidNumber.
2374 * <li>For fixed line numbers, many regions have the concept of area code, which
2375 * together with subscriber number constitute the national significant number.
2376 * It is sometimes okay to dial the subscriber number only when dialing in the
2377 * same area. This function will return true if the subscriber-number-only
2378 * version is passed in. On the other hand, because isValidNumber validates
2379 * using information on both starting digits (for fixed line numbers, that would
2380 * most likely be area codes) and length (obviously includes the length of area
2381 * codes for fixed line numbers), it will return false for the
2382 * subscriber-number-only version.
2385 * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
2387 * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult} a
2388 * ValidationResult object which indicates whether the number is possible.
2390 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason =
2393 /** @type {string} */
2394 var nationalNumber = this.getNationalSignificantNumber(number);
2395 /** @type {number} */
2396 var countryCode = number.getCountryCodeOrDefault();
2397 // Note: For Russian Fed and NANPA numbers, we just use the rules from the
2398 // default region (US or Russia) since the getRegionCodeForNumber will not
2399 // work if the number is possible but not valid. This would need to be
2400 // revisited if the possible number pattern ever differed between various
2401 // regions within those plans.
2402 /** @type {string} */
2403 var regionCode = this.getRegionCodeForCountryCode(countryCode);
2404 if (!this.isValidRegionCode_(regionCode)) {
2405 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult
2406 .INVALID_COUNTRY_CODE;
2408 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2409 var generalNumDesc = this.getMetadataForRegion(regionCode).getGeneralDesc();
2410 // Handling case of numbers with no metadata.
2411 if (!generalNumDesc.hasNationalNumberPattern()) {
2412 /** @type {number} */
2413 var numberLength = nationalNumber.length;
2414 if (numberLength < i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
2415 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
2416 } else if (numberLength >
2417 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_) {
2418 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG;
2420 return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
2423 /** @type {string} */
2424 var possibleNumberPattern =
2425 generalNumDesc.getPossibleNumberPatternOrDefault();
2426 return this.testNumberLengthAgainstPattern_(possibleNumberPattern,
2432 * Check whether a phone number is a possible number given a number in the form
2433 * of a string, and the region where the number could be dialed from. It
2434 * provides a more lenient check than {@link #isValidNumber}. See
2435 * {@link #isPossibleNumber} for details.
2437 * <p>This method first parses the number, then invokes
2438 * {@link #isPossibleNumber} with the resultant PhoneNumber object.
2440 * @param {string} number the number that needs to be checked, in the form of a
2442 * @param {string} regionDialingFrom the ISO 3166-1 two-letter region code that
2443 * denotes the region that we are expecting the number to be dialed from.
2444 * Note this is different from the region where the number belongs.
2445 * For example, the number +1 650 253 0000 is a number that belongs to US.
2446 * When written in this form, it can be dialed from any region. When it is
2447 * written as 00 1 650 253 0000, it can be dialed from any region which uses
2448 * an international dialling prefix of 00. When it is written as
2449 * 650 253 0000, it can only be dialed from within the US, and when written
2450 * as 253 0000, it can only be dialed from within a smaller area in the US
2451 * (Mountain View, CA, to be more specific).
2452 * @return {boolean} true if the number is possible.
2454 i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberString =
2455 function(number, regionDialingFrom) {
2458 return this.isPossibleNumber(this.parse(number, regionDialingFrom));
2466 * Attempts to extract a valid number from a phone number that is too long to be
2467 * valid, and resets the PhoneNumber object passed in to that valid version. If
2468 * no valid number could be extracted, the PhoneNumber object passed in will not
2470 * @param {i18n.phonenumbers.PhoneNumber} number a PhoneNumber object which
2471 * contains a number that is too long to be valid.
2472 * @return {boolean} true if a valid phone number can be successfully extracted.
2474 i18n.phonenumbers.PhoneNumberUtil.prototype.truncateTooLongNumber =
2477 if (this.isValidNumber(number)) {
2480 /** @type {i18n.phonenumbers.PhoneNumber} */
2481 var numberCopy = number.clone();
2482 /** @type {number} */
2483 var nationalNumber = number.getNationalNumberOrDefault();
2485 nationalNumber = Math.floor(nationalNumber / 10);
2486 numberCopy.setNationalNumber(nationalNumber);
2487 if (nationalNumber == 0 ||
2488 this.isPossibleNumberWithReason(numberCopy) ==
2489 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT) {
2492 } while (!this.isValidNumber(numberCopy));
2493 number.setNationalNumber(nationalNumber);
2499 * Extracts country calling code from fullNumber, returns it and places the
2500 * remaining number in nationalNumber. It assumes that the leading plus sign or
2501 * IDD has already been removed. Returns 0 if fullNumber doesn't start with a
2502 * valid country calling code, and leaves nationalNumber unmodified.
2504 * @param {!goog.string.StringBuffer} fullNumber
2505 * @param {!goog.string.StringBuffer} nationalNumber
2508 i18n.phonenumbers.PhoneNumberUtil.prototype.extractCountryCode =
2509 function(fullNumber, nationalNumber) {
2511 /** @type {string} */
2512 var fullNumberStr = fullNumber.toString();
2513 /** @type {number} */
2514 var potentialCountryCode;
2515 /** @type {number} */
2516 var numberLength = fullNumberStr.length;
2518 i <= i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE_ &&
2519 i <= numberLength; ++i) {
2520 potentialCountryCode = parseInt(fullNumberStr.substring(0, i), 10);
2521 if (potentialCountryCode in
2522 i18n.phonenumbers.metadata.countryCodeToRegionCodeMap) {
2523 nationalNumber.append(fullNumberStr.substring(i));
2524 return potentialCountryCode;
2532 * Tries to extract a country calling code from a number. This method will
2533 * return zero if no country calling code is considered to be present. Country
2534 * calling codes are extracted in the following ways:
2536 * <li>by stripping the international dialing prefix of the region the person is
2537 * dialing from, if this is present in the number, and looking at the next
2539 * <li>by stripping the '+' sign if present and then looking at the next digits
2540 * <li>by comparing the start of the number and the country calling code of the
2541 * default region. If the number is not considered possible for the numbering
2542 * plan of the default region initially, but starts with the country calling
2543 * code of this region, validation will be reattempted after stripping this
2544 * country calling code. If this number is considered a possible number, then
2545 * the first digits will be considered the country calling code and removed as
2549 * It will throw a i18n.phonenumbers.Error if the number starts with a '+' but
2550 * the country calling code supplied after this does not match that of any known
2553 * @param {string} number non-normalized telephone number that we wish to
2554 * extract a country calling code from - may begin with '+'.
2555 * @param {i18n.phonenumbers.PhoneMetadata} defaultRegionMetadata metadata
2556 * about the region this number may be from.
2557 * @param {!goog.string.StringBuffer} nationalNumber a string buffer to store
2558 * the national significant number in, in the case that a country calling
2559 * code was extracted. The number is appended to any existing contents. If
2560 * no country calling code was extracted, this will be left unchanged.
2561 * @param {boolean} keepRawInput true if the country_code_source and
2562 * preferred_carrier_code fields of phoneNumber should be populated.
2563 * @param {i18n.phonenumbers.PhoneNumber} phoneNumber the PhoneNumber object
2564 * where the country_code and country_code_source need to be populated.
2565 * Note the country_code is always populated, whereas country_code_source is
2566 * only populated when keepCountryCodeSource is true.
2567 * @return {number} the country calling code extracted or 0 if none could be
2569 * @throws {i18n.phonenumbers.Error}
2571 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode =
2572 function(number, defaultRegionMetadata, nationalNumber,
2573 keepRawInput, phoneNumber) {
2575 if (number.length == 0) {
2578 /** @type {!goog.string.StringBuffer} */
2579 var fullNumber = new goog.string.StringBuffer(number);
2580 // Set the default prefix to be something that will never match.
2581 /** @type {?string} */
2582 var possibleCountryIddPrefix;
2583 if (defaultRegionMetadata != null) {
2584 possibleCountryIddPrefix = defaultRegionMetadata.getInternationalPrefix();
2586 if (possibleCountryIddPrefix == null) {
2587 possibleCountryIddPrefix = 'NonMatch';
2590 /** @type {i18n.phonenumbers.PhoneNumber.CountryCodeSource} */
2591 var countryCodeSource = this.maybeStripInternationalPrefixAndNormalize(
2592 fullNumber, possibleCountryIddPrefix);
2594 phoneNumber.setCountryCodeSource(countryCodeSource);
2596 if (countryCodeSource !=
2597 i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY) {
2598 if (fullNumber.getLength() <
2599 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
2600 throw i18n.phonenumbers.Error.TOO_SHORT_AFTER_IDD;
2602 /** @type {number} */
2603 var potentialCountryCode = this.extractCountryCode(fullNumber,
2605 if (potentialCountryCode != 0) {
2606 phoneNumber.setCountryCode(potentialCountryCode);
2607 return potentialCountryCode;
2610 // If this fails, they must be using a strange country calling code that we
2611 // don't recognize, or that doesn't exist.
2612 throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
2613 } else if (defaultRegionMetadata != null) {
2614 // Check to see if the number starts with the country calling code for the
2615 // default region. If so, we remove the country calling code, and do some
2616 // checks on the validity of the number before and after.
2617 /** @type {number} */
2618 var defaultCountryCode = defaultRegionMetadata.getCountryCodeOrDefault();
2619 /** @type {string} */
2620 var defaultCountryCodeString = '' + defaultCountryCode;
2621 /** @type {string} */
2622 var normalizedNumber = fullNumber.toString();
2623 if (goog.string.startsWith(normalizedNumber, defaultCountryCodeString)) {
2624 /** @type {!goog.string.StringBuffer} */
2625 var potentialNationalNumber = new goog.string.StringBuffer(
2626 normalizedNumber.substring(defaultCountryCodeString.length));
2627 /** @type {i18n.phonenumbers.PhoneNumberDesc} */
2628 var generalDesc = defaultRegionMetadata.getGeneralDesc();
2629 /** @type {!RegExp} */
2630 var validNumberPattern =
2631 new RegExp(generalDesc.getNationalNumberPatternOrDefault());
2632 this.maybeStripNationalPrefixAndCarrierCode(
2633 potentialNationalNumber, defaultRegionMetadata);
2634 /** @type {string} */
2635 var potentialNationalNumberStr = potentialNationalNumber.toString();
2636 /** @type {string} */
2637 var possibleNumberPattern =
2638 generalDesc.getPossibleNumberPatternOrDefault();
2639 // If the number was not valid before but is valid now, or if it was too
2640 // long before, we consider the number with the country calling code
2641 // stripped to be a better result and keep that instead.
2642 if ((!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2643 validNumberPattern, fullNumber.toString()) &&
2644 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
2645 validNumberPattern, potentialNationalNumberStr)) ||
2646 this.testNumberLengthAgainstPattern_(possibleNumberPattern,
2647 fullNumber.toString()) ==
2648 i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG) {
2649 nationalNumber.append(potentialNationalNumberStr);
2651 phoneNumber.setCountryCodeSource(
2652 i18n.phonenumbers.PhoneNumber.CountryCodeSource
2653 .FROM_NUMBER_WITHOUT_PLUS_SIGN);
2655 phoneNumber.setCountryCode(defaultCountryCode);
2656 return defaultCountryCode;
2660 // No country calling code present.
2661 phoneNumber.setCountryCode(0);
2667 * Strips the IDD from the start of the number if present. Helper function used
2668 * by maybeStripInternationalPrefixAndNormalize.
2670 * @param {!RegExp} iddPattern the regular expression for the international
2672 * @param {!goog.string.StringBuffer} number the phone number that we wish to
2673 * strip any international dialing prefix from.
2674 * @return {boolean} true if an international prefix was present.
2677 i18n.phonenumbers.PhoneNumberUtil.prototype.parsePrefixAsIdd_ =
2678 function(iddPattern, number) {
2680 /** @type {string} */
2681 var numberStr = number.toString();
2682 if (numberStr.search(iddPattern) == 0) {
2683 /** @type {number} */
2684 var matchEnd = numberStr.match(iddPattern)[0].length;
2685 /** @type {Array.<string>} */
2686 var matchedGroups = numberStr.substring(matchEnd).match(
2687 i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN_);
2688 if (matchedGroups && matchedGroups[1] != null &&
2689 matchedGroups[1].length > 0) {
2690 /** @type {string} */
2691 var normalizedGroup = i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(
2692 matchedGroups[1], i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS,
2694 if (normalizedGroup == '0') {
2699 number.append(numberStr.substring(matchEnd));
2707 * Strips any international prefix (such as +, 00, 011) present in the number
2708 * provided, normalizes the resulting number, and indicates if an international
2709 * prefix was present.
2711 * @param {!goog.string.StringBuffer} number the non-normalized telephone number
2712 * that we wish to strip any international dialing prefix from.
2713 * @param {string} possibleIddPrefix the international direct dialing prefix
2714 * from the region we think this number may be dialed in.
2715 * @return {i18n.phonenumbers.PhoneNumber.CountryCodeSource} the corresponding
2716 * CountryCodeSource if an international dialing prefix could be removed
2717 * from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if
2718 * the number did not seem to be in international format.
2720 i18n.phonenumbers.PhoneNumberUtil.prototype.
2721 maybeStripInternationalPrefixAndNormalize = function(number,
2722 possibleIddPrefix) {
2723 /** @type {string} */
2724 var numberStr = number.toString();
2725 if (numberStr.length == 0) {
2726 return i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
2728 // Check to see if the number begins with one or more plus signs.
2729 if (i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN_.test(numberStr)) {
2730 numberStr = numberStr.replace(
2731 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN_, '');
2732 // Can now normalize the rest of the number since we've consumed the '+'
2733 // sign at the start.
2735 number.append(i18n.phonenumbers.PhoneNumberUtil.normalize(numberStr));
2736 return i18n.phonenumbers.PhoneNumber.CountryCodeSource
2737 .FROM_NUMBER_WITH_PLUS_SIGN;
2739 // Attempt to parse the first digits as an international prefix.
2740 /** @type {!RegExp} */
2741 var iddPattern = new RegExp(possibleIddPrefix);
2742 if (this.parsePrefixAsIdd_(iddPattern, number)) {
2743 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(number);
2744 return i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD;
2746 // If still not found, then try and normalize the number and then try again.
2747 // This shouldn't be done before, since non-numeric characters (+ and ~) may
2748 // legally be in the international prefix.
2749 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(number);
2750 return this.parsePrefixAsIdd_(iddPattern, number) ?
2751 i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD :
2752 i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
2757 * Strips any national prefix (such as 0, 1) present in the number provided.
2759 * @param {!goog.string.StringBuffer} number the normalized telephone number
2760 * that we wish to strip any national dialing prefix from.
2761 * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
2762 * region that we think this number is from.
2763 * @return {string} the carrier code extracted if it is present, otherwise
2764 * return an empty string.
2766 i18n.phonenumbers.PhoneNumberUtil.prototype.
2767 maybeStripNationalPrefixAndCarrierCode = function(number, metadata) {
2769 /** @type {string} */
2770 var carrierCode = '';
2771 /** @type {string} */
2772 var numberStr = number.toString();
2773 /** @type {number} */
2774 var numberLength = numberStr.length;
2775 /** @type {?string} */
2776 var possibleNationalPrefix = metadata.getNationalPrefixForParsing();
2777 if (numberLength == 0 || possibleNationalPrefix == null ||
2778 possibleNationalPrefix.length == 0) {
2779 // Early return for numbers of zero length.
2782 // Attempt to parse the first digits as a national prefix.
2783 /** @type {!RegExp} */
2784 var prefixPattern = new RegExp('^(?:' + possibleNationalPrefix + ')');
2785 /** @type {Array.<string>} */
2786 var prefixMatcher = prefixPattern.exec(numberStr);
2787 if (prefixMatcher) {
2788 /** @type {!RegExp} */
2789 var nationalNumberRule = new RegExp(
2790 metadata.getGeneralDesc().getNationalNumberPatternOrDefault());
2791 // prefixMatcher[numOfGroups] == null implies nothing was captured by the
2792 // capturing groups in possibleNationalPrefix; therefore, no transformation
2793 // is necessary, and we just remove the national prefix.
2794 /** @type {number} */
2795 var numOfGroups = prefixMatcher.length - 1;
2796 /** @type {?string} */
2797 var transformRule = metadata.getNationalPrefixTransformRule();
2798 /** @type {string} */
2799 var transformedNumber;
2800 /** @type {boolean} */
2801 var noTransform = transformRule == null || transformRule.length == 0 ||
2802 prefixMatcher[numOfGroups] == null ||
2803 prefixMatcher[numOfGroups].length == 0;
2805 transformedNumber = numberStr.substring(prefixMatcher[0].length);
2807 transformedNumber = numberStr.replace(prefixPattern, transformRule);
2809 // Check that the resultant number is viable. If not, return.
2810 if (!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(nationalNumberRule,
2811 transformedNumber)) {
2814 if ((noTransform && numOfGroups > 0 && prefixMatcher[1] != null) ||
2815 (!noTransform && numOfGroups > 1)) {
2816 carrierCode = prefixMatcher[1];
2819 number.append(transformedNumber);
2826 * Strips any extension (as in, the part of the number dialled after the call is
2827 * connected, usually indicated with extn, ext, x or similar) from the end of
2828 * the number, and returns it.
2830 * @param {!goog.string.StringBuffer} number the non-normalized telephone number
2831 * that we wish to strip the extension from.
2832 * @return {string} the phone extension.
2834 i18n.phonenumbers.PhoneNumberUtil.prototype.maybeStripExtension =
2837 /** @type {string} */
2838 var numberStr = number.toString();
2839 /** @type {number} */
2841 numberStr.search(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
2842 // If we find a potential extension, and the number preceding this is a viable
2843 // number, we assume it is an extension.
2844 if (mStart >= 0 && i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(
2845 numberStr.substring(0, mStart))) {
2846 // The numbers are captured into groups in the regular expression.
2847 /** @type {Array.<string>} */
2849 numberStr.match(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
2850 /** @type {number} */
2851 var matchedGroupsLength = matchedGroups.length;
2852 for (var i = 1; i < matchedGroupsLength; ++i) {
2853 if (matchedGroups[i] != null && matchedGroups[i].length > 0) {
2854 // We go through the capturing groups until we find one that captured
2855 // some digits. If none did, then we will return the empty string.
2857 number.append(numberStr.substring(0, mStart));
2858 return matchedGroups[i];
2867 * Checks to see that the region code used is valid, or if it is not valid, that
2868 * the number to parse starts with a + symbol so that we can attempt to infer
2869 * the region from the number.
2870 * @param {string} numberToParse number that we are attempting to parse.
2871 * @param {?string} defaultRegion the ISO 3166-1 two-letter region code that
2872 * denotes the region that we are expecting the number to be from.
2873 * @return {boolean} false if it cannot use the region provided and the region
2874 * cannot be inferred.
2877 i18n.phonenumbers.PhoneNumberUtil.prototype.checkRegionForParsing_ = function(
2878 numberToParse, defaultRegion) {
2879 // If the number is null or empty, we can't infer the region.
2880 return this.isValidRegionCode_(defaultRegion) ||
2881 (numberToParse != null && numberToParse.length > 0 &&
2882 i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN_.test(
2888 * Parses a string and returns it in proto buffer format. This method will throw
2889 * a {@link i18n.phonenumbers.Error} if the number is not considered to be a
2890 * possible number. Note that validation of whether the number is actually a
2891 * valid number for a particular region is not performed. This can be done
2892 * separately with {@link #isValidNumber}.
2894 * @param {?string} numberToParse number that we are attempting to parse. This
2895 * can contain formatting such as +, ( and -, as well as a phone number
2897 * @param {?string} defaultRegion the ISO 3166-1 two-letter region code that
2898 * denotes the region that we are expecting the number to be from. This is
2899 * only used if the number being parsed is not written in international
2900 * format. The country_code for the number in this case would be stored as
2901 * that of the default region supplied. If the number is guaranteed to start
2902 * with a '+' followed by the country calling code, then 'ZZ' or null can be
2904 * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
2905 * with the parsed number.
2906 * @throws {i18n.phonenumbers.Error} if the string is not considered to be a
2907 * viable phone number or if no default region was supplied and the number
2908 * is not in international format (does not start with +).
2910 i18n.phonenumbers.PhoneNumberUtil.prototype.parse = function(numberToParse,
2912 return this.parseHelper_(numberToParse, defaultRegion, false, true);
2917 * Parses a string and returns it in proto buffer format. This method differs
2918 * from {@link #parse} in that it always populates the raw_input field of the
2919 * protocol buffer with numberToParse as well as the country_code_source field.
2921 * @param {string} numberToParse number that we are attempting to parse. This
2922 * can contain formatting such as +, ( and -, as well as a phone number
2924 * @param {?string} defaultRegion the ISO 3166-1 two-letter region code that
2925 * denotes the region that we are expecting the number to be from. This is
2926 * only used if the number being parsed is not written in international
2927 * format. The country calling code for the number in this case would be
2928 * stored as that of the default region supplied.
2929 * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
2930 * with the parsed number.
2931 * @throws {i18n.phonenumbers.Error} if the string is not considered to be a
2932 * viable phone number or if no default region was supplied.
2934 i18n.phonenumbers.PhoneNumberUtil.prototype.parseAndKeepRawInput =
2935 function(numberToParse, defaultRegion) {
2937 if (!this.isValidRegionCode_(defaultRegion)) {
2938 if (numberToParse.length > 0 && numberToParse.charAt(0) !=
2939 i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) {
2940 throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
2943 return this.parseHelper_(numberToParse, defaultRegion, true, true);
2948 * Parses a string and returns it in proto buffer format. This method is the
2949 * same as the public {@link #parse} method, with the exception that it allows
2950 * the default region to be null, for use by {@link #isNumberMatch}.
2952 * @param {?string} numberToParse number that we are attempting to parse. This
2953 * can contain formatting such as +, ( and -, as well as a phone number
2955 * @param {?string} defaultRegion the ISO 3166-1 two-letter region code that
2956 * denotes the region that we are expecting the number to be from. This is
2957 * only used if the number being parsed is not written in international
2958 * format. The country calling code for the number in this case would be
2959 * stored as that of the default region supplied.
2960 * @param {boolean} keepRawInput whether to populate the raw_input field of the
2961 * phoneNumber with numberToParse.
2962 * @param {boolean} checkRegion should be set to false if it is permitted for
2963 * the default coregion to be null or unknown ('ZZ').
2964 * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
2965 * with the parsed number.
2966 * @throws {i18n.phonenumbers.Error}
2969 i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ =
2970 function(numberToParse, defaultRegion, keepRawInput, checkRegion) {
2972 if (numberToParse == null) {
2973 throw i18n.phonenumbers.Error.NOT_A_NUMBER;
2975 // Extract a possible number from the string passed in (this strips leading
2976 // characters that could not be the start of a phone number.)
2977 /** @type {string} */
2979 i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber(numberToParse);
2980 if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(number)) {
2981 throw i18n.phonenumbers.Error.NOT_A_NUMBER;
2984 // Check the region supplied is valid, or that the extracted number starts
2985 // with some sort of + sign so the number's region can be determined.
2986 if (checkRegion && !this.checkRegionForParsing_(number, defaultRegion)) {
2987 throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE;
2990 /** @type {i18n.phonenumbers.PhoneNumber} */
2991 var phoneNumber = new i18n.phonenumbers.PhoneNumber();
2993 phoneNumber.setRawInput(numberToParse);
2995 /** @type {!goog.string.StringBuffer} */
2996 var nationalNumber = new goog.string.StringBuffer(number);
2997 // Attempt to parse extension first, since it doesn't require region-specific
2998 // data and we want to have the non-normalised number here.
2999 /** @type {string} */
3000 var extension = this.maybeStripExtension(nationalNumber);
3001 if (extension.length > 0) {
3002 phoneNumber.setExtension(extension);
3005 /** @type {i18n.phonenumbers.PhoneMetadata} */
3006 var regionMetadata = this.getMetadataForRegion(defaultRegion);
3007 // Check to see if the number is given in international format so we know
3008 // whether this number is from the default region or not.
3009 /** @type {!goog.string.StringBuffer} */
3010 var normalizedNationalNumber = new goog.string.StringBuffer();
3011 /** @type {number} */
3012 var countryCode = this.maybeExtractCountryCode(nationalNumber.toString(),
3013 regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber);
3014 if (countryCode != 0) {
3015 /** @type {string} */
3016 var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCode);
3017 if (phoneNumberRegion != defaultRegion) {
3018 regionMetadata = this.getMetadataForRegion(phoneNumberRegion);
3021 // If no extracted country calling code, use the region supplied instead.
3022 // The national number is just the normalized version of the number we were
3024 i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(nationalNumber);
3025 normalizedNationalNumber.append(nationalNumber.toString());
3026 if (defaultRegion != null) {
3027 countryCode = regionMetadata.getCountryCodeOrDefault();
3028 phoneNumber.setCountryCode(countryCode);
3029 } else if (keepRawInput) {
3030 phoneNumber.clearCountryCodeSource();
3033 if (normalizedNationalNumber.getLength() <
3034 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3035 throw i18n.phonenumbers.Error.TOO_SHORT_NSN;
3038 if (regionMetadata != null) {
3039 /** @type {string} */
3040 var carrierCode = this.maybeStripNationalPrefixAndCarrierCode(
3041 normalizedNationalNumber, regionMetadata);
3043 phoneNumber.setPreferredDomesticCarrierCode(carrierCode);
3046 /** @type {string} */
3047 var normalizedNationalNumberStr = normalizedNationalNumber.toString();
3048 /** @type {number} */
3049 var lengthOfNationalNumber = normalizedNationalNumberStr.length;
3050 if (lengthOfNationalNumber <
3051 i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
3052 throw i18n.phonenumbers.Error.TOO_SHORT_NSN;
3054 if (lengthOfNationalNumber >
3055 i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_) {
3056 throw i18n.phonenumbers.Error.TOO_LONG;
3058 if (normalizedNationalNumberStr.charAt(0) == '0' &&
3059 regionMetadata != null &&
3060 regionMetadata.getLeadingZeroPossibleOrDefault()) {
3061 phoneNumber.setItalianLeadingZero(true);
3063 phoneNumber.setNationalNumber(parseInt(normalizedNationalNumberStr, 10));
3069 * Takes two phone numbers and compares them for equality.
3071 * <p>Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero
3072 * for Italian numbers and any extension present are the same. Returns NSN_MATCH
3073 * if either or both has no region specified, and the NSNs and extensions are
3074 * the same. Returns SHORT_NSN_MATCH if either or both has no region specified,
3075 * or the region specified is the same, and one NSN could be a shorter version
3076 * of the other number. This includes the case where one has an extension
3077 * specified, and the other does not. Returns NO_MATCH otherwise. For example,
3078 * the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH. The numbers
3079 * +1 345 657 1234 and 345 657 are a NO_MATCH.
3081 * @param {i18n.phonenumbers.PhoneNumber|string} firstNumberIn first number to
3082 * compare. If it is a string it can contain formatting, and can have
3083 * country calling code specified with + at the start.
3084 * @param {i18n.phonenumbers.PhoneNumber|string} secondNumberIn second number to
3085 * compare. If it is a string it can contain formatting, and can have
3086 * country calling code specified with + at the start.
3087 * @return {i18n.phonenumbers.PhoneNumberUtil.MatchType} NOT_A_NUMBER, NO_MATCH,
3088 * SHORT_NSN_MATCH, NSN_MATCH or EXACT_MATCH depending on the level of
3089 * equality of the two numbers, described in the method definition.
3091 i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch =
3092 function(firstNumberIn, secondNumberIn) {
3094 // If the input arguements are strings parse them to a proto buffer format.
3095 // Else make copies of the phone numbers so that the numbers passed in are not
3097 /** @type {i18n.phonenumbers.PhoneNumber} */
3099 /** @type {i18n.phonenumbers.PhoneNumber} */
3101 if (typeof firstNumberIn == 'string') {
3102 // First see if the first number has an implicit country calling code, by
3103 // attempting to parse it.
3105 firstNumber = this.parse(
3106 firstNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
3108 if (e != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
3109 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3111 // The first number has no country calling code. EXACT_MATCH is no longer
3112 // possible. We parse it as if the region was the same as that for the
3113 // second number, and if EXACT_MATCH is returned, we replace this with
3115 if (typeof secondNumberIn != 'string') {
3116 /** @type {string} */
3117 var secondNumberRegion = this.getRegionCodeForCountryCode(
3118 secondNumberIn.getCountryCodeOrDefault());
3119 if (secondNumberRegion !=
3120 i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_) {
3122 firstNumber = this.parse(firstNumberIn, secondNumberRegion);
3124 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3126 /** @type {i18n.phonenumbers.PhoneNumberUtil.MatchType} */
3127 var match = this.isNumberMatch(firstNumber, secondNumberIn);
3129 i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH) {
3130 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
3135 // If the second number is a string or doesn't have a valid country
3136 // calling code, we parse the first number without country calling code.
3138 firstNumber = this.parseHelper_(firstNumberIn, null, false, false);
3140 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3144 firstNumber = firstNumberIn.clone();
3146 if (typeof secondNumberIn == 'string') {
3148 secondNumber = this.parse(
3149 secondNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
3150 return this.isNumberMatch(firstNumberIn, secondNumber);
3152 if (e != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
3153 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
3155 return this.isNumberMatch(secondNumberIn, firstNumber);
3158 secondNumber = secondNumberIn.clone();
3160 // First clear raw_input, country_code_source and
3161 // preferred_domestic_carrier_code fields and any empty-string extensions so
3162 // that we can use the proto-buffer equality method.
3163 firstNumber.clearRawInput();
3164 firstNumber.clearCountryCodeSource();
3165 firstNumber.clearPreferredDomesticCarrierCode();
3166 secondNumber.clearRawInput();
3167 secondNumber.clearCountryCodeSource();
3168 secondNumber.clearPreferredDomesticCarrierCode();
3169 if (firstNumber.hasExtension() && firstNumber.getExtension().length == 0) {
3170 firstNumber.clearExtension();
3172 if (secondNumber.hasExtension() && secondNumber.getExtension().length == 0) {
3173 secondNumber.clearExtension();
3176 // Early exit if both had extensions and these are different.
3177 if (firstNumber.hasExtension() && secondNumber.hasExtension() &&
3178 firstNumber.getExtension() != secondNumber.getExtension()) {
3179 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
3181 /** @type {number} */
3182 var firstNumberCountryCode = firstNumber.getCountryCodeOrDefault();
3183 /** @type {number} */
3184 var secondNumberCountryCode = secondNumber.getCountryCodeOrDefault();
3185 // Both had country_code specified.
3186 if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) {
3187 if (firstNumber.equals(secondNumber)) {
3188 return i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH;
3189 } else if (firstNumberCountryCode == secondNumberCountryCode &&
3190 this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
3191 // A SHORT_NSN_MATCH occurs if there is a difference because of the
3192 // presence or absence of an 'Italian leading zero', the presence or
3193 // absence of an extension, or one NSN being a shorter variant of the
3195 return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
3197 // This is not a match.
3198 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
3200 // Checks cases where one or both country_code fields were not specified. To
3201 // make equality checks easier, we first set the country_code fields to be
3203 firstNumber.setCountryCode(0);
3204 secondNumber.setCountryCode(0);
3205 // If all else was the same, then this is an NSN_MATCH.
3206 if (firstNumber.equals(secondNumber)) {
3207 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
3209 if (this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
3210 return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
3212 return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
3217 * Returns true when one national number is the suffix of the other or both are
3220 * @param {i18n.phonenumbers.PhoneNumber} firstNumber the first PhoneNumber
3222 * @param {i18n.phonenumbers.PhoneNumber} secondNumber the second PhoneNumber
3224 * @return {boolean} true if one PhoneNumber is the suffix of the other one.
3227 i18n.phonenumbers.PhoneNumberUtil.prototype.isNationalNumberSuffixOfTheOther_ =
3228 function(firstNumber, secondNumber) {
3230 /** @type {string} */
3231 var firstNumberNationalNumber = '' + firstNumber.getNationalNumber();
3232 /** @type {string} */
3233 var secondNumberNationalNumber = '' + secondNumber.getNationalNumber();
3234 // Note that endsWith returns true if the numbers are equal.
3235 return goog.string.endsWith(firstNumberNationalNumber,
3236 secondNumberNationalNumber) ||
3237 goog.string.endsWith(secondNumberNationalNumber,
3238 firstNumberNationalNumber);
3243 * Returns true if the number can only be dialled from within the region. If
3244 * unknown, or the number can be dialled from outside the region as well,
3245 * returns false. Does not check the number is a valid number.
3246 * TODO: Make this method public when we have enough metadata to make it
3247 * worthwhile. Currently visible for testing purposes only.
3249 * @param {i18n.phonenumbers.PhoneNumber} number the phone-number for which we
3250 * want to know whether it is only diallable from within the region.
3251 * @return {boolean} true if the number can only be dialled from within the
3254 i18n.phonenumbers.PhoneNumberUtil.prototype.canBeInternationallyDialled =
3256 /** @type {?string} */
3257 var regionCode = this.getRegionCodeForNumber(number);
3258 /** @type {string} */
3259 var nationalSignificantNumber = this.getNationalSignificantNumber(number);
3260 if (!this.isValidRegionCode_(regionCode)) {
3263 /** @type {i18n.phonenumbers.PhoneMetadata} */
3264 var metadata = this.getMetadataForRegion(regionCode);
3265 return !this.isNumberMatchingDesc_(nationalSignificantNumber,
3266 metadata.getNoInternationalDialling());
3271 * Check whether the entire input sequence can be matched against the regular
3274 * @param {!RegExp|string} regex the regular expression to match against.
3275 * @param {string} str the string to test.
3276 * @return {boolean} true if str can be matched entirely against regex.
3279 i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_ = function(regex, str) {
3280 /** @type {Array.<string>} */
3281 var matchedGroups = (typeof regex == 'string') ?
3282 str.match('^(?:' + regex + ')$') : str.match(regex);
3283 if (matchedGroups && matchedGroups[0].length == str.length) {