summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlararennie@google.com <lararennie@google.com@ee073f10-1060-11df-b6a4-87a95322a99c>2012-02-09 15:17:29 +0000
committerlararennie@google.com <lararennie@google.com@ee073f10-1060-11df-b6a4-87a95322a99c>2012-02-09 15:17:29 +0000
commit35f0f61f256a275bba4f6ce331754602ebd13d8d (patch)
tree4bcae31bd06fbe9f8f69fd34298c42aa99a62a7d
parentb326557982dbdb6db73212e85199d47eaa9156dc (diff)
downloadandroid_external_libphonenumbergoogle-35f0f61f256a275bba4f6ce331754602ebd13d8d.tar.gz
android_external_libphonenumbergoogle-35f0f61f256a275bba4f6ce331754602ebd13d8d.tar.bz2
android_external_libphonenumbergoogle-35f0f61f256a275bba4f6ce331754602ebd13d8d.zip
JAVA: libphonenumber v4.6. New countries: BQ, CW, SS, metadata updates & bug fixes.
git-svn-id: http://libphonenumber.googlecode.com/svn/trunk@426 ee073f10-1060-11df-b6a4-87a95322a99c
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java12
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java15
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java276
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ANbin595 -> 293 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AXbin546 -> 657 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BFbin406 -> 418 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJbin401 -> 419 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQbin0 -> 335 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BRbin823 -> 797 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BSbin619 -> 619 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CWbin0 -> 485 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJbin313 -> 410 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FIbin763 -> 884 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_INbin3996 -> 4018 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LVbin345 -> 368 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MWbin574 -> 493 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RSbin728 -> 866 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SCbin518 -> 525 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SSbin0 -> 376 bytes
-rw-r--r--java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VNbin1000 -> 1126 bytes
-rw-r--r--java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java40
-rw-r--r--java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java8
-rw-r--r--java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java46
-rw-r--r--java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java.orig76
-rw-r--r--java/release_notes.txt16
-rw-r--r--resources/PhoneNumberMetaData.xml600
26 files changed, 699 insertions, 390 deletions
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java
index 915c02b..922ab6d 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java
@@ -31,10 +31,10 @@ public class CountryCodeToRegionCodeMap {
// countries sharing a calling code, such as the NANPA countries, the one
// indicated with "isMainCountryForCode" in the metadata should be first.
static Map<Integer, List<String>> getCountryCodeToRegionCodeMap() {
- // The capacity is set to 280 as there are 210 different country codes,
+ // The capacity is set to 281 as there are 211 different country codes,
// and this offers a load factor of roughly 0.75.
Map<Integer, List<String>> countryCodeToRegionCodeMap =
- new HashMap<Integer, List<String>>(280);
+ new HashMap<Integer, List<String>>(281);
ArrayList<String> listWithRegionCode;
@@ -254,6 +254,10 @@ public class CountryCodeToRegionCodeMap {
countryCodeToRegionCodeMap.put(98, listWithRegionCode);
listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SS");
+ countryCodeToRegionCodeMap.put(211, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
listWithRegionCode.add("MA");
countryCodeToRegionCodeMap.put(212, listWithRegionCode);
@@ -685,8 +689,10 @@ public class CountryCodeToRegionCodeMap {
listWithRegionCode.add("UY");
countryCodeToRegionCodeMap.put(598, listWithRegionCode);
- listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode = new ArrayList<String>(3);
+ listWithRegionCode.add("CW");
listWithRegionCode.add("AN");
+ listWithRegionCode.add("BQ");
countryCodeToRegionCodeMap.put(599, listWithRegionCode);
listWithRegionCode = new ArrayList<String>(1);
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java
index e0892ba..d4bc575 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java
@@ -71,6 +71,14 @@ final class PhoneNumberMatcher implements Iterator<PhoneNumberMatch> {
Pattern.compile("(?:(?:[0-3]?\\d/[01]?\\d)|(?:[01]?\\d/[0-3]?\\d))/(?:[12]\\d)?\\d{2}");
/**
+ * Matches timestamps. Examples: "2012-01-02 08:00". Note that the reg-ex does not include the
+ * trailing ":\d\d" -- that is covered by TIME_STAMPS_SUFFIX.
+ */
+ private static final Pattern TIME_STAMPS =
+ Pattern.compile("[12]\\d{3}[-/]?[01]\\d[-/]?[0-3]\\d [0-2]\\d$");
+ private static final Pattern TIME_STAMPS_SUFFIX = Pattern.compile(":[0-5]\\d");
+
+ /**
* Pattern to check that brackets match. Opening brackets should be closed within a phone number.
* This also checks that there is something inside the brackets. Having no brackets at all is also
* fine.
@@ -310,6 +318,13 @@ final class PhoneNumberMatcher implements Iterator<PhoneNumberMatch> {
if (PUB_PAGES.matcher(candidate).find() || SLASH_SEPARATED_DATES.matcher(candidate).find()) {
return null;
}
+ // Skip potential time-stamps.
+ if (TIME_STAMPS.matcher(candidate).find()) {
+ String followingText = text.toString().substring(offset + candidate.length());
+ if (TIME_STAMPS_SUFFIX.matcher(followingText).lookingAt()) {
+ return null;
+ }
+ }
// Try to come up with a valid match given the entire candidate.
String rawString = candidate.toString();
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
index 76212c6..883a676 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
@@ -95,6 +95,8 @@ public class PhoneNumberUtil {
// The PLUS_SIGN signifies the international prefix.
static final char PLUS_SIGN = '+';
+ private static final char STAR_SIGN = '*';
+
private static final String RFC3966_EXTN_PREFIX = ";ext=";
// A map that contains characters that are essential when dialling. That means any of the
@@ -256,11 +258,11 @@ public class PhoneNumberUtil {
// carrier codes, for example in Brazilian phone numbers. We also allow multiple "+" characters at
// the start.
// Corresponds to the following:
- // plus_sign*([punctuation]*[digits]){3,}([punctuation]|[digits]|[alpha])*
+ // plus_sign*(([punctuation]|[star])*[digits]){3,}([punctuation]|[star]|[digits]|[alpha])*
// Note VALID_PUNCTUATION starts with a -, so must be the first in the range.
private static final String VALID_PHONE_NUMBER =
- "[" + PLUS_CHARS + "]*(?:[" + VALID_PUNCTUATION + "]*" + DIGITS + "){3,}[" +
- VALID_PUNCTUATION + VALID_ALPHA + DIGITS + "]*";
+ "[" + PLUS_CHARS + "]*(?:[" + VALID_PUNCTUATION + STAR_SIGN + "]*" + DIGITS + "){3,}[" +
+ VALID_PUNCTUATION + STAR_SIGN + VALID_ALPHA + DIGITS + "]*";
// Default extension prefix to use when formatting. This will be put in front of any extension
// component of the number, after the main national number is formatted. For example, if you wish
@@ -993,6 +995,7 @@ public class PhoneNumberUtil {
return normalizedNumber.toString();
}
+ // @VisibleForTesting
static synchronized PhoneNumberUtil getInstance(
String baseFileLocation,
Map<Integer, List<String>> countryCallingCodeToRegionCodeMap) {
@@ -1020,6 +1023,14 @@ public class PhoneNumberUtil {
}
/**
+ * Convenience method to get a list of what global network calling codes the library has metadata
+ * for.
+ */
+ public Set<Integer> getSupportedGlobalNetworkCallingCodes() {
+ return countryCodeToNonGeographicalMetadataMap.keySet();
+ }
+
+ /**
* Gets a {@link PhoneNumberUtil} instance to carry out international phone number formatting,
* parsing, or validation. The instance is loaded with phone number metadata for a number of most
* commonly used regions.
@@ -1091,23 +1102,24 @@ public class PhoneNumberUtil {
// Early exit for E164 case since no formatting of the national number needs to be applied.
// Extensions are not formatted.
formattedNumber.append(nationalSignificantNumber);
- formatNumberByFormat(countryCallingCode, PhoneNumberFormat.E164, formattedNumber);
+ prefixNumberWithCountryCallingCode(countryCallingCode, PhoneNumberFormat.E164,
+ formattedNumber);
return;
}
// Note getRegionCodeForCountryCode() is used because formatting information for regions which
// share a country calling code is contained by only one region for performance reasons. For
// example, for NANPA regions it will be contained in the metadata for US.
String regionCode = getRegionCodeForCountryCode(countryCallingCode);
- if (!hasValidCountryCallingCode(countryCallingCode)) {
+ if (!hasValidCountryCallingCode(countryCallingCode)) {
formattedNumber.append(nationalSignificantNumber);
return;
}
PhoneMetadata metadata =
getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
- formattedNumber.append(formatNationalNumber(nationalSignificantNumber, metadata, numberFormat));
- maybeGetFormattedExtension(number, metadata, numberFormat, formattedNumber);
- formatNumberByFormat(countryCallingCode, numberFormat, formattedNumber);
+ formattedNumber.append(formatNsn(nationalSignificantNumber, metadata, numberFormat));
+ maybeAppendFormattedExtension(number, metadata, numberFormat, formattedNumber);
+ prefixNumberWithCountryCallingCode(countryCallingCode, numberFormat, formattedNumber);
}
/**
@@ -1133,18 +1145,24 @@ public class PhoneNumberUtil {
if (!hasValidCountryCallingCode(countryCallingCode)) {
return nationalSignificantNumber;
}
- List<NumberFormat> userDefinedFormatsCopy =
- new ArrayList<NumberFormat>(userDefinedFormats.size());
PhoneMetadata metadata =
getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
- for (NumberFormat numFormat : userDefinedFormats) {
- String nationalPrefixFormattingRule = numFormat.getNationalPrefixFormattingRule();
+
+ StringBuilder formattedNumber = new StringBuilder(20);
+
+ NumberFormat formattingPattern =
+ chooseFormattingPatternForNumber(userDefinedFormats, nationalSignificantNumber);
+ if (formattingPattern == null) {
+ // If no pattern above is matched, we format the number as a whole.
+ formattedNumber.append(nationalSignificantNumber);
+ } else {
+ NumberFormat numFormatCopy = new NumberFormat();
+ // Before we do a replacement of the national prefix pattern $NP with the national prefix, we
+ // need to copy the rule so that subsequent replacements for different numbers have the
+ // appropriate national prefix.
+ numFormatCopy.mergeFrom(formattingPattern);
+ String nationalPrefixFormattingRule = formattingPattern.getNationalPrefixFormattingRule();
if (nationalPrefixFormattingRule.length() > 0) {
- // Before we do a replacement of the national prefix pattern $NP with the national prefix,
- // we need to copy the rule so that subsequent replacements for different numbers have the
- // appropriate national prefix.
- NumberFormat numFormatCopy = new NumberFormat();
- numFormatCopy.mergeFrom(numFormat);
String nationalPrefix = metadata.getNationalPrefix();
if (nationalPrefix.length() > 0) {
// Replace $NP with national prefix and $FG with the first group ($1).
@@ -1157,19 +1175,12 @@ public class PhoneNumberUtil {
// We don't want to have a rule for how to format the national prefix if there isn't one.
numFormatCopy.clearNationalPrefixFormattingRule();
}
- userDefinedFormatsCopy.add(numFormatCopy);
- } else {
- // Otherwise, we just add the original rule to the modified list of formats.
- userDefinedFormatsCopy.add(numFormat);
}
+ formattedNumber.append(
+ formatNsnUsingPattern(nationalSignificantNumber, numFormatCopy, numberFormat));
}
-
- StringBuilder formattedNumber =
- new StringBuilder(formatAccordingToFormats(nationalSignificantNumber,
- userDefinedFormatsCopy,
- numberFormat));
- maybeGetFormattedExtension(number, metadata, numberFormat, formattedNumber);
- formatNumberByFormat(countryCallingCode, numberFormat, formattedNumber);
+ maybeAppendFormattedExtension(number, metadata, numberFormat, formattedNumber);
+ prefixNumberWithCountryCallingCode(countryCallingCode, numberFormat, formattedNumber);
return formattedNumber.toString();
}
@@ -1197,12 +1208,11 @@ public class PhoneNumberUtil {
StringBuilder formattedNumber = new StringBuilder(20);
PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
- formattedNumber.append(formatNationalNumber(nationalSignificantNumber,
- metadata,
- PhoneNumberFormat.NATIONAL,
- carrierCode));
- maybeGetFormattedExtension(number, metadata, PhoneNumberFormat.NATIONAL, formattedNumber);
- formatNumberByFormat(countryCallingCode, PhoneNumberFormat.NATIONAL, formattedNumber);
+ formattedNumber.append(formatNsn(nationalSignificantNumber, metadata,
+ PhoneNumberFormat.NATIONAL, carrierCode));
+ maybeAppendFormattedExtension(number, metadata, PhoneNumberFormat.NATIONAL, formattedNumber);
+ prefixNumberWithCountryCallingCode(countryCallingCode, PhoneNumberFormat.NATIONAL,
+ formattedNumber);
return formattedNumber.toString();
}
@@ -1314,6 +1324,10 @@ public class PhoneNumberUtil {
public String formatOutOfCountryCallingNumber(PhoneNumber number,
String regionCallingFrom) {
if (!isValidRegionCode(regionCallingFrom)) {
+ LOGGER.log(Level.WARNING,
+ "Trying to format number from invalid region "
+ + regionCallingFrom
+ + ". International formatting applied.");
return format(number, PhoneNumberFormat.INTERNATIONAL);
}
int countryCallingCode = number.getCountryCode();
@@ -1327,7 +1341,7 @@ public class PhoneNumberUtil {
// country calling code.
return countryCallingCode + " " + format(number, PhoneNumberFormat.NATIONAL);
}
- } else if (countryCallingCode == getCountryCodeForRegion(regionCallingFrom)) {
+ } else if (countryCallingCode == getCountryCodeForValidRegion(regionCallingFrom)) {
// For regions that share a country calling code, the country calling code need not be dialled.
// This also applies when dialling within a region, so this if clause covers both these cases.
// Technically this is the case for dialling from La Reunion to other overseas departments of
@@ -1353,18 +1367,17 @@ public class PhoneNumberUtil {
PhoneMetadata metadataForRegion =
getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
String formattedNationalNumber =
- formatNationalNumber(nationalSignificantNumber,
- metadataForRegion, PhoneNumberFormat.INTERNATIONAL);
+ formatNsn(nationalSignificantNumber, metadataForRegion, PhoneNumberFormat.INTERNATIONAL);
StringBuilder formattedNumber = new StringBuilder(formattedNationalNumber);
- maybeGetFormattedExtension(number, metadataForRegion, PhoneNumberFormat.INTERNATIONAL,
- formattedNumber);
+ maybeAppendFormattedExtension(number, metadataForRegion, PhoneNumberFormat.INTERNATIONAL,
+ formattedNumber);
if (internationalPrefixForFormatting.length() > 0) {
formattedNumber.insert(0, " ").insert(0, countryCallingCode).insert(0, " ")
.insert(0, internationalPrefixForFormatting);
} else {
- formatNumberByFormat(countryCallingCode,
- PhoneNumberFormat.INTERNATIONAL,
- formattedNumber);
+ prefixNumberWithCountryCallingCode(countryCallingCode,
+ PhoneNumberFormat.INTERNATIONAL,
+ formattedNumber);
}
return formattedNumber.toString();
}
@@ -1379,6 +1392,7 @@ public class PhoneNumberUtil {
*
* Note this method guarantees no digit will be inserted, removed or modified as a result of
* formatting.
+ *
* @param number the phone number that needs to be formatted in its original number format
* @param regionCallingFrom the region whose IDD needs to be prefixed if the original number
* has one
@@ -1565,26 +1579,27 @@ public class PhoneNumberUtil {
if (isNANPACountry(regionCallingFrom)) {
return countryCode + " " + rawInput;
}
- } else if (countryCode == getCountryCodeForRegion(regionCallingFrom)) {
- // Here we copy the formatting rules so we can modify the pattern we expect to match against.
- List<NumberFormat> availableFormats =
- new ArrayList<NumberFormat>(metadataForRegionCallingFrom.numberFormatSize());
- for (NumberFormat format : metadataForRegionCallingFrom.numberFormats()) {
- NumberFormat newFormat = new NumberFormat();
- newFormat.mergeFrom(format);
- // The first group is the first group of digits that the user determined.
- newFormat.setPattern("(\\d+)(.*)");
- // Here we just concatenate them back together after the national prefix has been fixed.
- newFormat.setFormat("$1$2");
- availableFormats.add(newFormat);
+ } else if (isValidRegionCode(regionCallingFrom) &&
+ countryCode == getCountryCodeForValidRegion(regionCallingFrom)) {
+ NumberFormat formattingPattern =
+ chooseFormattingPatternForNumber(metadataForRegionCallingFrom.numberFormats(),
+ nationalNumber);
+ if (formattingPattern == null) {
+ // If no pattern above is matched, we format the original input.
+ return rawInput;
}
- // Now we format using these patterns instead of the default pattern, but with the national
- // prefix prefixed if necessary, by choosing the format rule based on the leading digits
- // present in the unformatted national number.
+ NumberFormat newFormat = new NumberFormat();
+ newFormat.mergeFrom(formattingPattern);
+ // The first group is the first group of digits that the user wrote together.
+ newFormat.setPattern("(\\d+)(.*)");
+ // Here we just concatenate them back together after the national prefix has been fixed.
+ newFormat.setFormat("$1$2");
+ // Now we format using this pattern instead of the default pattern, but with the national
+ // prefix prefixed if necessary.
// This will not work in the cases where the pattern (and not the leading digits) decide
// whether a national prefix needs to be used, since we have overridden the pattern to match
// anything, but that is not the case in the metadata to date.
- return formatAccordingToFormats(rawInput, availableFormats, PhoneNumberFormat.NATIONAL);
+ return formatNsnUsingPattern(rawInput, newFormat, PhoneNumberFormat.NATIONAL);
}
String internationalPrefixForFormatting = "";
// If an unsupported region-calling-from is entered, or a country with multiple international
@@ -1600,15 +1615,15 @@ public class PhoneNumberUtil {
StringBuilder formattedNumber = new StringBuilder(rawInput);
String regionCode = getRegionCodeForCountryCode(countryCode);
PhoneMetadata metadataForRegion = getMetadataForRegionOrCallingCode(countryCode, regionCode);
- maybeGetFormattedExtension(number, metadataForRegion,
- PhoneNumberFormat.INTERNATIONAL, formattedNumber);
+ maybeAppendFormattedExtension(number, metadataForRegion,
+ PhoneNumberFormat.INTERNATIONAL, formattedNumber);
if (internationalPrefixForFormatting.length() > 0) {
formattedNumber.insert(0, " ").insert(0, countryCode).insert(0, " ")
.insert(0, internationalPrefixForFormatting);
} else {
// Invalid region entered as country-calling-from (so no metadata was found for it) or the
// region chosen has multiple international dialling prefixes.
- formatNumberByFormat(countryCode,
+ prefixNumberWithCountryCallingCode(countryCode,
PhoneNumberFormat.INTERNATIONAL,
formattedNumber);
}
@@ -1632,9 +1647,9 @@ public class PhoneNumberUtil {
/**
* A helper function that is used by format and formatByPattern.
*/
- private void formatNumberByFormat(int countryCallingCode,
- PhoneNumberFormat numberFormat,
- StringBuilder formattedNumber) {
+ private void prefixNumberWithCountryCallingCode(int countryCallingCode,
+ PhoneNumberFormat numberFormat,
+ StringBuilder formattedNumber) {
switch (numberFormat) {
case E164:
formattedNumber.insert(0, countryCallingCode).insert(0, PLUS_SIGN);
@@ -1651,21 +1666,19 @@ public class PhoneNumberUtil {
}
}
- // Simple wrapper of formatNationalNumber for the common case of no carrier code.
- private String formatNationalNumber(String number,
- PhoneMetadata metadata,
- PhoneNumberFormat numberFormat) {
- return formatNationalNumber(number, metadata, numberFormat, null);
+ // Simple wrapper of formatNsn for the common case of no carrier code.
+ private String formatNsn(String number, PhoneMetadata metadata, PhoneNumberFormat numberFormat) {
+ return formatNsn(number, metadata, numberFormat, null);
}
// Note in some regions, the national number can be written in two completely different ways
// depending on whether it forms part of the NATIONAL format or INTERNATIONAL format. The
// numberFormat parameter here is used to specify which format to use for those cases. If a
// carrierCode is specified, this will be inserted into the formatted string to replace $CC.
- private String formatNationalNumber(String number,
- PhoneMetadata metadata,
- PhoneNumberFormat numberFormat,
- String carrierCode) {
+ private String formatNsn(String number,
+ PhoneMetadata metadata,
+ PhoneNumberFormat numberFormat,
+ String carrierCode) {
List<NumberFormat> intlNumberFormats = metadata.intlNumberFormats();
// When the intlNumberFormats exists, we use that to format national number for the
// INTERNATIONAL format instead of using the numberDesc.numberFormats.
@@ -1673,13 +1686,10 @@ public class PhoneNumberUtil {
(intlNumberFormats.size() == 0 || numberFormat == PhoneNumberFormat.NATIONAL)
? metadata.numberFormats()
: metadata.intlNumberFormats();
- String formattedNationalNumber =
- formatAccordingToFormats(number, availableFormats, numberFormat, carrierCode);
- if (numberFormat == PhoneNumberFormat.RFC3966) {
- formattedNationalNumber =
- SEPARATOR_PATTERN.matcher(formattedNationalNumber).replaceAll("-");
- }
- return formattedNationalNumber;
+ NumberFormat formattingPattern = chooseFormattingPatternForNumber(availableFormats, number);
+ return (formattingPattern == null)
+ ? number
+ : formatNsnUsingPattern(number, formattingPattern, numberFormat, carrierCode);
}
private NumberFormat chooseFormattingPatternForNumber(List<NumberFormat> availableFormats,
@@ -1698,50 +1708,58 @@ public class PhoneNumberUtil {
return null;
}
- // Simple wrapper of formatAccordingToFormats for the common case of no carrier code.
- private String formatAccordingToFormats(String nationalNumber,
- List<NumberFormat> availableFormats,
- PhoneNumberFormat numberFormat) {
- return formatAccordingToFormats(nationalNumber, availableFormats, numberFormat, null);
+ // Simple wrapper of formatNsnUsingPattern for the common case of no carrier code.
+ private String formatNsnUsingPattern(String nationalNumber,
+ NumberFormat formattingPattern,
+ PhoneNumberFormat numberFormat) {
+ return formatNsnUsingPattern(nationalNumber, formattingPattern, numberFormat, null);
}
// Note that carrierCode is optional - if NULL or an empty string, no carrier code replacement
// will take place.
- private String formatAccordingToFormats(String nationalNumber,
- List<NumberFormat> availableFormats,
- PhoneNumberFormat numberFormat,
- String carrierCode) {
- NumberFormat numFormat = chooseFormattingPatternForNumber(availableFormats, nationalNumber);
- if (numFormat == null) {
- // If no pattern above is matched, we format the number as a whole.
- return nationalNumber;
- }
- String numberFormatRule = numFormat.getFormat();
- Matcher m = regexCache.getPatternForRegex(numFormat.getPattern()).matcher(nationalNumber);
+ private String formatNsnUsingPattern(String nationalNumber,
+ NumberFormat formattingPattern,
+ PhoneNumberFormat numberFormat,
+ String carrierCode) {
+ String numberFormatRule = formattingPattern.getFormat();
+ Matcher m =
+ regexCache.getPatternForRegex(formattingPattern.getPattern()).matcher(nationalNumber);
+ String formattedNationalNumber = "";
if (numberFormat == PhoneNumberFormat.NATIONAL &&
carrierCode != null && carrierCode.length() > 0 &&
- numFormat.getDomesticCarrierCodeFormattingRule().length() > 0) {
+ formattingPattern.getDomesticCarrierCodeFormattingRule().length() > 0) {
// Replace the $CC in the formatting rule with the desired carrier code.
- String carrierCodeFormattingRule = numFormat.getDomesticCarrierCodeFormattingRule();
+ String carrierCodeFormattingRule = formattingPattern.getDomesticCarrierCodeFormattingRule();
carrierCodeFormattingRule =
CC_PATTERN.matcher(carrierCodeFormattingRule).replaceFirst(carrierCode);
// Now replace the $FG in the formatting rule with the first group and the carrier code
// combined in the appropriate way.
numberFormatRule = FIRST_GROUP_PATTERN.matcher(numberFormatRule)
.replaceFirst(carrierCodeFormattingRule);
- return m.replaceAll(numberFormatRule);
+ formattedNationalNumber = m.replaceAll(numberFormatRule);
} else {
// Use the national prefix formatting rule instead.
- String nationalPrefixFormattingRule = numFormat.getNationalPrefixFormattingRule();
+ String nationalPrefixFormattingRule = formattingPattern.getNationalPrefixFormattingRule();
if (numberFormat == PhoneNumberFormat.NATIONAL &&
nationalPrefixFormattingRule != null &&
nationalPrefixFormattingRule.length() > 0) {
Matcher firstGroupMatcher = FIRST_GROUP_PATTERN.matcher(numberFormatRule);
- return m.replaceAll(firstGroupMatcher.replaceFirst(nationalPrefixFormattingRule));
+ formattedNationalNumber =
+ m.replaceAll(firstGroupMatcher.replaceFirst(nationalPrefixFormattingRule));
} else {
- return m.replaceAll(numberFormatRule);
+ formattedNationalNumber = m.replaceAll(numberFormatRule);
}
}
+ if (numberFormat == PhoneNumberFormat.RFC3966) {
+ // Strip any leading punctuation.
+ Matcher matcher = SEPARATOR_PATTERN.matcher(formattedNationalNumber);
+ if (matcher.lookingAt()) {
+ formattedNationalNumber = matcher.replaceFirst("");
+ }
+ // Replace the rest with a dash between each number group.
+ formattedNationalNumber = matcher.reset(formattedNationalNumber).replaceAll("-");
+ }
+ return formattedNationalNumber;
}
/**
@@ -1769,7 +1787,7 @@ public class PhoneNumberUtil {
public PhoneNumber getExampleNumberForType(String regionCode, PhoneNumberType type) {
// Check the region code is valid.
if (!isValidRegionCode(regionCode)) {
- LOGGER.log(Level.SEVERE, "Invalid or unknown region code provided: " + regionCode);
+ LOGGER.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode);
return null;
}
PhoneNumberDesc desc = getNumberDescByType(getMetadataForRegion(regionCode), type);
@@ -1802,6 +1820,9 @@ public class PhoneNumberUtil {
} catch (NumberParseException e) {
LOGGER.log(Level.SEVERE, e.toString());
}
+ } else {
+ LOGGER.log(Level.WARNING,
+ "Invalid or unknown country calling code provided: " + countryCallingCode);
}
return null;
}
@@ -1810,32 +1831,22 @@ public class PhoneNumberUtil {
* Appends the formatted extension of a phone number to formattedNumber, if the phone number had
* an extension specified.
*/
- private void maybeGetFormattedExtension(PhoneNumber number, PhoneMetadata metadata,
- PhoneNumberFormat numberFormat,
- StringBuilder formattedNumber) {
+ private void maybeAppendFormattedExtension(PhoneNumber number, PhoneMetadata metadata,
+ PhoneNumberFormat numberFormat,
+ StringBuilder formattedNumber) {
if (number.hasExtension() && number.getExtension().length() > 0) {
if (numberFormat == PhoneNumberFormat.RFC3966) {
formattedNumber.append(RFC3966_EXTN_PREFIX).append(number.getExtension());
} else {
- formatExtension(number.getExtension(), metadata, formattedNumber);
+ if (metadata.hasPreferredExtnPrefix()) {
+ formattedNumber.append(metadata.getPreferredExtnPrefix()).append(number.getExtension());
+ } else {
+ formattedNumber.append(DEFAULT_EXTN_PREFIX).append(number.getExtension());
+ }
}
}
}
- /**
- * Formats the extension part of the phone number by prefixing it with the appropriate extension
- * prefix. This will be the default extension prefix, unless overridden by a preferred
- * extension prefix for this region.
- */
- private void formatExtension(String extensionDigits, PhoneMetadata metadata,
- StringBuilder extension) {
- if (metadata.hasPreferredExtnPrefix()) {
- extension.append(metadata.getPreferredExtnPrefix()).append(extensionDigits);
- } else {
- extension.append(DEFAULT_EXTN_PREFIX).append(extensionDigits);
- }
- }
-
PhoneNumberDesc getNumberDescByType(PhoneMetadata metadata, PhoneNumberType type) {
switch (type) {
case PREMIUM_RATE:
@@ -1992,12 +2003,14 @@ public class PhoneNumberUtil {
*/
public boolean isValidNumberForRegion(PhoneNumber number, String regionCode) {
int countryCode = number.getCountryCode();
- if (countryCode == 0 ||
+ PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode);
+ if ((metadata == null) ||
(!REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) &&
- countryCode != getCountryCodeForRegion(regionCode))) {
+ countryCode != getCountryCodeForValidRegion(regionCode))) {
+ // Either the region code was invalid, or the country calling code for this number does not
+ // match that of the region code.
return false;
}
- PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode);
PhoneNumberDesc generalNumDesc = metadata.getGeneralDesc();
String nationalSignificantNumber = getNationalSignificantNumber(number);
@@ -2072,12 +2085,23 @@ public class PhoneNumberUtil {
*/
public int getCountryCodeForRegion(String regionCode) {
if (!isValidRegionCode(regionCode)) {
- LOGGER.log(Level.SEVERE,
+ LOGGER.log(Level.WARNING,
"Invalid or missing region code ("
+ ((regionCode == null) ? "null" : regionCode)
+ ") provided.");
return 0;
}
+ return getCountryCodeForValidRegion(regionCode);
+ }
+
+ /**
+ * Returns the country calling code for a specific region. For example, this would be 1 for the
+ * United States, and 64 for New Zealand. Assumes the region is already valid.
+ *
+ * @param regionCode the region that we want to get the country calling code for
+ * @return the country calling code for the region denoted by regionCode
+ */
+ private int getCountryCodeForValidRegion(String regionCode) {
PhoneMetadata metadata = getMetadataForRegion(regionCode);
return metadata.getCountryCode();
}
@@ -2098,7 +2122,7 @@ public class PhoneNumberUtil {
*/
public String getNddPrefixForRegion(String regionCode, boolean stripNonDigits) {
if (!isValidRegionCode(regionCode)) {
- LOGGER.log(Level.SEVERE,
+ LOGGER.log(Level.WARNING,
"Invalid or missing region code ("
+ ((regionCode == null) ? "null" : regionCode)
+ ") provided.");
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AN
index ece2723..10f648f 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AN
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AN
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX
index 91d11b5..18ca4d0 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF
index 01ca8c3..802997e 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ
index af2439c..09eee90 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ
new file mode 100644
index 0000000..6ac0880
--- /dev/null
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR
index 845377b..31ed9bc 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS
index 2a8b978..d280135 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW
new file mode 100644
index 0000000..8f4170e
--- /dev/null
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ
index 57af3c0..0683a64 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI
index 1e7307e..9995781 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN
index 326d131..f07407a 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV
index 335c85d..fd64fb8 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW
index 2fb6952..fdb4093 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS
index 81c0848..bf324e6 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC
index 39ee643..7f55e5a 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS
new file mode 100644
index 0000000..a8293fd
--- /dev/null
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS
Binary files differ
diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN
index 2d29291..d775464 100644
--- a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN
+++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN
Binary files differ
diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java
index 7c30588..1d23fc2 100644
--- a/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java
+++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java
@@ -141,6 +141,13 @@ public class ExampleNumbersTest extends TestCase {
assertEquals(0, wrongTypeCases.size());
}
+ public void testVoicemail() throws Exception {
+ Set<PhoneNumberType> voicemailTypes = EnumSet.of(PhoneNumberType.VOICEMAIL);
+ checkNumbersValidAndCorrectType(PhoneNumberType.VOICEMAIL, voicemailTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
public void testSharedCost() throws Exception {
Set<PhoneNumberType> sharedCostTypes = EnumSet.of(PhoneNumberType.SHARED_COST);
checkNumbersValidAndCorrectType(PhoneNumberType.SHARED_COST, sharedCostTypes);
@@ -162,11 +169,44 @@ public class ExampleNumbersTest extends TestCase {
}
if (exampleNumber != null && phoneNumberUtil.canBeInternationallyDialled(exampleNumber)) {
wrongTypeCases.add(exampleNumber);
+ LOGGER.log(Level.SEVERE, "Number " + exampleNumber.toString()
+ + " should not be internationally diallable");
}
}
assertEquals(0, wrongTypeCases.size());
}
+ // TODO: Update this to use connectsToEmergencyNumber or similar once that is
+ // implemented.
+ public void testEmergency() throws Exception {
+ int wrongTypeCounter = 0;
+ for (String regionCode : phoneNumberUtil.getSupportedRegions()) {
+ PhoneNumberDesc desc =
+ phoneNumberUtil.getMetadataForRegion(regionCode).getEmergency();
+ if (desc.hasExampleNumber()) {
+ String exampleNumber = desc.getExampleNumber();
+ if (!exampleNumber.matches(desc.getPossibleNumberPattern()) ||
+ !exampleNumber.matches(desc.getNationalNumberPattern())) {
+ wrongTypeCounter++;
+ LOGGER.log(Level.SEVERE, "Emergency example number test failed for " + regionCode);
+ }
+ }
+ }
+ assertEquals(0, wrongTypeCounter);
+ }
+
+ public void testGlobalNetworkNumbers() throws Exception {
+ for (Integer callingCode : phoneNumberUtil.getSupportedGlobalNetworkCallingCodes()) {
+ PhoneNumber exampleNumber =
+ phoneNumberUtil.getExampleNumberForNonGeoEntity(callingCode);
+ assertNotNull("No example phone number for calling code " + callingCode, exampleNumber);
+ if (!phoneNumberUtil.isValidNumber(exampleNumber)) {
+ invalidCases.add(exampleNumber);
+ LOGGER.log(Level.SEVERE, "Failed validation for " + exampleNumber.toString());
+ }
+ }
+ }
+
public void testEveryRegionHasAnExampleNumber() throws Exception {
for (String regionCode : phoneNumberUtil.getSupportedRegions()) {
PhoneNumber exampleNumber = phoneNumberUtil.getExampleNumber(regionCode);
diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java
index a9f841d..9127f77 100644
--- a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java
+++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java
@@ -370,6 +370,9 @@ public class PhoneNumberMatcherTest extends TestCase {
new NumberTest("1/12/2011", RegionCode.US),
new NumberTest("10/12/82", RegionCode.DE),
new NumberTest("650x2531234", RegionCode.US),
+ new NumberTest("2012-01-02 08:00", RegionCode.US),
+ new NumberTest("2012/01/02 08:00", RegionCode.US),
+ new NumberTest("20120102 08:00", RegionCode.US),
};
/**
@@ -398,12 +401,13 @@ public class PhoneNumberMatcherTest extends TestCase {
new NumberTest("9002309. 158", RegionCode.US),
new NumberTest("12 7/8 - 14 12/34 - 5", RegionCode.US),
new NumberTest("12.1 - 23.71 - 23.45", RegionCode.US),
-
new NumberTest("800 234 1 111x1111", RegionCode.US),
new NumberTest("1979-2011 100", RegionCode.US),
new NumberTest("+494949-4-94", RegionCode.DE), // National number in wrong format
new NumberTest("\uFF14\uFF11\uFF15\uFF16\uFF16\uFF16\uFF16-\uFF17\uFF17\uFF17", RegionCode.US),
-
+ new NumberTest("2012-0102 08", RegionCode.US), // Very strange formatting.
+ new NumberTest("2012-01-02 08", RegionCode.US),
+ new NumberTest("1800-10-10 22", RegionCode.AU), // Breakdown assistance number.
};
/**
diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java
index be62ef8..d78e80f 100644
--- a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java
+++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java
@@ -709,6 +709,9 @@ public class PhoneNumberUtilTest extends TestCase {
assertEquals("+1 (650) 253-0000", phoneUtil.formatByPattern(US_NUMBER,
PhoneNumberFormat.INTERNATIONAL,
newNumberFormats));
+ assertEquals("+1-650-253-0000", phoneUtil.formatByPattern(US_NUMBER,
+ PhoneNumberFormat.RFC3966,
+ newNumberFormats));
// $NP is set to '1' for the US. Here we check that for other NANPA countries the US rules are
// followed.
@@ -1027,6 +1030,18 @@ public class PhoneNumberUtilTest extends TestCase {
assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE));
assertTrue(phoneUtil.isValidNumberForRegion(INTERNATIONAL_TOLL_FREE, RegionCode.UN001));
assertFalse(phoneUtil.isValidNumberForRegion(INTERNATIONAL_TOLL_FREE, RegionCode.US));
+ assertFalse(phoneUtil.isValidNumberForRegion(INTERNATIONAL_TOLL_FREE, RegionCode.ZZ));
+
+ PhoneNumber invalidNumber = new PhoneNumber();
+ // Invalid country calling codes.
+ invalidNumber.setCountryCode(3923).setNationalNumber(2366L);
+ assertFalse(phoneUtil.isValidNumberForRegion(invalidNumber, RegionCode.ZZ));
+ invalidNumber.setCountryCode(3923).setNationalNumber(2366L);
+ assertFalse(phoneUtil.isValidNumberForRegion(invalidNumber, RegionCode.UN001));
+ invalidNumber.setCountryCode(0).setNationalNumber(2366L);
+ assertFalse(phoneUtil.isValidNumberForRegion(invalidNumber, RegionCode.UN001));
+ invalidNumber.setCountryCode(0);
+ assertFalse(phoneUtil.isValidNumberForRegion(invalidNumber, RegionCode.ZZ));
}
public void testIsNotValidNumber() {
@@ -1048,6 +1063,13 @@ public class PhoneNumberUtilTest extends TestCase {
invalidNumber.setCountryCode(64).setNationalNumber(3316005L);
assertFalse(phoneUtil.isValidNumber(invalidNumber));
+ invalidNumber.clear();
+ // Invalid country calling codes.
+ invalidNumber.setCountryCode(3923).setNationalNumber(2366L);
+ assertFalse(phoneUtil.isValidNumber(invalidNumber));
+ invalidNumber.setCountryCode(0);
+ assertFalse(phoneUtil.isValidNumber(invalidNumber));
+
assertFalse(phoneUtil.isValidNumber(INTERNATIONAL_TOLL_FREE_TOO_LONG));
}
@@ -1551,6 +1573,10 @@ public class PhoneNumberUtilTest extends TestCase {
// already possible.
usNumber.setCountryCode(1).setNationalNumber(1234567890L);
assertEquals(usNumber, phoneUtil.parse("123-456-7890", RegionCode.US));
+
+ // Test star numbers. Although this is not strictly valid, we would like to make sure we can
+ // parse the output we produce when formatting the number.
+ assertEquals(JP_STAR_NUMBER, phoneUtil.parse("+81 *2345", RegionCode.JP));
}
public void testParseNumberWithAlphaCharacters() throws Exception {
@@ -1703,6 +1729,26 @@ public class PhoneNumberUtilTest extends TestCase {
e.getErrorType());
}
try {
+ String plusStar = "+***";
+ phoneUtil.parse(plusStar, RegionCode.DE);
+ fail("This should not parse without throwing an exception " + plusStar);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
+ String plusStarPhoneNumber = "+*******91";
+ phoneUtil.parse(plusStarPhoneNumber, RegionCode.DE);
+ fail("This should not parse without throwing an exception " + plusStarPhoneNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
String tooShortPhoneNumber = "+49 0";
phoneUtil.parse(tooShortPhoneNumber, RegionCode.DE);
fail("This should not parse without throwing an exception " + tooShortPhoneNumber);
diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java.orig b/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java.orig
deleted file mode 100644
index b1ae29b..0000000
--- a/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java.orig
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2011 The Libphonenumber Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.i18n.phonenumbers;
-
-import junit.framework.TestCase;
-
-import java.io.InputStream;
-
-/**
- * @author Shaopeng Jia
- */
-public class ShortNumberUtilTest extends TestCase {
- private ShortNumberUtil shortUtil;
- static final String TEST_META_DATA_FILE_PREFIX =
- "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting";
-
- public ShortNumberUtilTest() {
- PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(
- TEST_META_DATA_FILE_PREFIX,
- CountryCodeToRegionCodeMapForTesting.getCountryCodeToRegionCodeMap());
- shortUtil = new ShortNumberUtil(phoneUtil);
- }
-
- public void testConnectsToEmergencyNumber_US() {
- assertTrue(shortUtil.connectsToEmergencyNumber("911", RegionCode.US));
- assertTrue(shortUtil.connectsToEmergencyNumber("119", RegionCode.US));
- assertFalse(shortUtil.connectsToEmergencyNumber("999", RegionCode.US));
- }
-
- public void testConnectsToEmergencyNumberLongNumber_US() {
- assertTrue(shortUtil.connectsToEmergencyNumber("9116666666", RegionCode.US));
- assertTrue(shortUtil.connectsToEmergencyNumber("1196666666", RegionCode.US));
- assertFalse(shortUtil.connectsToEmergencyNumber("9996666666", RegionCode.US));
- }
-
- public void testConnectsToEmergencyNumberWithFormatting_US() {
- assertTrue(shortUtil.connectsToEmergencyNumber("9-1-1", RegionCode.US));
- assertTrue(shortUtil.connectsToEmergencyNumber("1-1-9", RegionCode.US));
- assertFalse(shortUtil.connectsToEmergencyNumber("9-9-9", RegionCode.US));
- }
-
- public void testConnectsToEmergencyNumberWithPlusSign_US() {
- assertFalse(shortUtil.connectsToEmergencyNumber("+911", RegionCode.US));
- assertFalse(shortUtil.connectsToEmergencyNumber("\uFF0B911", RegionCode.US));
- assertFalse(shortUtil.connectsToEmergencyNumber(" +911", RegionCode.US));
- assertFalse(shortUtil.connectsToEmergencyNumber("+119", RegionCode.US));
- assertFalse(shortUtil.connectsToEmergencyNumber("+999", RegionCode.US));
- }
-
- public void testConnectsToEmergencyNumber_BR() {
- assertTrue(shortUtil.connectsToEmergencyNumber("911", RegionCode.BR));
- assertTrue(shortUtil.connectsToEmergencyNumber("190", RegionCode.BR));
- assertFalse(shortUtil.connectsToEmergencyNumber("999", RegionCode.BR));
- }
-
- public void testConnectsToEmergencyNumberLongNumber_BR() {
- // Brazilian emergency numbers don't work when additional digits are appended.
- assertFalse(shortUtil.connectsToEmergencyNumber("9111", RegionCode.BR));
- assertFalse(shortUtil.connectsToEmergencyNumber("1900", RegionCode.BR));
- assertFalse(shortUtil.connectsToEmergencyNumber("9996", RegionCode.BR));
- }
-}
diff --git a/java/release_notes.txt b/java/release_notes.txt
index 4df4e8d..5970332 100644
--- a/java/release_notes.txt
+++ b/java/release_notes.txt
@@ -1,3 +1,19 @@
+February 9th, 2012: libphonenumber-4.6
+* Bug fixes
+ - Fix for formatByPattern to enable RFC formatting to work
+ - Fix for RFC formatting to work even when the international formatting rule starts with
+ punctuation
+ - Logging consistency changes - some warnings are no longer printed, others have become only
+ WARNINGS
+ - Fix for isValidNumberForRegion potentially throwing a NPE
+ - Parsing Israeli * numbers written in international format now works
+ - PhoneNumberMatcher doesn't match timestamps as phone-numbers
+* Metadata changes
+ - Updates for AN, AX, BF, BJ, BR, BS, DJ, FI, IN, LV, MW, RS, SC, VN
+ - New countries supported: SS (South Sudan), CW (Curaçao) and BQ (Bonaire, Sint Eustatius and Saba)
+* Refactoring of the private formatting functions in PhoneNumberUtil to ensure names are more
+ descriptive and to reduce code duplication.
+
January 19th, 2012: libphonenumber-4.5
* Code changes
- Support for non-geographical country calling codes (e.g. +800).
diff --git a/resources/PhoneNumberMetaData.xml b/resources/PhoneNumberMetaData.xml
index 8fcb1be..bdbf55c 100644
--- a/resources/PhoneNumberMetaData.xml
+++ b/resources/PhoneNumberMetaData.xml
@@ -669,92 +669,38 @@
</territory>
<!-- Netherlands Antilles -->
+ <!-- Note this country no longer exists. This metadata exists only to validate old Sint Maarten
+ numbers through their parallel running period (which ends Sep 2012). -->
+ <!-- The link below no longer works, since ITU deleted this document since this country no
+ longer exists. We keep it here as a record of the last place we found information on this
+ country. -->
<!-- http://www.itu.int/oth/T0202000097/en -->
<territory id="AN" countryCode="599" internationalPrefix="00">
- <availableFormats>
- <numberFormat pattern="(\d{3})(\d{4})">
- <leadingDigits>[13-7]</leadingDigits>
- <format>$1 $2</format>
- </numberFormat>
- <numberFormat pattern="(9)(\d{3})(\d{4})">
- <leadingDigits>9</leadingDigits>
- <format>$1 $2 $3</format>
- </numberFormat>
- </availableFormats>
+ <!-- Shares formatting patterns with "CW". -->
<generalDesc>
- <nationalNumberPattern>[13-79]\d{6,7}</nationalNumberPattern>
- <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <nationalNumberPattern>5\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
</generalDesc>
<fixedLine>
- <!-- The prefixes listed beginning with 5 are in fact for Sint Maarten and should be removed
- when parallel running has ended (predicted to be September 2012). -->
<nationalNumberPattern>
- (?:
- 318|
- 5(?:
- 25|
- 4\d|
- 8[239]
- )|
- 7(?:
- 1[578]|
- 50
- )|
- 9(?:
- [48]\d{2}|
- 50\d|
- 7(?:
- 2[0-2]|
- [34]\d|
- 6[35-7]|
- 77
- )
- )
- )\d{4}|
- 416[0239]\d{3}
+ 5(?:
+ 4\d|
+ 8[239]
+ )\d{4}
</nationalNumberPattern>
- <exampleNumber>7151234</exampleNumber>
+ <exampleNumber>5451234</exampleNumber>
</fixedLine>
<mobile>
<nationalNumberPattern>
- (?:
- 318|
- 5(?:
- 1[01]|
- 2[0-7]|
- 5\d|
- 8[016-8]
- )|
- 7(?:
- 0[01]|
- [89]\d
- )|
- 9(?:
- 5(?:
- [1246]\d|
- 3[01]
- )|
- 6(?:
- [1679]\d|
- 3[01]
- )
- )
- )\d{4}|
- 416[15-8]\d{3}
+ 5(?:
+ 1[01]|
+ 2[0-7]|
+ 5\d|
+ 8[016-8]
+ )\d{4}
</nationalNumberPattern>
- <exampleNumber>3181234</exampleNumber>
+ <exampleNumber>5101234</exampleNumber>
</mobile>
- <!-- Value-added services are lumped together under shared cost, since we are not sure exactly
- what they are. -->
- <sharedCost>
- <nationalNumberPattern>
- (?:
- 10|
- 69
- )\d{5}
- </nationalNumberPattern>
- <exampleNumber>1011234</exampleNumber>
- </sharedCost>
<emergency>
<!-- http://www.rijksdienstcn.com/index.php?view=pagina&id=126&set_language=EN -->
<nationalNumberPattern>
@@ -1770,6 +1716,31 @@
</nationalNumberPattern>
<possibleNumberPattern>\d{5,12}</possibleNumberPattern>
</generalDesc>
+ <noInternationalDialling>
+ <!-- According to the national numbering plan, service numbers are in general not accessible
+ from abroad, although 600/700/800 numbers may be. -->
+ <nationalNumberPattern>
+ [13]00\d{3,7}|
+ 2(?:
+ 0(?:
+ 0\d{3,7}|
+ 2[023]\d{1,6}|
+ 9[89]\d{1,6}
+ )
+ )|
+ 60(?:
+ [12]\d{5,6}|
+ 6\d{7}
+ )|
+ 7(?:
+ 1\d{7}|
+ 3\d{8}|
+ 5[03-9]\d{2,7}
+ )
+ </nationalNumberPattern>
+ <possibleNumberPattern>\d{5,10}</possibleNumberPattern>
+ <exampleNumber>100123</exampleNumber>
+ </noInternationalDialling>
<fixedLine>
<nationalNumberPattern>18[1-8]\d{3,9}</nationalNumberPattern>
<possibleNumberPattern>\d{6,12}</possibleNumberPattern>
@@ -1795,18 +1766,22 @@
<exampleNumber>600123456</exampleNumber>
</premiumRate>
<uan>
+ <!-- Covers nationwide non-geographic numbers, and nationwide "service numbers", typically
+ assigned to institutions such as universities, the national post, etc, where they are
+ not otherwise classified as toll-free or premium-rate numbers. -->
<nationalNumberPattern>
- 10[1-9]\d{3,7}|
+ [13]0\d{4,8}|
2(?:
0(?:
- [16-8]\d{3,7}|
- 2[14-9]\d{1,6}|
- [3-5]\d{2,7}|
- 9[0-7]\d{1,6}
+ [016-8]\d{3,7}|
+ [2-59]\d{2,7}
)|
9\d{4,8}
)|
- 30[1-9]\d{3,7}|
+ 60(?:
+ [12]\d{5,6}|
+ 6\d{7}
+ )|
7(?:
1\d{7}|
3\d{8}|
@@ -2451,7 +2426,7 @@
</numberFormat>
</availableFormats>
<generalDesc>
- <nationalNumberPattern>[2457]\d{7}</nationalNumberPattern>
+ <nationalNumberPattern>[24-7]\d{7}</nationalNumberPattern>
<possibleNumberPattern>\d{8}</possibleNumberPattern>
</generalDesc>
<fixedLine>
@@ -2478,11 +2453,14 @@
since diallable numbers have been found outside the range that the document specifies.
Including 716 as well since many numbers seem to have this prefix. -->
<nationalNumberPattern>
- 7(?:
- [02-68]\d|
- 1[0-4689]|
- 7[0-6]|
- 9[0-689]
+ (?:
+ 60[0-3]|
+ 7(?:
+ [02-68]\d|
+ 1[0-4689]|
+ 7[0-6]|
+ 9[0-689]
+ )
)\d{5}
</nationalNumberPattern>
<exampleNumber>70123456</exampleNumber>
@@ -2808,13 +2786,18 @@
<possibleNumberPattern>\d{4}</possibleNumberPattern>
<exampleNumber>7312</exampleNumber>
</tollFree>
- <!-- Other numbers beginning with 81 are reserved for _either_ free phone or shared-cost, but
- there is no clear differentiation between these. -->
<voip>
<nationalNumberPattern>857[58]\d{4}</nationalNumberPattern>
<possibleNumberPattern>\d{8}</possibleNumberPattern>
<exampleNumber>85751234</exampleNumber>
</voip>
+ <!-- Numbers beginning with 81 are reserved for _either_ free phone or shared-cost (same cost
+ as a local-call.) We model these as UAN since we have no more detailed information. -->
+ <uan>
+ <nationalNumberPattern>81\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>81123456</exampleNumber>
+ </uan>
<emergency>
<nationalNumberPattern>11[78]</nationalNumberPattern>
<possibleNumberPattern>\d{3}</possibleNumberPattern>
@@ -3031,6 +3014,51 @@
</emergency>
</territory>
+ <!-- Bonaire, Sint Eustatius and Saba -->
+ <!-- http://www.itu.int/oth/T02020000F8/en -->
+ <territory id="BQ" countryCode="599" internationalPrefix="00">
+ <!-- Shares formatting patterns with CW. -->
+ <generalDesc>
+ <nationalNumberPattern>[347]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>
+ (?:
+ 318[023]|
+ 416[0239]|
+ 7(?:
+ 1[578]|
+ 50
+ )\d
+ )\d{3}
+ </nationalNumberPattern>
+ <exampleNumber>7151234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>
+ (?:
+ 318[1456]|
+ 416[15-8]|
+ 7(?:
+ 0[01]|
+ [89]\d
+ )\d
+ )\d{3}|
+ </nationalNumberPattern>
+ <exampleNumber>3181234</exampleNumber>
+ </mobile>
+ <emergency>
+ <!-- http://www.rijksdienstcn.com/index.php?view=pagina&id=126&set_language=EN -->
+ <nationalNumberPattern>
+ 112|
+ 911
+ </nationalNumberPattern>
+ <possibleNumberPattern>\d{3}</possibleNumberPattern>
+ <exampleNumber>112</exampleNumber>
+ </emergency>
+ </territory>
+
<!-- Brazil -->
<!-- http://en.wikipedia.org/wiki/%2B55 -->
<territory id="BR" countryCode="55"
@@ -3051,10 +3079,6 @@
</numberFormat>
<numberFormat pattern="([34]00\d)(\d{4})">
<leadingDigits>[34]00</leadingDigits>
- <leadingDigits>
- 400|
- 3003
- </leadingDigits>
<format>$1-$2</format>
</numberFormat>
<numberFormat nationalPrefixFormattingRule="$NP$FG"
@@ -3068,12 +3092,7 @@
<possibleNumberPattern>\d{8,10}</possibleNumberPattern>
</generalDesc>
<noInternationalDialling>
- <nationalNumberPattern>
- (?:
- 400\d|
- 3003
- )\d{4}
- </nationalNumberPattern>
+ <nationalNumberPattern>[34]00\d{5}</nationalNumberPattern>
<possibleNumberPattern>\d{8}</possibleNumberPattern>
<exampleNumber>40041234</exampleNumber>
</noInternationalDialling>
@@ -3124,12 +3143,7 @@
<exampleNumber>300123456</exampleNumber>
</premiumRate>
<sharedCost>
- <nationalNumberPattern>
- (?:
- 400\d|
- 3003
- )\d{4}
- </nationalNumberPattern>
+ <nationalNumberPattern>[34]00\d{5}</nationalNumberPattern>
<possibleNumberPattern>\d{8}</possibleNumberPattern>
<exampleNumber>40041234</exampleNumber>
</sharedCost>
@@ -3148,7 +3162,7 @@
</territory>
<!-- Bahamas -->
- <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000100001MSWE.pdf -->
+ <!-- http://www.itu.int/oth/T0202000010/en -->
<territory id="BS" countryCode="1" leadingDigits="242"
nationalPrefix="1" internationalPrefix="011">
<generalDesc>
@@ -3196,7 +3210,7 @@
81
)|
5(?:
- 2[34]|
+ 2[45]|
3[35]|
44|
5[1-9]|
@@ -4911,6 +4925,81 @@
</emergency>
</territory>
+ <!-- Curaçao -->
+ <!-- http://www.itu.int/oth/T02020000F5/en -->
+ <territory id="CW" countryCode="599" internationalPrefix="00" mainCountryForCode="true">
+ <!-- All the formatting patterns for country-code 599 are here. -->
+ <availableFormats>
+ <numberFormat pattern="(\d{3})(\d{4})">
+ <leadingDigits>[13-7]</leadingDigits>
+ <format>$1 $2</format>
+ </numberFormat>
+ <numberFormat pattern="(9)(\d{3})(\d{4})">
+ <leadingDigits>9</leadingDigits>
+ <format>$1 $2 $3</format>
+ </numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[169]\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>
+ 9(?:
+ [48]\d{2}|
+ 50\d|
+ 7(?:
+ 2[0-2]|
+ [34]\d|
+ 6[35-7]|
+ 77
+ )
+ )\d{4}
+ </nationalNumberPattern>
+ <exampleNumber>94151234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>
+ 9(?:
+ 5(?:
+ [1246]\d|
+ 3[01]
+ )|
+ 6(?:
+ [1679]\d|
+ 3[01]
+ )
+ )\d{4}
+ </nationalNumberPattern>
+ <exampleNumber>95181234</exampleNumber>
+ </mobile>
+ <pager>
+ <nationalNumberPattern>955\d{5}</nationalNumberPattern>
+ <exampleNumber>95581234</exampleNumber>
+ </pager>
+ <sharedCost>
+ <!-- Value-added services are lumped together under shared cost, since we are not sure
+ exactly what they are. -->
+ <nationalNumberPattern>
+ (?:
+ 10|
+ 69
+ )\d{5}
+ </nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>1011234</exampleNumber>
+ </sharedCost>
+ <emergency>
+ <!-- http://www.rijksdienstcn.com/index.php?view=pagina&id=126&set_language=EN -->
+ <nationalNumberPattern>
+ 112|
+ 911
+ </nationalNumberPattern>
+ <possibleNumberPattern>\d{3}</possibleNumberPattern>
+ <exampleNumber>112</exampleNumber>
+ </emergency>
+ </territory>
+
<!-- Cyprus -->
<!-- http://www.itu.int/oth/T0202000034/en -->
<territory id="CY" countryCode="357" internationalPrefix="00">
@@ -5404,30 +5493,36 @@
<!-- http://www.itu.int/oth/T020200003A/en -->
<territory id="DJ" countryCode="253" internationalPrefix="00">
<availableFormats>
- <!-- The number format here is suggested in the plan and used online,
- although the phone numbers of the national numbering authority itself on
- the plan do not follow this. -->
<numberFormat pattern="(\d{2})(\d{2})(\d{2})">
<format>$1 $2 $3</format>
</numberFormat>
+ <numberFormat pattern="(\d{2})(\d{2})(\d{2})(\d{2})">
+ <format>$1 $2 $3 $4</format>
+ </numberFormat>
</availableFormats>
+ <!--TODO: Remove support for 6-digit numbers after March 1st, 2012, when the national
+ numbering plan is going to migrate to 8 digits. -->
<generalDesc>
- <nationalNumberPattern>[1-8]\d{5}</nationalNumberPattern>
- <possibleNumberPattern>\d{6}</possibleNumberPattern>
+ <nationalNumberPattern>[1-8]\d{5,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
</generalDesc>
<fixedLine>
- <!-- Includes "Numéro long CDMA fixe" numbers starting with the digit 5. -->
+ <!-- Includes "Numéro long CDMA fixe" numbers. -->
<nationalNumberPattern>
(?:
1[05]|
[2-5]\d
- )\d{4}
+ )\d{4}|
+ 2(?:
+ 1[2-5]|
+ 7[45]|
+ )\d{5}
</nationalNumberPattern>
- <exampleNumber>251234</exampleNumber>
+ <exampleNumber>21360003</exampleNumber>
</fixedLine>
<mobile>
- <nationalNumberPattern>[6-8]\d{5}</nationalNumberPattern>
- <exampleNumber>601234</exampleNumber>
+ <nationalNumberPattern>(?:77)?[6-8]\d{5}</nationalNumberPattern>
+ <exampleNumber>77831001</exampleNumber>
</mobile>
<emergency>
<nationalNumberPattern>1[78]</nationalNumberPattern>
@@ -6389,6 +6484,15 @@
<territory id="FI" countryCode="358" internationalPrefix="00|99[049]" nationalPrefix="0"
nationalPrefixFormattingRule="$NP$FG" mainCountryForCode="true">
<availableFormats>
+ <numberFormat pattern="(\d{3})(\d{3,7})">
+ <leadingDigits>
+ (?:
+ [1-3]00|
+ [6-8]0
+ )
+ </leadingDigits>
+ <format>$1 $2</format>
+ </numberFormat>
<numberFormat pattern="(\d{2})(\d{4,10})">
<leadingDigits>
2[09]|
@@ -6405,10 +6509,6 @@
</leadingDigits>
<format>$1 $2</format>
</numberFormat>
- <numberFormat pattern="([6-8]00)(\d{4,7})">
- <leadingDigits>[6-8]0</leadingDigits>
- <format>$1 $2</format>
- </numberFormat>
</availableFormats>
<generalDesc>
<nationalNumberPattern>
@@ -6417,6 +6517,31 @@
</nationalNumberPattern>
<possibleNumberPattern>\d{5,12}</possibleNumberPattern>
</generalDesc>
+ <noInternationalDialling>
+ <!-- According to the national numbering plan, service numbers are in general not accessible
+ from abroad, although 600/700/800 numbers may be. -->
+ <nationalNumberPattern>
+ [13]00\d{3,7}|
+ 2(?:
+ 0(?:
+ 0\d{3,7}|
+ 2[023]\d{1,6}|
+ 9[89]\d{1,6}
+ )
+ )|
+ 60(?:
+ [12]\d{5,6}|
+ 6\d{7}
+ )|
+ 7(?:
+ 1\d{7}|
+ 3\d{8}|
+ 5[03-9]\d{2,7}
+ )
+ </nationalNumberPattern>
+ <possibleNumberPattern>\d{5,10}</possibleNumberPattern>
+ <exampleNumber>100123</exampleNumber>
+ </noInternationalDialling>
<fixedLine>
<!-- This is limited to geographic numbers - non-geographic nationwide subscriber numbers
are listed under UAN. It also excludes Åland numbers. -->
@@ -6453,18 +6578,22 @@
<exampleNumber>600123456</exampleNumber>
</premiumRate>
<uan>
+ <!-- Covers nationwide non-geographic numbers, and nationwide "service numbers", typically
+ assigned to institutions such as universities, the national post, etc, where they are
+ not otherwise classified as toll-free or premium-rate numbers. -->
<nationalNumberPattern>
- 10[1-9]\d{3,7}|
+ [13]0\d{4,8}|
2(?:
0(?:
- [16-8]\d{3,7}|
- 2[14-9]\d{1,6}|
- [3-5]\d{2,7}|
- 9[0-7]\d{1,6}
+ [016-8]\d{3,7}|
+ [2-59]\d{2,7}
)|
9\d{4,8}
)|
- 30[1-9]\d{3,7}|
+ 60(?:
+ [12]\d{5,6}|
+ 6\d{7}
+ )|
7(?:
1\d{7}|
3\d{8}|
@@ -9798,9 +9927,9 @@
2[236-9]|
3[0479]|
4[0-68]|
- 5[0-579]
+ 5[0-57-9]
6[05789]
- 7[12569]|
+ 7[123569]|
8[0124-9]|
9[02-9]
)|
@@ -9822,7 +9951,7 @@
9[689]
)|
4(?:
- 0[245789]|
+ 0[1245789]|
1[15-9]|
[29][89]|
39|
@@ -9877,7 +10006,7 @@
8[567]
)|
3(?:
- 0[235-8]|
+ 0[0235-8]|
4[14789]|
74|
90
@@ -9894,6 +10023,7 @@
30|
4[47]|
53|
+ 85|
7[45]|
9[015]
)|
@@ -9903,6 +10033,7 @@
)|
7(?:
1[24]|
+ 33|
[2569]
)|
8(?:
@@ -9910,13 +10041,13 @@
17|
2[024-8]|
44|
- 5[389]|
+ 5[3589]|
6[0167]
)|
9(?:
[057-9]|
2[35-9]|
- 3[09]|
+ 3[019]|
4[03678]|
6[0-46-9]
)
@@ -10295,14 +10426,13 @@
<!-- A couple of additional prefixes not found on the wikipedia page, are added because SMS
messages have been successfully sent to these numbers. It seems almost impossible to
know for some of these numbers whether they are land-line or mobile, since the ranges
- overlap. Extra prefixes added: 7277, 730[124-689], 735[0-4789], 738[1-9], 740[47-9],
- 750[79], 7520, 7796, 787[2-4], 789[146], 810[0-8], 811[56], 812[0-2569], 814[0-35],
- 8171, 8179, 8197, 822[1-689], 823\d, 8252, 826[0-7], 827[01357], 828[567],
- 829[0-246-9], the ranges in 83X excepting 8303, 8344 and 8390, 840[0-57-9], 842[2-689],
- 843[0-59], 844[0-489], 845[0-24-9], 846[09], 847[0135], 848[0-8], 850[079], 8511,
- 852[0-689], 8530, 854[47], 857[45], 8595, 860[125-9], 865[03-79], 867[09], 868[0-579],
- 869[0-467], 8712, 872[013-9], 875[1-35-9], 876[0-8], 879[24589], 882[04], 885[89],
- 8887, 892[679], 894[6-8], 896[3469]. -->
+ overlap. Extra prefixes added: 7277, 730[124-689], 735[0-2478], 738[1-57], 740[479],
+ 750[79], 7796, 787[34], 7896, 810[1-358], 811[56], 812[02569], 814[01], 8171, 8179,
+ 822[1-689], 823[0-24-9], 826[0-35-7], 827[0137], 829[0-2479], the ranges in 83X
+ excepting 830[037], 834[14] and 8390, 840[02-57-9], 842[24-689], 843[0-59], 844[0-489],
+ 845[0-24-689], 846[09], 847[0135], 848[0-8], 850[79], 852[02-589], 8530, 854[47], 8595,
+ 860[1259], 865[03-79], 867[09], 868[349], 869[0-46], 872[013-9], 875[1-35-9],
+ 876[0-47], 879[4589], 8824, 8859, 892[67], 894[6-8], 896[346]. -->
<nationalNumberPattern>
(?:
7(?:
@@ -10320,7 +10450,7 @@
9[689]
)|
4(?:
- 0[245789]|
+ 0[1245789]|
1[15-9]|
[29][89]|
39|
@@ -10378,7 +10508,7 @@
8[567]
)|
3(?:
- 0[235-8]|
+ 0[0235-8]|
4[14789]|
74|
90
@@ -10396,6 +10526,7 @@
4[47]|
53|
7[45]|
+ 85|
9[015]
)|
6(?:
@@ -10404,6 +10535,7 @@
)|
7(?:
1[24]|
+ 33|
[2569]\d
)|
8(?:
@@ -10411,13 +10543,13 @@
17|
2[024-8]|
44|
- 5[389]|
+ 5[3589]|
6[0167]
)|
9(?:
[057-9]\d|
2[35-9]|
- 3[09]|
+ 3[019]|
4[036-8]|
6[0-46-9]
)
@@ -14303,6 +14435,7 @@
<!-- Latvia -->
<!-- http://www.itu.int/oth/T0202000076/en -->
+ <!-- http://en.wikipedia.org/wiki/+371 -->
<territory id="LV" countryCode="371" internationalPrefix="00">
<availableFormats>
<numberFormat pattern="([2689]\d)(\d{3})(\d{3})">
@@ -14314,8 +14447,8 @@
<possibleNumberPattern>\d{8}</possibleNumberPattern>
</generalDesc>
<fixedLine>
- <nationalNumberPattern>6\d{7}</nationalNumberPattern>
- <exampleNumber>61234567</exampleNumber>
+ <nationalNumberPattern>6[3-8]\d{6}</nationalNumberPattern>
+ <exampleNumber>63123456</exampleNumber>
</fixedLine>
<mobile>
<nationalNumberPattern>2\d{7}</nationalNumberPattern>
@@ -14329,6 +14462,10 @@
<nationalNumberPattern>90\d{6}</nationalNumberPattern>
<exampleNumber>90123456</exampleNumber>
</premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>81\d{6}</nationalNumberPattern>
+ <exampleNumber>81123456</exampleNumber>
+ </sharedCost>
<emergency>
<nationalNumberPattern>
0[123]|
@@ -15917,7 +16054,7 @@
nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
<availableFormats>
<numberFormat pattern="(\d)(\d{3})(\d{3})">
- <leadingDigits>[13-5]</leadingDigits>
+ <leadingDigits>1</leadingDigits>
<format>$1 $2 $3</format>
</numberFormat>
<numberFormat pattern="(2\d{2})(\d{3})(\d{3})">
@@ -15928,25 +16065,14 @@
<leadingDigits>[1789]</leadingDigits>
<format>$1 $2 $3 $4</format>
</numberFormat>
- <!-- Delete in Jan 2012. -->
- <numberFormat pattern="(\d)(\d{3})(\d{3})">
- <leadingDigits>[89]</leadingDigits>
- <format>$1 $2 $3</format>
- </numberFormat>
</availableFormats>
- <!-- According to the plan, the switch from 7 to 9 digits for mobile numbers happened in July
- 2009. However, online numbers don't seem to reflect this - even on the telephone company
- websites. Recent information provided by ITU stated that final migration happened on 30th
- November 2011, and from December 1st only the 9-digit plan will be in use. We will delete
- the old-format numbers in January 2010. -->
<generalDesc>
<nationalNumberPattern>
(?:
- [3-5]|
- [27]\d{2}|
- [189](?:
+ 1(?:
\d{2}
- )?
+ )?|
+ [2789]\d{2}
)\d{6}
</nationalNumberPattern>
<possibleNumberPattern>\d{7,9}</possibleNumberPattern>
@@ -15967,16 +16093,12 @@
<nationalNumberPattern>
(?:
111|
- [3-5]|
77\d|
- 8(?:
- 8\d
- )?|
- 9(?:
- 9\d
- )?
+ 88\d|
+ 99\d
)\d{6}
</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
<exampleNumber>991234567</exampleNumber>
</mobile>
<emergency>
@@ -19092,13 +19214,44 @@
</numberFormat>
</availableFormats>
<generalDesc>
- <nationalNumberPattern>[1-36-9]\d{4,11}</nationalNumberPattern>
+ <!-- The complicated pattern here is to distinguish between Pristina (area code 38, followed
+ by 2-9) and the country calling code (381). -->
+ <nationalNumberPattern>
+ [126-9]\d{4,11}|
+ 3(?:
+ [0-79]\d{3,10}|
+ 8[2-9]\d{2,9}
+ )
+ </nationalNumberPattern>
<possibleNumberPattern>\d{5,12}</possibleNumberPattern>
</generalDesc>
<fixedLine>
- <nationalNumberPattern>[1-3]\d{6,11}</nationalNumberPattern>
+ <!-- Most subscriber numbers may not start with 0 or 1. Exceptionally, the prefix 11 1[5-7]
+ has been issused, so we allow 11 1X here. -->
+ <nationalNumberPattern>
+ (?:
+ 1(?:
+ [02-9][2-9]|
+ 1[1-9]
+ )\d|
+ 2(?:
+ [0-24-7][2-9]\d|
+ [389](?:
+ 0[2-9]|
+ [2-9]\d
+ )
+ )|
+ 3(?:
+ [0-8][2-9]\d|
+ 9(?:
+ [2-9]\d|
+ 0[2-9]
+ )
+ )
+ )\d{3,8}
+ </nationalNumberPattern>
<possibleNumberPattern>\d{5,12}</possibleNumberPattern>
- <exampleNumber>101234567</exampleNumber>
+ <exampleNumber>10234567</exampleNumber>
</fixedLine>
<mobile>
<nationalNumberPattern>
@@ -19517,6 +19670,8 @@
<exampleNumber>4217123</exampleNumber>
</fixedLine>
<mobile>
+ <!-- Although wikipedia says the prefix 28 is as-of-yet unallocated, open-source users have
+ already reported seeing numbers with this prefix. -->
<nationalNumberPattern>
2(?:
5(?:
@@ -19526,7 +19681,8 @@
7(?:
[0-79]\d|
8[24-9]
- )
+ )|
+ 8\d{2}
)\d{3}
</nationalNumberPattern>
<possibleNumberPattern>\d{7}</possibleNumberPattern>
@@ -20544,6 +20700,59 @@
</emergency>
</territory>
+ <!-- South Sudan -->
+ <!-- http://www.itu.int/oth/T02020000F9/en -->
+ <!-- http://en.wikipedia.org/wiki/+211 -->
+ <!-- These number sources disagree over whether the number length should be 7 or 10 digits. The
+ contact numbers for the South Sudan telecommunications authority, along with all numbers
+ seen online, are 9 digits, so we follow this instead. -->
+ <territory id="SS" countryCode="211" internationalPrefix="00" nationalPrefix="0">
+ <availableFormats>
+ <numberFormat pattern="(\d{3})(\d{3})(\d{3})" nationalPrefixFormattingRule="$NP$FG">
+ <format>$1 $2 $3</format>
+ </numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1489]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- 1[67] has been included as per the ITU document, even though no online numbers can be
+ found. -->
+ <nationalNumberPattern>
+ (?:
+ 1[67]\d|
+ 811
+ )\d{6}
+ </nationalNumberPattern>
+ <exampleNumber>811123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <!-- Online numbers indicate that 95 is used by Vivacell, [49]77 by Gemtel, 91 by Zain,
+ 9[29] by MTN (although it is unclear if 477 is still in use). 12 has been ascribed
+ to "Sudani", but it is not clear whether they are in fact still operating in South
+ Sudan. Patterns here are derived entirely from numbers found online. -->
+ <nationalNumberPattern>
+ (?:
+ 1(?:
+ 02|
+ 2[1269]
+ )|
+ 477|
+ 9(?:
+ 0[03689]|
+ 1\d|
+ 2[024-9]|
+ 5[5-79]|
+ 77|
+ 98
+ )
+ )\d{6}
+ </nationalNumberPattern>
+ <exampleNumber>977123456</exampleNumber>
+ </mobile>
+ </territory>
+
<!-- Sao Tome and Principe -->
<!-- http://www.itu.int/oth/T02020000B6/en -->
<territory id="ST" countryCode="239" internationalPrefix="00">
@@ -20636,6 +20845,7 @@
<!-- Sint Maarten -->
<!-- http://www.nanpa.com/pdf/PL_429.pdf -->
+ <!-- http://www.itu.int/oth/T02020000F7/en -->
<territory id="SX" countryCode="1" leadingDigits="721"
nationalPrefix="1" internationalPrefix="011">
<generalDesc>
@@ -23205,6 +23415,10 @@
nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG"
nationalPrefixOptionalWhenFormatting="true">
<availableFormats>
+ <numberFormat pattern="([17]99)(\d{4})">
+ <leadingDigits>[17]99</leadingDigits>
+ <format>$1 $2</format>
+ </numberFormat>
<numberFormat pattern="([48])(\d{4})(\d{4})">
<leadingDigits>[48]</leadingDigits>
<format>$1 $2 $3</format>
@@ -23214,7 +23428,7 @@
2[025-79]|
3[0136-9]|
5[2-9]|
- 6[0-46-9]|
+ 6[0-46-8]|
7[02-79]
</leadingDigits>
<format>$1 $2 $3</format>
@@ -23245,7 +23459,7 @@
<leadingDigits>
1(?:
[26]|
- 88|
+ 8[68]|
99
)
</leadingDigits>
@@ -23259,11 +23473,20 @@
</availableFormats>
<generalDesc>
<nationalNumberPattern>
- 8\d{5,8}|
- [1-79]\d{7,9}
+ [17]\d{6,9}|
+ [2-69]\d{7,9}|
+ 8\d{6,8}
</nationalNumberPattern>
<possibleNumberPattern>\d{7,10}</possibleNumberPattern>
</generalDesc>
+ <noInternationalDialling>
+ <nationalNumberPattern>
+ [17]99\d{4}|
+ 69\d{5,6}
+ </nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>1992000</exampleNumber>
+ </noInternationalDialling>
<fixedLine>
<nationalNumberPattern>
(?:
@@ -23276,7 +23499,7 @@
[0136-9]|
[25][01]
)|
- [48]\d|
+ 4\d|
5(?:
[01][01]|
[2-9]
@@ -23288,12 +23511,11 @@
7(?:
[02-79]|
[18][01]
- )
- )\d{7}|
- 69\d{5,6}|
- 80\d{5}
+ )|
+ 8[1-9]
+ )\d{7}
</nationalNumberPattern>
- <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
<exampleNumber>2101234567</exampleNumber>
</fixedLine>
<mobile>
@@ -23303,7 +23525,7 @@
1(?:
2\d|
6[3-9]|
- 88|
+ 8[68]|
99
)
)\d{7}
@@ -23321,6 +23543,18 @@
<possibleNumberPattern>\d{8,10}</possibleNumberPattern>
<exampleNumber>1900123456</exampleNumber>
</premiumRate>
+ <uan>
+ <!-- These include non-geographic fixed numbers, such as for government ministries. While
+ listed as "private networks", they may actually be callable from within Vietnam. (They are
+ "private" in the sense that ordinary people could not be assigned these numbers.) -->
+ <nationalNumberPattern>
+ [17]99\d{4}|
+ 69\d{5,6}|
+ 80\d{5}
+ </nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>1992000</exampleNumber>
+ </uan>
<emergency>
<nationalNumberPattern>11[345]</nationalNumberPattern>
<possibleNumberPattern>\d{3}</possibleNumberPattern>