├── .nvmrc ├── .eslintignore ├── example ├── client │ ├── .eslintrc │ └── index.js ├── webpack.config.js ├── README.md └── index.html ├── .eslintrc ├── __tests__ ├── .eslintrc ├── index.spec.ts ├── test_match.ts └── data.csv ├── .babelrc ├── .github └── ISSUE_TEMPLATE │ ├── 2--all-other-issues.md │ └── 1_phone_number_format_issue.yml ├── scripts └── add-new-rules │ ├── tsconfig.json │ ├── interface.ts │ └── index.ts ├── jest.config.js ├── .gitignore ├── tsconfig.json ├── webpack.config.js ├── LICENSE ├── package.json ├── .npmignore ├── src ├── index.ts ├── lib │ └── utility.ts └── data │ └── country_phone_data.ts ├── README.md └── test_generate.js /.nvmrc: -------------------------------------------------------------------------------- 1 | v12.22.0 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | coverage 3 | lib 4 | -------------------------------------------------------------------------------- /example/client/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "aftership/frontend", 3 | "rules": { 4 | "max-lines": 0 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "aftership", 3 | "rules": { 4 | "max-lines": 0, 5 | "comma-dangle": "off" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /__tests__/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "aftership", 3 | "env": { 4 | "jest": true, 5 | "comma-dangle": "off" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "targets": { 5 | "node": "6.11" 6 | } 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2--all-other-issues.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 2. All other issues 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /scripts/add-new-rules/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "lib": ["es2015"], 6 | "esModuleInterop": true, 7 | "allowJs": true 8 | } 9 | } -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | preset: 'ts-jest', 5 | testEnvironment: 'node', 6 | coverageDirectory: './coverage/', 7 | collectCoverage: true, 8 | transform: { 9 | '^.+\\.(ts|tsx)?$': 'ts-jest', 10 | '^.+\\.(js|jsx)$': 'babel-jest', 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /scripts/add-new-rules/interface.ts: -------------------------------------------------------------------------------- 1 | export interface IStackDriverError { 2 | jsonPayload: { 3 | data: string; 4 | message: "The phone number is not valid."; 5 | }; 6 | } 7 | 8 | export interface ITwilioPhoneNumberInstance { 9 | countryCode: string; 10 | phoneNumber: string; 11 | } 12 | 13 | export interface Iiso3166 { 14 | alpha2: string; 15 | country_code: string; 16 | mobile_begin_with: string[]; 17 | phone_number_lengths: number[]; 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # =============== log ignore 2 | node_modules/ 3 | 4 | # =========================== DO NOT touch below v1.0.0 =============================== 5 | 6 | # =============== RubyMine.gitignore 7 | # =============== PhPStorm.gitignore 8 | .idea 9 | 10 | 11 | # =============== OSX.gitignore 12 | .DS_Store 13 | .AppleDouble 14 | .LSOverride 15 | 16 | npm-debug.log 17 | 18 | .publishrc 19 | 20 | # ==== build output 21 | dist 22 | web 23 | 24 | coverage 25 | 26 | # ==== .env 27 | .env 28 | 29 | # ==== stackdriver 30 | stackdriver 31 | 32 | # === logs 33 | logs 34 | 35 | # === vscode 36 | .vscode 37 | 38 | test.js -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "lib": [ 6 | "es6", 7 | "dom" 8 | ], 9 | "esModuleInterop": true, 10 | "allowJs": true, 11 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 12 | "outDir": "./dist", /* Redirect output structure to the directory. */ 13 | "strict": true, /* Enable all strict type-checking options. */ 14 | "noUnusedLocals": true, /* Report errors on unused locals. */ 15 | "noUnusedParameters": true, /* Report errors on unused parameters. */ 16 | "noImplicitReturns": false, /* Report error when not all code paths in function return a value. */ 17 | }, 18 | "include": ["src"], 19 | "exclude": ["node_modules", "**/__tests__/*"] 20 | } -------------------------------------------------------------------------------- /example/webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const webpack = require('webpack'); 5 | const MinifyPlugin = require('babel-minify-webpack-plugin'); 6 | 7 | module.exports = { 8 | mode: 'production', 9 | entry: './example/client/index.js', 10 | output: { 11 | path: path.resolve(__dirname), 12 | filename: 'app.js' 13 | }, 14 | devServer: { 15 | static: { 16 | directory: path.join(__dirname) 17 | } 18 | }, 19 | stats: { 20 | colors: true, 21 | modules: false 22 | }, 23 | plugins: [ 24 | new webpack.optimize.ModuleConcatenationPlugin(), 25 | new MinifyPlugin() 26 | ], 27 | module: { 28 | rules: [ 29 | { 30 | test: /\.js$/, 31 | exclude: '/node_modules/', 32 | use: { 33 | loader: 'babel-loader', 34 | options: { 35 | presets: [['@babel/preset-env']] 36 | } 37 | } 38 | }, 39 | ] 40 | }, 41 | performance: { 42 | maxAssetSize: 500000, 43 | maxEntrypointSize: 500000 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const MinifyPlugin = require('babel-minify-webpack-plugin'); 5 | const webpack = require('webpack'); 6 | 7 | module.exports = { 8 | // devtool: 'source-map', 9 | entry: './lib/index.js', 10 | mode: 'production', 11 | output: { 12 | path: path.resolve(__dirname, 'dist'), 13 | filename: 'index.js', 14 | libraryTarget: 'umd', 15 | library: 'phone', 16 | globalObject: 'this' 17 | }, 18 | plugins: [ 19 | new webpack.optimize.ModuleConcatenationPlugin(), 20 | new MinifyPlugin() 21 | ], 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.js$/, 26 | include: [ 27 | path.resolve(__dirname, 'lib') 28 | ], 29 | loader: 'babel-loader', 30 | options: { 31 | babelrc: false, 32 | presets: [ 33 | ['env', { 34 | targets: { 35 | browsers: '>1%', 36 | node: '6.10' 37 | }, 38 | modules: false, 39 | debug: true 40 | }] 41 | ] 42 | } 43 | } 44 | ] 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2020 AfterShip 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /__tests__/index.spec.ts: -------------------------------------------------------------------------------- 1 | import phone from '../src/index'; 2 | 3 | describe('Parameter types', () => { 4 | test('using default parameter if not provided', () => { 5 | const result = phone('+1 (817) 569-8900', {}); 6 | 7 | expect(result).toEqual({ 8 | isValid: true, 9 | phoneNumber: '+18175698900', 10 | countryIso2: 'US', 11 | countryIso3: 'USA', 12 | countryCode: '+1' 13 | }); 14 | }); 15 | 16 | test('2nd parameter is undefined', () => { 17 | const result = phone('+1 (817) 569-8900'); 18 | 19 | expect(result).toEqual({ 20 | isValid: true, 21 | phoneNumber: '+18175698900', 22 | countryIso2: 'US', 23 | countryIso3: 'USA', 24 | countryCode: '+1' 25 | }); 26 | }); 27 | 28 | test('phone is not a string', () => { 29 | const result = phone(18175698900 as unknown as string); 30 | 31 | expect(result).toEqual({ 32 | isValid: false, 33 | phoneNumber: null, 34 | countryIso2: null, 35 | countryIso3: null, 36 | countryCode: null 37 | }); 38 | }); 39 | 40 | test('country is not a string', () => { 41 | const result = phone('+18175698900', { 42 | country: 123 as unknown as string 43 | }); 44 | 45 | expect(result).toEqual({ 46 | isValid: true, 47 | phoneNumber: '+18175698900', 48 | countryIso2: 'US', 49 | countryIso3: 'USA', 50 | countryCode: '+1' 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | ## AfterShip Phone browser usage 2 | 3 | We use the new `Array.prototype.find` function to simplify the coding. To support for older browser. You need to include the `polyfill` yourself. Here is live example to use `phone` browser. In this example we use `webpack`, `babel-polyfill` and `babel-preset-env` to simplify and optimize the build for target browser env. of cause you can using other services or package like `https://polyfill.io/`, `core-js`, etc. 4 | 5 | You can running this example by 6 | 7 | 1. git clone git@github.com:AfterShip/phone.git 8 | 2. yarn install 9 | 3. yarn run start:example 10 | 4. navigate to `localhost:8080` 11 | 12 | ```javascript 13 | // client/index.js 14 | import 'babel-polyfill'; 15 | ``` 16 | 17 | ```javascript 18 | // webpack.config.js 19 | 'use strict'; 20 | 21 | const path = require('path'); 22 | 23 | module.exports = { 24 | entry: './example/client/index.js', 25 | output: { 26 | path: path.resolve(__dirname), 27 | filename: 'app.js' 28 | }, 29 | devServer: { 30 | contentBase: path.join(__dirname), 31 | stats: { 32 | colors: true, 33 | modules: false 34 | } 35 | }, 36 | module: { 37 | rules: [ 38 | { 39 | test: /\.js$/, 40 | loader: 'babel-loader', 41 | options: { 42 | babelrc: false, 43 | presets: [ 44 | ['env', { 45 | targets: { 46 | browsers: '>1%' 47 | }, 48 | useBuiltIns: true, // optimize build for the babel-polyfill 49 | debug: true, 50 | modules: false 51 | }] 52 | ] 53 | } 54 | } 55 | ] 56 | } 57 | }; 58 | 59 | ``` 60 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1_phone_number_format_issue.yml: -------------------------------------------------------------------------------- 1 | name: 1. Phone number format issue 2 | description: For any issues related to phone number format (such as not detecting a certain phone number). 3 | title: "[phone number format] " 4 | labels: ["phone-number-format"] 5 | assignees: 6 | - bossa573 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: "## Creating a PR directly is much appreciated, thank you very much." 11 | - type: input 12 | id: country_region 13 | attributes: 14 | label: Country/Region 15 | description: in ISO 3166 alpha-3 16 | placeholder: e.g. USA, GBR, FRA, etc 17 | validations: 18 | required: true 19 | - type: input 20 | id: sample_phone_number 21 | attributes: 22 | label: Sample input with real phone format 23 | description: A dummy phone number is fine, do not leave personal info. 24 | placeholder: e.g. +13805553750, separated with comma for multiple phone numbers 25 | validations: 26 | required: true 27 | - type: textarea 28 | id: reference 29 | attributes: 30 | label: Reference docs/website 31 | description: Reference docs/website showing that the phone number format should be valid, government websites, 3rd party websites, or even Wikipedia pages are fine. 32 | placeholder: 33 | validations: 34 | required: true 35 | - type: checkboxes 36 | id: mobile_phone_number 37 | attributes: 38 | label: Mobile phone number 39 | description: Make sure your reported phone number is a mobile phone number. Landline, VoIP, or any other phone number formats are not supported and will not be accepted. If this checkbox is unchecked, the ticket will be closed. 40 | options: 41 | - label: I confirmed that the provided sample is a mobile phone number. 42 | validations: 43 | required: true 44 | 45 | -------------------------------------------------------------------------------- /__tests__/test_match.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { parse } from 'papaparse'; 3 | import phone from '../src/index'; 4 | 5 | interface TestCaseItem { 6 | input_phone: string; 7 | input_country: string; 8 | not_validate_prefix: string; 9 | output_phone: string; 10 | output_country_alpha2: string; 11 | output_country_alpha3: string; 12 | output_country_code: string; 13 | output_is_valid: string; 14 | desc1: string; 15 | desc2: string; 16 | test_desc: string; 17 | strict_detection: string; 18 | } 19 | 20 | const testCases = (parse(fs.readFileSync(`${__dirname}/data.csv`).toString(), { 21 | header: true 22 | })).data as TestCaseItem[]; 23 | 24 | for (const testCase of testCases) { 25 | test(`${testCase.input_phone} / ${testCase.input_country} / ${testCase.not_validate_prefix}`, function() { 26 | const {input_phone: phoneNumber, input_country: country, not_validate_prefix: notValidatePrefix, strict_detection: strictDetectionString} = testCase; 27 | const validateMobilePrefix = !notValidatePrefix; 28 | 29 | let strictDetection = undefined; 30 | 31 | if (strictDetectionString === 'true') { 32 | strictDetection = true; 33 | } else if (strictDetectionString === 'false') { 34 | strictDetection = false; 35 | } 36 | 37 | const result = phone(phoneNumber, { 38 | country, 39 | validateMobilePrefix, 40 | strictDetection 41 | }); 42 | 43 | if (testCase.output_is_valid === 'true') { 44 | expect(result).toEqual({ 45 | isValid: true, 46 | phoneNumber: testCase.output_phone, 47 | countryIso2: testCase.output_country_alpha2, 48 | countryIso3: testCase.output_country_alpha3, 49 | countryCode: testCase.output_country_code 50 | }); 51 | } else { 52 | expect(result).toEqual({ 53 | isValid: false, 54 | phoneNumber: null, 55 | countryIso2: null, 56 | countryIso3: null, 57 | countryCode: null 58 | }); 59 | } 60 | }); 61 | } 62 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | AfterShip - phone 9 | 10 | 11 |
12 |

phone example

13 |
14 |
15 |
16 | 17 |
18 |
19 | 20 |
21 |
22 |
23 |
24 |

This username is available

25 |
26 |
27 |
28 |
29 |
30 | 34 |
35 |
36 |
37 |
38 | 42 |
43 |
44 |
45 |
46 |
47 |

Result

48 |
49 |       
50 |     
51 |
52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /example/client/index.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | import { phone } from '../../dist/'; 3 | 4 | const input = document.getElementById('phone'); 5 | const code = document.getElementById('code'); 6 | const help = document.querySelector('.help'); 7 | const country = document.getElementById('country'); 8 | const validateMobilePrefix = document.getElementById('validateMobilePrefix'); 9 | const strictDetection = document.getElementById('strictDetection'); 10 | 11 | const formatPhone = (e) => { 12 | const inputPhoneNumber = input.value; 13 | const options = { 14 | validateMobilePrefix: validateMobilePrefix.checked, 15 | strictDetection: strictDetection.checked, 16 | }; 17 | 18 | const countryValue = country.value.trim(); 19 | if (countryValue) { 20 | options.country = countryValue; 21 | } 22 | 23 | const { phoneNumber, countryIso2, countryIso3, countryCode, isValid } = phone(inputPhoneNumber, options); 24 | 25 | if (!isValid) { 26 | [ 27 | help, 28 | input, 29 | ].forEach(node => { 30 | node.classList.remove('is-success'); 31 | node.classList.add('is-danger'); 32 | }); 33 | code.classList.add('is-hidden'); 34 | code.textContent = ''; 35 | help.textContent = 'This phone number is invalid'; 36 | return; 37 | } 38 | [ 39 | help, 40 | input, 41 | ].forEach(node => { 42 | node.classList.add('is-success'); 43 | node.classList.remove('is-danger'); 44 | }); 45 | 46 | help.textContent = 'This phone number is valid'; 47 | code.classList.remove('is-hidden'); 48 | code.textContent = ` 49 | isValid: ${isValid} 50 | Formatted Phone number: ${phoneNumber} 51 | Country code alpha 2: ${countryIso2} 52 | Country code alpha 3: ${countryIso3} 53 | Country calling code: ${countryCode}`; 54 | }; 55 | 56 | input.addEventListener('input', formatPhone); 57 | country.addEventListener('input', formatPhone); 58 | validateMobilePrefix.addEventListener('click', formatPhone); 59 | strictDetection.addEventListener('click', formatPhone); 60 | 61 | 62 | input.dispatchEvent(new Event('input')); 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phone", 3 | "version": "3.1.68", 4 | "description": "With a given country and phone number, validate and format the phone number to E.164 standard", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "engines": { 8 | "node": ">=12" 9 | }, 10 | "directories": { 11 | "lib": "./src/lib" 12 | }, 13 | "scripts": { 14 | "test": "jest", 15 | "test:watch": "jest --watch", 16 | "test:update": "jest --updateSnapshot", 17 | "lint": "eslint .", 18 | "build": "rimraf ./dist && tsc", 19 | "start:example": "yarn build && webpack serve --config ./example/webpack.config.js --progress", 20 | "dev": "yarn start:example", 21 | "prepublishOnly": "yarn build", 22 | "fix:numbers": "ts-node -P scripts/add-new-rules/tsconfig.json scripts/add-new-rules" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/aftership/phone" 27 | }, 28 | "bugs": { 29 | "url": "https://github.com/aftership/phone/issues" 30 | }, 31 | "devDependencies": { 32 | "@babel/preset-env": "^7.26.9", 33 | "@types/jest": "^29.5.14", 34 | "@types/node": "^22.14.1", 35 | "@types/papaparse": "^5.3.15", 36 | "babel-cli": "^6.26.0", 37 | "babel-loader": "^10.0.0", 38 | "babel-minify-webpack-plugin": "^0.3.1", 39 | "babel-polyfill": "^6.26.0", 40 | "babel-preset-env": "^1.7.0", 41 | "dotenv": "^16.5.0", 42 | "eslint": "^9.24.0", 43 | "eslint-config-aftership": "^7.0.0", 44 | "eslint-plugin-import": "^2.31.0", 45 | "idempotent-babel-polyfill": "^7.4.4", 46 | "jest": "^29.7.0", 47 | "lodash": "^4.17.21", 48 | "papaparse": "^5.5.2", 49 | "rimraf": "^6.0.1", 50 | "ts-jest": "^29.3.2", 51 | "ts-node": "^10.9.2", 52 | "twilio": "^5.5.2", 53 | "typescript": "^5.8.3", 54 | "webpack": "^5.99.5", 55 | "webpack-cli": "^6.0.1", 56 | "webpack-dev-server": "^5.2.1" 57 | }, 58 | "keywords": [ 59 | "phone", 60 | "e.164" 61 | ], 62 | "author": "AfterShip", 63 | "license": "MIT", 64 | "dependencies": {} 65 | } 66 | -------------------------------------------------------------------------------- /scripts/add-new-rules/index.ts: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | 3 | const accountSid = process.env.TWILIO_SID; 4 | const authToken = process.env.TWILIO_TOKEN; 5 | 6 | ~function() { 7 | if (!accountSid || !authToken) { 8 | throw new Error('Please set environment TWILIO_SID & TWILIO_TOKEN first!'); 9 | } 10 | }(); 11 | 12 | import { IStackDriverError, ITwilioPhoneNumberInstance, Iiso3166 } from './interface'; 13 | import * as _find from 'lodash/find'; 14 | import * as fs from 'fs'; 15 | import * as path from 'path'; 16 | 17 | const errors: IStackDriverError[] = require('./stackdriver/errors.json'); 18 | const error_phone_array: string[] = require('./stackdriver/error_list.json'); 19 | const iso3166s: Iiso3166[] = require('../../lib/iso3166Data'); 20 | const client = require('twilio')(accountSid, authToken); 21 | 22 | ~async function() { 23 | const error_numbers = [...new Set( 24 | errors.map(({ jsonPayload: {data} }) => data) 25 | .concat(error_phone_array) 26 | .map(data => { 27 | const formatted_number = data.replace(/[\s|-]+/g, ''); 28 | return formatted_number; 29 | }), 30 | )]; 31 | const errorStream = fs.createWriteStream(path.resolve(__dirname, './logs/error.log')); 32 | const twilioPromises = error_numbers.map(num => { 33 | return client 34 | .lookups 35 | .phoneNumbers(num) 36 | .fetch() 37 | .catch(err => { 38 | errorStream.write(`${num}:\n ${JSON.stringify(err, null, 4)}\n`); 39 | }); 40 | }); 41 | 42 | const lookups = await Promise.all(twilioPromises).then(v => { 43 | errorStream.end(); 44 | return v; 45 | }); 46 | const filteredLookups: ITwilioPhoneNumberInstance[] = lookups.filter(v => v); 47 | const deduplatedLookups = [...new Set( 48 | filteredLookups.map(({ phoneNumber, countryCode }) => `${countryCode}:${phoneNumber}`), 49 | )].map(str => { 50 | const [countryCode, phoneNumber] = str.split(':'); 51 | return {countryCode, phoneNumber}; 52 | }); 53 | 54 | const sumByAlpha2 = deduplatedLookups.reduce((sum, { countryCode, phoneNumber }) => { 55 | const [matched_item] = iso3166s.filter(({ alpha2 }) => alpha2 === countryCode); 56 | const { 57 | alpha2, 58 | country_code, 59 | mobile_begin_with, 60 | phone_number_lengths, 61 | } = matched_item; 62 | const localPhoneNumber = phoneNumber.replace('+' + country_code, ''); 63 | const isBeginWithRight = mobile_begin_with.length === 0 || mobile_begin_with.some(num => new RegExp(`^${num}`).test(localPhoneNumber)); 64 | const new_mobile_begin_with = isBeginWithRight ? mobile_begin_with: mobile_begin_with.concat(localPhoneNumber.slice(0, mobile_begin_with[0].length)); 65 | const new_phone_number_lengths = [...new Set(phone_number_lengths.concat(localPhoneNumber.length))]; 66 | 67 | const sum_alpha2 = sum[alpha2]; 68 | return { 69 | ...sum, 70 | [alpha2]: { 71 | ...matched_item, 72 | mobile_begin_with: sum_alpha2 ? 73 | [...new Set([ 74 | ...new_mobile_begin_with, 75 | ...sum_alpha2.mobile_begin_with 76 | ])] : 77 | new_mobile_begin_with, 78 | phone_number_lengths: sum_alpha2 ? 79 | [...new Set([ 80 | ...new_phone_number_lengths, 81 | ...sum_alpha2.phone_number_lengths, 82 | ])] : 83 | new_phone_number_lengths 84 | } 85 | }; 86 | }, {}); 87 | 88 | const resultStream = fs.createWriteStream(path.resolve(__dirname, './logs/result.log')); 89 | resultStream.write(JSON.stringify(sumByAlpha2, null, 4)); 90 | resultStream.end(); 91 | }(); 92 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # v1.0.4 2015-05-06 2 | 3 | 4 | # ------------------------------------------------------------------------------ 5 | # Add your custom excludes below 6 | # ------------------------------------------------------------------------------ 7 | .nyc_output/ 8 | .npmrc 9 | .vscode/ 10 | .tern-project 11 | lib/ 12 | src/ 13 | script/ 14 | example/ 15 | .babelrc 16 | .eslintignore 17 | .flowconfig 18 | .gitignore 19 | .publishrc 20 | .stylelintrc 21 | example.config.json 22 | gulfile.babel.js 23 | jest.config.json 24 | litmus-support-clients.js 25 | flow-typed 26 | __tests__/ 27 | webpack.config.js 28 | .eslintrc 29 | 30 | 31 | # =============== log ignore builtAssets 32 | 33 | /tmp/* 34 | /builtAssets/* 35 | *.log 36 | .nyc_output/ 37 | coverage/ 38 | 39 | # =========================== DO NOT touch below v1.0.3 =============================== 40 | 41 | 42 | node_modules 43 | 44 | # =============== RubyMine.gitignore 45 | # =============== PhPStorm.gitignore 46 | .idea 47 | 48 | 49 | # =============== OSX.gitignore 50 | .DS_Store 51 | .AppleDouble 52 | .LSOverride 53 | 54 | # Thumbnails 55 | ._* 56 | 57 | # =============== # Windows image file caches 58 | Thumbs.db 59 | ehthumbs.db 60 | 61 | # Folder config file 62 | Desktop.ini 63 | 64 | # Recycle Bin used on file shares 65 | $RECYCLE.BIN/ 66 | 67 | # Except the .htpassed 68 | !.htpasswd 69 | !.nodemonignore 70 | 71 | npm-debug.log 72 | 73 | dump.rdb 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | # FROM https://github.com/niftylettuce/node-email-templates/blob/master/.gitignore 83 | 84 | # ------------------------------------------------------------------------------ 85 | # Common Node files and folders 86 | # https://github.com/github/gitignore/blob/master/Node.gitignore 87 | # ------------------------------------------------------------------------------ 88 | 89 | lib-cov 90 | *.seed 91 | *.log 92 | *.csv 93 | *.dat 94 | *.out 95 | *.pid 96 | *.gz 97 | 98 | pids 99 | log 100 | results 101 | 102 | node_modules 103 | npm-debug.log 104 | 105 | 106 | # ------------------------------------------------------------------------------ 107 | # Nodemon 108 | # ------------------------------------------------------------------------------ 109 | 110 | .monitor 111 | 112 | 113 | # ------------------------------------------------------------------------------ 114 | # JSHint 115 | # ------------------------------------------------------------------------------ 116 | 117 | jshint 118 | 119 | 120 | # ------------------------------------------------------------------------------ 121 | # Numerous always-ignore extensions 122 | # ------------------------------------------------------------------------------ 123 | 124 | *.diff 125 | *.err 126 | *.orig 127 | *.rej 128 | *.swo 129 | *.swp 130 | *.vi 131 | *~ 132 | *.sass-cache 133 | 134 | 135 | # ------------------------------------------------------------------------------ 136 | # Files from other repository control systems 137 | # ------------------------------------------------------------------------------ 138 | 139 | .hg 140 | .svn 141 | .CVS 142 | 143 | 144 | # ------------------------------------------------------------------------------ 145 | # PHPStorm, RubyMine 146 | # ------------------------------------------------------------------------------ 147 | 148 | .idea 149 | 150 | 151 | # ------------------------------------------------------------------------------ 152 | # OS X and other IDE's folder attributes 153 | # ------------------------------------------------------------------------------ 154 | 155 | .DS_Store 156 | Thumbs.db 157 | .cache 158 | .project 159 | .settings 160 | .tmproj 161 | *.esproj 162 | nbproject 163 | *.sublime-project 164 | *.sublime-workspace 165 | 166 | 167 | # ------------------------------------------------------------------------------ 168 | # Dreamweaver added files 169 | # ------------------------------------------------------------------------------ 170 | 171 | _notes 172 | dwsync.xml 173 | 174 | 175 | # ------------------------------------------------------------------------------ 176 | # Komodo 177 | # ------------------------------------------------------------------------------ 178 | 179 | *.komodoproject 180 | .komodotools 181 | bower_components 182 | 183 | config/examples.json 184 | config.json 185 | 186 | # ------------------------------------------------------------------------------ 187 | # customized scripts 188 | # ------------------------------------------------------------------------------ 189 | scripts 190 | 191 | test.js 192 | test_generate.js 193 | .github 194 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import countryPhoneData from './data/country_phone_data'; 2 | import { 3 | findCountryPhoneDataByCountry, 4 | findCountryPhoneDataByPhoneNumber, 5 | validatePhoneISO3166, 6 | CountryPhoneDataItem, 7 | } from './lib/utility'; 8 | 9 | export interface PhoneInvalidResult { 10 | isValid: false; 11 | phoneNumber: null; 12 | countryIso2: null; 13 | countryIso3: null; 14 | countryCode: null; 15 | } 16 | 17 | export interface PhoneValidResult { 18 | isValid: true; 19 | phoneNumber: string; 20 | countryIso2: string; 21 | countryIso3: string; 22 | countryCode: string; 23 | } 24 | 25 | export type PhoneResult = PhoneInvalidResult | PhoneValidResult; 26 | 27 | /** 28 | * @typedef {Object} Option 29 | * @property {string=} country - country code in ISO3166 alpha 2 or 3 30 | * @property {boolean=} validateMobilePrefix - true to validate phone number prefix 31 | * @property {boolean=} strictDetection - true to disable remove truck code and detection logic 32 | * 33 | * @param {string} phoneNumber - phone number 34 | * @param {Option} option 35 | * @returns {{phoneNumber: string|null, countryIso2: string|null, countryIso3: string|null}} 36 | */ 37 | export default function phone(phoneNumber: string, { 38 | country = '', 39 | validateMobilePrefix = true, 40 | strictDetection = false 41 | }: { 42 | country?: string; 43 | validateMobilePrefix?: boolean; 44 | strictDetection?: boolean; 45 | } = {}): PhoneResult { 46 | const invalidResult = { 47 | isValid: false as const, 48 | phoneNumber: null, 49 | countryIso2: null, 50 | countryIso3: null, 51 | countryCode: null 52 | }; 53 | 54 | let processedPhoneNumber = (typeof phoneNumber !== 'string') ? '' : phoneNumber.trim(); 55 | const processedCountry = (typeof country !== 'string') ? '' : country.trim(); 56 | const hasPlusSign = Boolean(processedPhoneNumber.match(/^\+/)); 57 | 58 | // remove any non-digit character, included the + 59 | processedPhoneNumber = processedPhoneNumber.replace(/\D/g, ''); 60 | 61 | let foundCountryPhoneData = findCountryPhoneDataByCountry(processedCountry); 62 | 63 | if (!foundCountryPhoneData) { 64 | return invalidResult; 65 | } 66 | 67 | let defaultCountry = false; 68 | 69 | // if country provided, only reformat the phone number 70 | if (processedCountry) { 71 | // remove leading 0s for all countries except 'CIV', 'COG' 72 | if (!['CIV', 'COG'].includes(foundCountryPhoneData.alpha3)) { 73 | processedPhoneNumber = processedPhoneNumber.replace(/^0+/, ''); 74 | } 75 | 76 | // if input 89234567890, RUS, remove the 8 77 | if (foundCountryPhoneData.alpha3 === 'RUS' && processedPhoneNumber.length === 11 && processedPhoneNumber.match(/^89/) !== null) { 78 | processedPhoneNumber = processedPhoneNumber.replace(/^8+/, ''); 79 | } 80 | 81 | // if there's no plus sign and the phone number length is one of the valid length under country phone data 82 | // then assume there's no country code, hence add back the country code 83 | if (!hasPlusSign && foundCountryPhoneData.phone_number_lengths.includes(processedPhoneNumber.length)) { 84 | processedPhoneNumber = `${foundCountryPhoneData.country_code}${processedPhoneNumber}`; 85 | } 86 | } else if (hasPlusSign) { 87 | // if there is a plus sign but no country provided 88 | // try to find the country phone data by the phone number 89 | const { exactCountryPhoneData, possibleCountryPhoneData } = findCountryPhoneDataByPhoneNumber(processedPhoneNumber, validateMobilePrefix); 90 | 91 | if (exactCountryPhoneData) { 92 | foundCountryPhoneData = exactCountryPhoneData; 93 | } else if (possibleCountryPhoneData && !strictDetection) { 94 | // for some countries, the phone number usually includes one trunk prefix for local use 95 | // The UK mobile phone number ‘07911 123456’ in international format is ‘+44 7911 123456’, so without the first zero. 96 | // 8 (AAA) BBB-BB-BB, 0AA-BBBBBBB 97 | // the numbers should be omitted in international calls 98 | 99 | foundCountryPhoneData = possibleCountryPhoneData; 100 | processedPhoneNumber = foundCountryPhoneData.country_code + processedPhoneNumber.replace(new RegExp(`^${foundCountryPhoneData.country_code}\\d`), ''); 101 | } else { 102 | foundCountryPhoneData = null; 103 | } 104 | } else if (foundCountryPhoneData.phone_number_lengths.indexOf(processedPhoneNumber.length) !== -1) { 105 | // B: no country, no plus sign --> treat it as USA 106 | // 1. check length if == 11, or 10, if 10, add +1, then go go D 107 | // no plus sign, no country is given. then it must be USA 108 | // iso3166 = iso3166_data[0]; already assign by the default value 109 | processedPhoneNumber = `1${processedPhoneNumber}`; 110 | defaultCountry = true; 111 | } 112 | 113 | if (!foundCountryPhoneData) { 114 | return invalidResult; 115 | } 116 | 117 | let validateResult = validatePhoneISO3166(processedPhoneNumber, foundCountryPhoneData, validateMobilePrefix, hasPlusSign); 118 | 119 | if (validateResult) { 120 | return { 121 | isValid: true as const, 122 | phoneNumber: `+${processedPhoneNumber}`, 123 | countryIso2: foundCountryPhoneData.alpha2, 124 | countryIso3: foundCountryPhoneData.alpha3, 125 | countryCode: `+${foundCountryPhoneData.country_code}` 126 | }; 127 | } 128 | 129 | if (defaultCountry) { 130 | // also try to validate against CAN for default country, as CAN is also start with +1 131 | foundCountryPhoneData = findCountryPhoneDataByCountry('CAN') as CountryPhoneDataItem; 132 | validateResult = validatePhoneISO3166(processedPhoneNumber, foundCountryPhoneData, validateMobilePrefix, hasPlusSign); 133 | if (validateResult) { 134 | return { 135 | isValid: true as const, 136 | phoneNumber: `+${processedPhoneNumber}`, 137 | countryIso2: foundCountryPhoneData.alpha2, 138 | countryIso3: foundCountryPhoneData.alpha3, 139 | countryCode: `+${foundCountryPhoneData.country_code}` 140 | }; 141 | } 142 | } 143 | 144 | return invalidResult; 145 | }; 146 | 147 | export { 148 | phone, 149 | countryPhoneData, 150 | }; 151 | -------------------------------------------------------------------------------- /src/lib/utility.ts: -------------------------------------------------------------------------------- 1 | import countryPhoneData from '../data/country_phone_data'; 2 | 3 | type GetArrayElementType = T extends readonly (infer U)[] ? U : never; 4 | export type CountryPhoneDataItem = GetArrayElementType; 5 | 6 | /** 7 | * @param {string=} country - country code alpha 2 or 3 8 | * @returns {{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with, phone_number_lengths: [number]}|{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with: [string, string, string, string], phone_number_lengths: [number]}|{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with: [string], phone_number_lengths: [number]}|{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with: [string], phone_number_lengths: [number]}|{country_code: string, alpha2: string, country_name: string, alpha3: string, mobile_begin_with: [string, string], phone_number_lengths: [number]}|null} 9 | */ 10 | export function findCountryPhoneDataByCountry(country: string) { 11 | // if no country provided, assume it's USA 12 | if (!country) { 13 | return countryPhoneData.find(countryPhoneDatum => countryPhoneDatum.alpha3 === 'USA') || null; 14 | } 15 | 16 | if (country.length === 2) { 17 | return countryPhoneData.find(countryPhoneDatum => country.toUpperCase() === countryPhoneDatum.alpha2) || null; 18 | } 19 | 20 | if (country.length === 3) { 21 | return countryPhoneData.find(countryPhoneDatum => country.toUpperCase() === countryPhoneDatum.alpha3) || null; 22 | } 23 | 24 | return countryPhoneData.find(countryPhoneDatum => country.toUpperCase() === countryPhoneDatum.country_name.toUpperCase()) || null; 25 | } 26 | 27 | export function findExactCountryPhoneData(phoneNumber: string, validateMobilePrefix: boolean, countryPhoneDatum: CountryPhoneDataItem) { 28 | // check if the phone number length match any one of the length config 29 | const phoneNumberLengthMatched = countryPhoneDatum.phone_number_lengths.some(length => { 30 | // as the phone number must include the country code, 31 | // but countryPhoneDatum.phone_number_lengths is the length without country code 32 | // therefore need to add back countryPhoneDatum.country_code.length to length 33 | return (countryPhoneDatum.country_code.length + length === phoneNumber.length); 34 | }); 35 | 36 | if (!phoneNumberLengthMatched) { 37 | return null; 38 | } 39 | 40 | // if no need to validate mobile prefix or the country data does not have mobile begin with 41 | // pick the current one as the answer directly 42 | if (!countryPhoneDatum.mobile_begin_with.length || !validateMobilePrefix) { 43 | return countryPhoneDatum; 44 | } 45 | 46 | // if the mobile begin with is correct, pick as the correct answer 47 | if (countryPhoneDatum.mobile_begin_with.some(beginWith => { 48 | return phoneNumber.match(new RegExp('^' + countryPhoneDatum.country_code + beginWith)); 49 | })) { 50 | return countryPhoneDatum; 51 | } 52 | 53 | return null; 54 | } 55 | 56 | export function findPossibleCountryPhoneData(phoneNumber: string, validateMobilePrefix: boolean, countryPhoneDatum: CountryPhoneDataItem) { 57 | // check if the phone number length match any one of the length config 58 | const phoneNumberLengthMatched = countryPhoneDatum.phone_number_lengths.some(length => { 59 | // the phone number must include the country code 60 | // countryPhoneDatum.phone_number_lengths is the length without country code 61 | // + 1 is assuming there is an unwanted trunk code prepended to the phone number 62 | return (countryPhoneDatum.country_code.length + length + 1 === phoneNumber.length); 63 | }); 64 | 65 | if (!phoneNumberLengthMatched) { 66 | return null; 67 | } 68 | 69 | // if no need to validate mobile prefix or the country data does not have mobile begin with 70 | // pick the current one as the answer directly 71 | if (!countryPhoneDatum.mobile_begin_with.length || !validateMobilePrefix) { 72 | return countryPhoneDatum; 73 | } 74 | 75 | // if the mobile begin with is correct, pick as the correct answer 76 | // match another \d for the unwanted trunk code prepended to the phone number 77 | if (countryPhoneDatum.mobile_begin_with.some(beginWith => { 78 | return phoneNumber.match(new RegExp('^' + countryPhoneDatum.country_code + '\\d?' + beginWith)); 79 | })) { 80 | return countryPhoneDatum; 81 | } 82 | } 83 | 84 | /** 85 | * get country phone data by phone number 86 | * the phone number must include country code as the complete phone number includes the plus sign 87 | * @param phoneNumber 88 | * @param validateMobilePrefix 89 | * @returns {{exactCountryPhoneData: (*), possibleCountryPhoneData: (*)}} 90 | */ 91 | export function findCountryPhoneDataByPhoneNumber(phoneNumber: string, validateMobilePrefix: boolean) { 92 | let exactCountryPhoneData; 93 | let possibleCountryPhoneData; 94 | 95 | for (const countryPhoneDatum of countryPhoneData) { 96 | // if the country code is wrong, skip directly 97 | if (!phoneNumber.match(new RegExp('^' + countryPhoneDatum.country_code))) { 98 | continue; 99 | } 100 | 101 | // process only if exact match not found yet 102 | if (!exactCountryPhoneData) { 103 | exactCountryPhoneData = findExactCountryPhoneData(phoneNumber, validateMobilePrefix, countryPhoneDatum); 104 | } 105 | 106 | if (!possibleCountryPhoneData) { 107 | possibleCountryPhoneData = findPossibleCountryPhoneData(phoneNumber, validateMobilePrefix, countryPhoneDatum); 108 | } 109 | } 110 | 111 | return { 112 | exactCountryPhoneData, 113 | possibleCountryPhoneData 114 | } 115 | } 116 | 117 | 118 | /** 119 | * 120 | * @param {string} phone - phone number without plus sign, with or without country calling code 121 | * @param {Object} countryPhoneDatum - iso 3166 data 122 | * @param {String} countryPhoneDatum.country_code - country calling codes 123 | * @param {Array} countryPhoneDatum.phone_number_lengths - all available phone number lengths for this country 124 | * @param {Array} countryPhoneDatum.mobile_begin_with - mobile begin with number 125 | * @param {boolean} validateMobilePrefix - true if we skip mobile begin with checking 126 | * @param {boolean} plusSign - true if the input contains a plus sign 127 | * @returns {*|boolean} 128 | */ 129 | export function validatePhoneISO3166(phone: string, countryPhoneDatum: CountryPhoneDataItem, validateMobilePrefix: boolean, plusSign: boolean) { 130 | if (!countryPhoneDatum.phone_number_lengths) { 131 | return false; 132 | } 133 | 134 | // remove country calling code from the phone number 135 | const phoneWithoutCountry = phone.replace(new RegExp('^' + countryPhoneDatum.country_code), ''); 136 | 137 | // if the phone number have +, countryPhoneDatum detected, 138 | // but the phone number does not have country calling code 139 | // then should consider the phone number as invalid 140 | if (plusSign && countryPhoneDatum && phoneWithoutCountry.length === phone.length) { 141 | return false; 142 | } 143 | 144 | const phone_number_lengths = countryPhoneDatum.phone_number_lengths; 145 | const mobile_begin_with = countryPhoneDatum.mobile_begin_with; 146 | 147 | const isLengthValid = phone_number_lengths.some(length => phoneWithoutCountry.length === length); 148 | // some country doesn't have mobile_begin_with 149 | const isBeginWithValid = mobile_begin_with.length ? 150 | mobile_begin_with.some(beginWith => phoneWithoutCountry.match(new RegExp('^' + beginWith))): 151 | true; 152 | 153 | return isLengthValid && (!validateMobilePrefix || isBeginWithValid); 154 | } 155 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phone · [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FAfterShip%2Fphone.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2FAfterShip%2Fphone?ref=badge_shield) 2 | 3 | ## What is phone? 4 | `phone` is used to normalize mobile phone numbers into E.164 format. 5 | 6 | A common problem is that users normally input phone numbers in this way: 7 | 8 | ``` 9 | `(817) 569-8900` or 10 | `817569-8900` or 11 | `1(817) 569-8900` or 12 | `+1(817) 569-8900` or ... 13 | ``` 14 | 15 | We always want: 16 | 17 | ``` 18 | +18175698900 19 | ``` 20 | 21 | ## Install 22 | ``` 23 | npm install phone 24 | 25 | // or 26 | 27 | yarn add phone 28 | ``` 29 | 30 | ## Usage 31 | 32 | ```javascript 33 | const {phone} = require('phone'); 34 | 35 | // or 36 | 37 | import {phone} from 'phone'; 38 | ``` 39 | 40 | ### 1. Simple usage 41 | 42 | ```javascript 43 | phone('+852 6569-8900'); 44 | // { isValid: true, phoneNumber: '+85265698900', countryIso2: 'HK', countryIso3: 'HKG', countryCode: '+852' } 45 | ``` 46 | 47 | ### 2. With Country 48 | 49 | ```javascript 50 | phone('+1(817) 569-8900', {country: ''}); 51 | // { isValid: true, phoneNumber: '+18175698900', countryIso2: 'US', countryIso3: 'USA', countryCode: '+1'} 52 | 53 | phone('(817) 569-8900', {country: 'USA'}); 54 | // { isValid: true, phoneNumber: '+18175698900', countryIso2: 'US', countryIso3: 'USA', countryCode: '+1'} 55 | 56 | phone('(817) 569-8900', {country: 'HKG'}); 57 | // { isValid: false } 58 | // not a valid HKG mobile phone number 59 | 60 | phone('+1(817) 569-8900', {country: 'HKG'}); 61 | // { isValid: false } 62 | // not a valid HKG mobile phone number 63 | 64 | phone('6123-6123', {country: 'HKG'}); 65 | // { isValid: true, phoneNumber: '+85261236123', countryIso2: 'HK', countryIso3: 'HKG', countryCode: '+852' } 66 | ``` 67 | 68 | ### 3. Without country code and no phone prefix 69 | 70 | If both country code and country phone prefix are not provided, the phone number will be treated as USA or Canada by default. 71 | 72 | ```javascript 73 | phone('(817) 569-8900'); 74 | // { isValid: true, phoneNumber: '+18175698900', countryIso2: 'US', countryIso3: 'USA', countryCode: '+1' } 75 | 76 | phone('(817) 569-8900', {country: ''}); 77 | // { isValid: true, phoneNumber: '+18175698900', countryIso2: 'US', countryIso3: 'USA', countryCode: '+1' } 78 | 79 | phone('780-569-8900', {country: null}); 80 | // { isValid: true, phoneNumber: '+17805698900', countryIso2: 'CA', countryIso3: 'CAN', countryCode: '+1' } 81 | // 780 is a Canada phone prefix 82 | 83 | phone('6123-6123', {country: null}); 84 | // { isValid: false } 85 | // as default country is USA / CAN and the phone number does not fit such countries' rules 86 | ``` 87 | 88 | ### 4. With country code / phone prefix, but no `+` sign 89 | 90 | Even you input a valid phone number with a valid prefix, if there is no plus sign, it will not work as expected: 91 | 92 | ```javascript 93 | phone('85291234567'); 94 | // or 95 | phone('85291234567', {country: null}); 96 | 97 | // { isValid: false } 98 | ``` 99 | 100 | `852` is a valid Hong Kong phone prefix, and `91234567` is a valid Hong Kong mobile phone number. 101 | However, there is no plus sign provided, the module will assume the phone number is a USA or Canada phone number, 102 | hence no result will be found. 103 | 104 | If you know you have provided country phone prefix, make sure you also provide a plus sign: 105 | 106 | ```javascript 107 | phone('+85291234567'); 108 | // or 109 | phone('+85291234567', {country: null}); 110 | 111 | // { isValid: true, phoneNumber: '+85291234567', countryIso2: 'HK', countryIso3: 'HKG', countryCode: '+852' } 112 | ``` 113 | 114 | or, if you know the country, and only want to reformat the phone number to E.164 format: 115 | 116 | ```javascript 117 | phone('91234567', {country: 'HKG'}) 118 | // { isValid: true, phoneNumber: '+85291234567', countryIso2: 'HK', countryIso3: 'HKG', countryCode: '+852' } 119 | ``` 120 | 121 | ### 5. Skipping phone number initial digit checking 122 | 123 | If you want to skip phone number initial digit checking, set `validateMobilePrefix` to false: 124 | 125 | ```javascript 126 | phone('+(852) 2356-4902'); 127 | // { isValid: false } 128 | // '2' is a Hong Kong landline phone number prefix, not a valid mobile phone number prefix 129 | 130 | phone('+(852) 2356-4902', {validateMobilePrefix: true}); 131 | // { isValid: false } 132 | // same as above, default value of validateMobilePrefix = true 133 | 134 | phone('+(852) 2356-4902', {validateMobilePrefix: false}); 135 | // { isValid: true, phoneNumber: '+85223564902', countryIso2: 'HK', countryIso3: 'HKG', countryCode: '+852' } 136 | // skipping mobile prefix checking 137 | ``` 138 | 139 | With `validateMobilePrefix` set to `false`, the initial digit checking logic will be disabled completely, even you enter a phone number start with a non-exist digit: 140 | 141 | ```javascript 142 | phone('+(852) 0356-4902', {validateMobilePrefix: false}); 143 | // { isValid: true, phoneNumber: '+85203564902', countryIso2: 'HK', countryIso3: 'HKG', countryCode: '+852' } 144 | // even the phone number start with `0` is not a valid landline phone number 145 | ``` 146 | Note that the module does not have the capability to determine if the prefix is a valid `landline` prefix number. 147 | 148 | ### 6. Trunk Code Detection Logic 149 | 150 | For some phone numbers, such as this sample UK phone number: 151 | 152 | ``` 153 | +44 07911 123456 154 | ``` 155 | 156 | There is a trunk code `0` after the country code `+44` so that it is unable to match any correct country. 157 | 158 | Hence the module will try to remove 1 digit after the country code, 159 | 160 | and try to detect: 161 | 162 | ``` 163 | +44 7911 123456 164 | ``` 165 | 166 | and it would become a valid UK phone number now. 167 | 168 | ```javascript 169 | phone('+4407911 123456') 170 | // { isValid: true, phoneNumber: '+447911123456', countryIso2: 'GB', countryIso3: 'GBR', countryCode: '+44' } 171 | ``` 172 | 173 | If you want to disable this behavior, 174 | please set `strictDetection` to `true`: 175 | 176 | ```javascript 177 | phone('+4407911 123456', {strictDetection: true}) 178 | // { isValid: false } 179 | ``` 180 | 181 | ## API 182 | 183 | ```typescript 184 | const {phone} = require('phone'); 185 | 186 | // or 187 | 188 | import {phone} from 'phone'; 189 | 190 | phone(phoneNumber: string, { country, validateMobilePrefix, strictDetection }?: { 191 | country?: string; 192 | validateMobilePrefix?: boolean; 193 | strictDetection?: boolean; 194 | }) 195 | ``` 196 | 197 | #### Input 198 | 199 | Parameter | Type | Required | Default | Description 200 | --- | --- | --- | --- | --- 201 | phoneNumber | String | Yes | - | The phone number text you want to process 202 | country | String | No | null | Provided country code in iso-3166 alpha 2 or 3 format 203 | validateMobilePrefix | Boolean | No | true | Set to false if you want to skip phone number initial digit checking 204 | strictDetection | Boolean | No | false | Set to true if you want to disable trunk code detection logic. 205 | 206 | #### Returns 207 | 208 | ```typescript 209 | type PhoneResult = PhoneInvalidResult | PhoneValidResult; 210 | 211 | interface PhoneValidResult { 212 | isValid: true; 213 | phoneNumber: string; 214 | countryIso2: string; 215 | countryIso3: string; 216 | countryCode: string; 217 | } 218 | 219 | interface PhoneInvalidResult { 220 | isValid: false; 221 | phoneNumber: null; 222 | countryIso2: null; 223 | countryIso3: null; 224 | countryCode: null; 225 | } 226 | ``` 227 | 228 | Parameter | Type | Description 229 | --- | --- | --- 230 | isValid | Boolean | To indicate if the result valid 231 | phoneNumber | String or null | Normalized phone number in E.164 format 232 | countryIso2 | String or null | Detected phone number country code in iso-3166 alpha 2 format 233 | countryIso3 | String or null | Detected phone number country code in iso-3166 alpha 3 format 234 | countryCode | String or null | Detected phone number country calling code with `+` sign 235 | 236 | [comment]: <> (## Demo) 237 | 238 | [comment]: <> ([Try it on CodeSandbox](https://codesandbox.io/s/phone-browser-example-react-o5vt5?file=/src/App.js)) 239 | 240 | ## Test 241 | 242 | ``` 243 | yarn test 244 | ``` 245 | 246 | ## Interactive Web Example 247 | 248 | ``` 249 | yarn start:example 250 | ``` 251 | 252 | or 253 | 254 | ``` 255 | yarn dev 256 | ``` 257 | 258 | And then visit http://localhost:8080 259 | 260 | ## Build 261 | 262 | ``` 263 | yarn build 264 | ``` 265 | 266 | [comment]: <> (## Supported Environment) 267 | 268 | [comment]: <> (We currently transpile script to work on target environments for which the browser's global usage is >1%, and Node.js 6.10+.) 269 | 270 | [comment]: <> (You can check browser usage statistics on the [browserlist](http://browserl.ist/?q=%3E1%25).) 271 | 272 | [comment]: <> (You may need polyfills for some older browsers; for more details, please read the `example/README` file.) 273 | 274 | 275 | ## FAQ 276 | 277 | 1. Does `phone` do any logical validation? 278 | 279 | Yes. If you provide `country`, and the phone number does not start with a `+` sign, the module will validate both `phone_number_lengths` and `mobile_begin_with` 280 | 281 | 2. Why is `phone` returning an invalid result for a valid phone number? 282 | 283 | By default, the function validates **mobile phone numbers only**. It checks the phone number prefix and length to determine validity. If you want to skip the mobile prefix validation (for example, when checking landline numbers), you can set `validateMobilePrefix` to `false`. 284 | 285 | > **Note:** Disabling this check does **not** enable "landline mode". The library does **not** support landline number validation, as it only contains validation rules for mobile numbers. If a landline number has a different length or format than a mobile number, the library may not process it correctly. 286 | 287 | If you believe the result is incorrect, please submit a ticket to improve our validation rules. 288 | 289 | 3. Why is `phone` returning an object with `isValid = false` instead of returning a null directly? 290 | 291 | Returning an object (with `isValid = false`) allows us to extend the response format in the future, making it more flexible for adding additional information about invalid results. 292 | 293 | ## Migrate from v2 294 | 295 | The interface of v3 has been changed for better usability, maintainability, and flexibility, this shows all the changes from v2: 296 | 297 | #### Function Interface 298 | 299 | Version | Interface 300 | --- | --- 301 | v2 | phone(phoneNumber, country, allowLandline) 302 | v3 | phone(phoneNumber,{country: String, validateMobilePrefix: Boolean, strictDetection: Boolean}) 303 | 304 | #### Function Response 305 | 306 | Version | Result | Interface 307 | --- | --- | --- 308 | v2 | - | [phoneNumber, country] 309 | v3 | Valid | {isValid: true, phoneNumber: string, countryIso2: string, countryIso3: string, countryCode: string} 310 | v3 | Invalid | {isValid: false, phoneNumber: null, countryIso2: null, countryIso3: null, countryCode: null} 311 | 312 | #### allowLandline vs validateMobilePrefix 313 | 314 | `allowLandline` in v2 is essentially equal to `validateMobilePrefix` in v3, however, the value is the opposite. 315 | 316 | Because `allowLandline = true` in v2 means "Skip the mobile phone number prefix validation", and there is NO capability to verify if the input phone number is a valid landline phone number. 317 | 318 | To avoid misleading information, the parameter name has been changed to `validateMobilePrefix`, and the input value is the opposite, while `validateMobilePrefix = false` means "Skip the mobile phone number prefix validation". 319 | 320 | 321 | ## Phone Number Format Improvement 322 | 323 | We strive to ensure this package functions well across diverse scenarios. However, please note that the phone number formats may not be updated proactively or regularly, as this is a manual task and we lack a dedicated incentive for continuous updates. If you find any incorrect rules for a country or other specific case, please create a pull request to inform us. 324 | 325 | When submitting pull requests to add or modify phone number formats, it is essential to include reference information such as PDFs, websites, etc. **PRs submitted without references will not be accepted.** Thank you for your understanding and cooperation. 326 | 327 | **The library supports mobile phone number format only.** We are unable to provide landline phone number support as we do not have landline phone number format data, hence we do not accept PRs for landline phone numbers. 328 | 329 | ## License 330 | 331 | This project is licensed under the [MIT license](https://github.com/AfterShip/phone/blob/master/LICENSE). 332 | 333 | 334 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FAfterShip%2Fphone.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FAfterShip%2Fphone?ref=badge_large) 335 | -------------------------------------------------------------------------------- /__tests__/data.csv: -------------------------------------------------------------------------------- 1 | input_phone,input_country,not_validate_prefix,output_phone,output_country_alpha2,output_country_alpha3,output_country_code,output_is_valid,desc1,desc2,test_desc,strict_detection 2 | (852) 569-8900,,,,,,,false,Testing input parameter Phone,Test 1,"returns ", 3 | +1 (817) 569-8900,,,+18175698900,US,USA,+1,true,,Test 2,"returns +18175698900,USA", 4 | +852 6569-8900,,,+85265698900,HK,HKG,+852,true,,Test 3,"returns +85265698900,HKG", 5 | +852 6569-8900,HKG,,+85265698900,HK,HKG,+852,true,,Test 4,"returns +85265698900,HKG", 6 | ,HKG,,,,,,false,,Test 5,"returns ", 7 | +225 0534567888,CIV,,+2250534567888,CI,CIV,+225,true,,Test 6,should remove the leadings zero when country is CIV, 8 | +242 012345678,COG,,+242012345678,CG,COG,+242,true,,,should remove the leadings zero when country is COG, 9 | (852) 569-8900,,,,,,,false,Testing USA Phone,Test 1,"returns ", 10 | +1 (817) 569-8900,,,+18175698900,US,USA,+1,true,,Test 2,"returns +18175698900,USA", 11 | +1 (817) 569-8900,,,+18175698900,US,USA,+1,true,,Test 3,"returns +18175698900,USA", 12 | 2121234567,,,+12121234567,US,USA,+1,true,,Test 4,"returns +12121234567,USA", 13 | 22-6569-8900,,,+12265698900,CA,CAN,+1,true,,"Test 5, does not provide country, should match canada phone number","returns +12265698900,CAN", 14 | 22-5569-8900,,,+12255698900,US,USA,+1,true,,Test 6,"returns +12255698900,USA", 15 | +1 (817) 569-8900,United States,,+18175698900,US,USA,+1,true,,Test 7,"returns +18175698900,USA", 16 | +1 (817) 569-8900,"United States ",,+18175698900,US,USA,+1,true,,Test 8,"returns +18175698900,USA", 17 | +1 (817) 569-8900,USA,,+18175698900,US,USA,+1,true,,Test 9,"returns +18175698900,USA", 18 | +1 (817) 569-8900,"USA ",,+18175698900,US,USA,+1,true,,Test 10,"returns +18175698900,USA", 19 | +1 (817) 569-8900,US,,+18175698900,US,USA,+1,true,,Test 11,"returns +18175698900,USA", 20 | +1 (817) 569-8900," US",,+18175698900,US,USA,+1,true,,Test 12,"returns +18175698900,USA", 21 | +1 (817) 569-8900,HKG,,,,,,false,,Test 13,"returns ", 22 | +1 (888) 569-8900,,,+18885698900,US,USA,+1,true,,Test 14,"returns +18885698900,USA", 23 | +1905-555-1234,,,+19055551234,CA,CAN,+1,true,Testing default Canada phone number,"Test 1, does not provide country, should match canada phone number","returns +19055551234,CAN", 24 | 519-555-1234,,,+15195551234,CA,CAN,+1,true,,"Test 2, does not provide country and plus sign, should match canada phone number","returns +15195551234,CAN", 25 | 1519-555-1234,,,,,,,false,,"Test 3, does not provide country and plus sign but with ""1"", should match nothing","returns ", 26 | +1 340 1234 567,VIR,,+13401234567,VI,VIR,+1,true,Testing +1 but NOT in USA,+1 340 United States Virgin Islands,"returns +13401234567,VIR", 27 | +1 670 1234 567,MNP,,+16701234567,MP,MNP,+1,true,,+1 670 Northern Mariana Islands,"returns +16701234567,MNP", 28 | +1 671 1234 567,GUM,,+16711234567,GU,GUM,+1,true,,+1 671 Guam,"returns +16711234567,GUM", 29 | +1 684 1234 567,ASM,,,,,,false,,+1 684 American Samoa,"returns ", 30 | +1 684 2584 567,ASM,,+16842584567,AS,ASM,+1,true,,+1 684 American Samoa,"returns +16842584567,ASM", 31 | +1 684 7334 567,ASM,,+16847334567,AS,ASM,+1,true,,+1 684 American Samoa,"returns +16847334567,ASM", 32 | +1 787 1234 567,PRI,,+17871234567,PR,PRI,+1,true,,+1 787 / 939 Puerto Rico,"returns +17871234567,PRI", 33 | +1 939 1234 567,PRI,,+19391234567,PR,PRI,+1,true,,+1 787 / 939 Puerto Rico,"returns +19391234567,PRI", 34 | +1 242 1234 567,BHS,,+12421234567,BS,BHS,+1,true,,+1 242 Bahamas,"returns +12421234567,BHS", 35 | +1 246 1234 567,BRB,,+12461234567,BB,BRB,+1,true,,+1 246 Barbados,"returns +12461234567,BRB", 36 | +1 264 1234 567,AIA,,,,,,false,,+1 264 Anguilla,"returns ", 37 | +1 264 5234 567,AIA,,+12645234567,AI,AIA,+1,true,,+1 264 Anguilla,"returns +12645234567,AIA", 38 | +1 264 7234 567,AIA,,+12647234567,AI,AIA,+1,true,,+1 264 Anguilla,"returns +12647234567,AIA", 39 | +1 268 1234 567,ATG,,,,,,false,,+1 268 Antigua and Barbuda,"returns ", 40 | +1 268 7234 567,ATG,,+12687234567,AG,ATG,+1,true,,+1 268 Antigua and Barbuda,"returns +12687234567,ATG", 41 | +1 284 1234 567,VGB,,+12841234567,VG,VGB,+1,true,,+1 284 British Virgin Islands,"returns +12841234567,VGB", 42 | +1 345 1234 567,CYM,,+13451234567,KY,CYM,+1,true,,+1 345 Cayman Islands,"returns +13451234567,CYM", 43 | +1 441 1234 567,BMU,,,,,,false,,+1 441 Bermuda,"returns ", 44 | +1 441 3234 567,BMU,,+14413234567,BM,BMU,+1,true,,+1 441 Bermuda,"returns +14413234567,BMU", 45 | +1 441 5234 567,BMU,,+14415234567,BM,BMU,+1,true,,+1 441 Bermuda,"returns +14415234567,BMU", 46 | +1 441 7234 567,BMU,,+14417234567,BM,BMU,+1,true,,+1 441 Bermuda,"returns +14417234567,BMU", 47 | +1 473 1234 567,GRD,,+14731234567,GD,GRD,+1,true,,+1 473 Grenada,"returns +14731234567,GRD", 48 | +1 649 1234 567,TCA,,,,,,false,,+1 649 Turks and Caicos Islands,"returns ", 49 | +1 649 2234 567,TCA,,+16492234567,TC,TCA,+1,true,,+1 649 Turks and Caicos Islands,"returns +16492234567,TCA", 50 | +1 664 1234 567,MSR,,+16641234567,MS,MSR,+1,true,,+1 664 Montserrat,"returns +16641234567,MSR", 51 | +1 721 1234 567,SXM,,+17211234567,SX,SXM,+1,true,,+1 721 Sint Maarten,"returns +17211234567,SXM", 52 | +1 758 1234 567,LCA,,+17581234567,LC,LCA,+1,true,,+1 758 Saint Lucia,"returns +17581234567,LCA", 53 | +1 767 1234 567,DMA,,+17671234567,DM,DMA,+1,true,,+1 767 Dominica,"returns +17671234567,DMA", 54 | +1 784 1234 567,VCT,,+17841234567,VC,VCT,+1,true,,+1 784 Saint Vincent and the Grenadines,"returns +17841234567,VCT", 55 | +1 809 1234 567,DOM,,+18091234567,DO,DOM,+1,true,,+1 809 / 829 / 849 Dominican Republic,"returns +18091234567,DOM", 56 | +1 829 1234 567,DOM,,+18291234567,DO,DOM,+1,true,,+1 809 / 829 / 849 Dominican Republic,"returns +18291234567,DOM", 57 | +1 849 1234 567,DOM,,+18491234567,DO,DOM,+1,true,,+1 809 / 829 / 849 Dominican Republic,"returns +18491234567,DOM", 58 | +1 868 1234 567,TTO,,+18681234567,TT,TTO,+1,true,,+1 868 Trinidad and Tobago,"returns +18681234567,TTO", 59 | +1 869 1234 567,KNA,,+18691234567,KN,KNA,+1,true,,+1 869 Saint Kitts and Nevis,"returns +18691234567,KNA", 60 | +1 876 1234 567,JAM,,+18761234567,JM,JAM,+1,true,,+1 876 Jamaica,"returns +18761234567,JAM", 61 | +52 1 762 100 9517,,,+5217621009517,MX,MEX,+52,true,Testing MEX Phone,Test 1,"returns +5217621009517,MEX", 62 | +52 1 762 100 9517,MEX,,+5217621009517,MX,MEX,+52,true,,Test 2,"returns +5217621009517,MEX", 63 | +52 1 762 100 9517,USA,,,,,,false,,Test 3,"returns ", 64 | +52 1 762 100 9517,Mexico,,+5217621009517,MX,MEX,+52,true,,Test 4,"returns +5217621009517,MEX", 65 | +52 1 762 100 9517,United States,,,,,,false,,Test 5,"returns ", 66 | +52 62 100 9517,,,,,,,false,,Test 6,"returns ", 67 | +52 62 100 9517,MEX,,,,,,false,,Test 7,"returns ", 68 | +52 62 100 9517,USA,,,,,,false,,Test 8,"returns ", 69 | +52 62 100 9517,Mexico,,,,,,false,,Test 9,"returns ", 70 | +52 62 100 9517,United States,,,,,,false,,Test 10,"returns ", 71 | 52762 100 9517,,,,,,,false,,Test 11,"returns ", 72 | 762 100 9517,MEX,,+527621009517,MX,MEX,+52,true,,Test 12,"returns +527621009517,MEX", 73 | 762 100 9517,MEXINVALID,,,,,,false,,Test 13,"returns ", 74 | 762 100 9517,Mexico,,+527621009517,MX,MEX,+52,true,,Test 14,"returns +527621009517,MEX", 75 | 762 100 9517,Mexico Invalid,,,,,,false,,Test 15,"returns ", 76 | 6123-6123,HKG,,+85261236123,HK,HKG,+852,true,Testing HKG Phone Quick Test,Test 1,"returns +85261236123,HKG", 77 | +55 11 9 6123 1234,BRA,,+5511961231234,BR,BRA,+55,true,Testing BRA Phone Quick Test,Test 1,"returns +5511961231234,BRA", 78 | +55 69 8 6123 1234,BRA,,+5569861231234,BR,BRA,+55,false,,Test 4,"returns +5569861231234,BRA", 79 | +55 65 9 9123 4567,BRA,,+5565991234567,BR,BRA,+55,true,,Test 5,"returns +5565991234567,BRA", 80 | +5599988311895,BRA,,+5599988311895,BR,BRA,+55,true,,Test 6,"returns +5599988311895,BRA", 81 | +1-787-672-9999,PRI,,+17876729999,PR,PRI,+1,true,Testing PRI Phone Quick Test,Test 1,"returns +17876729999,PRI", 82 | 17876729999,PRI,,+17876729999,PR,PRI,+1,true,,Test 2,"returns +17876729999,PRI", 83 | 7876729999,PRI,,+17876729999,PR,PRI,+1,true,,Test 3,"returns +17876729999,PRI", 84 | 89234567890,RUS,,+79234567890,RU,RUS,+7,true,Testing RUS Phone Quick Test,Test 1,"returns +79234567890,RUS", 85 | +79234567890,RUS,,+79234567890,RU,RUS,+7,true,,Test 2,"returns +79234567890,RUS", 86 | +79234567890,,,+79234567890,RU,RUS,+7,true,,Test 3,"returns +79234567890,RUS", 87 | +70234567890,RUS,,,,,,false,,Test 4,"returns ", 88 | +79234567890,USA,,,,,,false,,Test 5,"returns ", 89 | 0812345678,THA,,+66812345678,TH,THA,+66,true,Testing THA Phone Quick Test,Test 1,"returns +66812345678,THA", 90 | 0912345678,THA,,+66912345678,TH,THA,+66,true,,Test 2,"returns +66912345678,THA", 91 | 812345678,THA,,+66812345678,TH,THA,+66,true,,Test 3,"returns +66812345678,THA", 92 | 0714795861,TZA,,+255714795861,TZ,TZA,+255,true,Testing TZA Phone Quick Test,Test 1,"returns +255714795861,TZA", 93 | 0684795861,TZA,,+255684795861,TZ,TZA,+255,true,,Test 2,"returns +255684795861,TZA", 94 | 714795861,TZA,,+255714795861,TZ,TZA,+255,true,,Test 3,"returns +255714795861,TZA", 95 | +77012345678,KAZ,,+77012345678,KZ,KAZ,+7,true,Testing KAZ Phone Quick Test,Test 1,"returns +77012345678,KAZ", 96 | +77412345678,KAZ,,+77412345678,KZ,KAZ,+7,true,,Test 2,"returns +77412345678,KAZ", 97 | +77712345678,KAZ,,+77712345678,KZ,KAZ,+7,true,,Test 3,"returns +77712345678,KAZ", 98 | +507 61234567,PAN,,+50761234567,PA,PAN,+507,true,Testing PAN Phone Quick Test,Test 1,"returns +50761234567,PAN", 99 | +507 51234567,PAN,,,,,,false,,Test 2,"returns ", 100 | +230 51234567,,,+23051234567,MU,MUS,+230,true,Testing MUS Phone Quick Test,Test 1,"returns +23051234567,MUS", 101 | +230 5123-4567,,,+23051234567,MU,MUS,+230,true,,Test 2,"returns +23051234567,MUS", 102 | +230 6123-4567,,,,,,,false,,Test 3,"returns ", 103 | +230 6123-4567,HKG,,,,,,false,,Test 4,"returns ", 104 | +86 199 51343779,,,+8619951343779,CN,CHN,+86,true,Testing CHN Phone Quick Test,Test for pattern 199,"returns +8619951343779,CHN", 105 | +86 198 51343779,,,+8619851343779,CN,CHN,+86,true,,Test for pattern 198,"returns +8619851343779,CHN", 106 | +86 166 51343779,,,+8616651343779,CN,CHN,+86,true,,Test for pattern 166,"returns +8616651343779,CHN", 107 | +54 233 123 4567,,,+542331234567,AR,ARG,+54,true,Testing ARG numbers,Test for number without 9 prefix,"returns +542331234567,ARG", 108 | +54 9 233 123 4567,,,+542331234567,AR,ARG,+54,true,,Test for number with 9 prefix,"returns +542331234567,ARG", 109 | +54 13 123 456,,,+5413123456,AR,ARG,+54,true,,Test for number with 2 + 6 digit,"returns +5413123456,ARG", 110 | +54 13 123 4567,,,+54131234567,AR,ARG,+54,true,,Test for number with 2 + 7 digit,"returns +54131234567,ARG", 111 | +54 13 123 45678,,,+541312345678,AR,ARG,+54,true,,Test for number with 2 + 8 digit,"returns +541312345678,ARG", 112 | +54 133 123 45678,,,+5413312345678,AR,ARG,+54,true,,Test for number with 3 + 8 digit,"returns +5413312345678,ARG", 113 | +54 1334 123 45678,,,+54133412345678,AR,ARG,+54,true,,Test for number with 4 + 8 digit,"returns +54133412345678,ARG", 114 | +299 555299,,,+299555299,GL,GRL,+299,true,Testing GRL numbers,Test for numbers starting with 5,"returns +299555299,GRL", 115 | +299 233299,,,+299233299,GL,GRL,+299,true,,Test for numbers starting with 2,"returns +299233299,GRL", 116 | +299 321000,,,,,,,false,,Test for landlines,"returns ", 117 | +95 9 55 00000,,,+9595500000,MM,MMR,+95,true,Testing MMR Phone,"Test for 8 digits mobile numbers ","returns +9595500000,MMR", 118 | +95 9 30 000 000,,,+95930000000,MM,MMR,+95,true,,"Test for 9 digits mobile numbers ","returns +95930000000,MMR", 119 | +95 9 426 00 0000,,,+959426000000,MM,MMR,+95,true,,Test 10 digits mobile numbers,"returns +959426000000,MMR", 120 | +95 1 1234567,,,,,,,false,,Test land lines,"returns ", 121 | +1 367 1234567,,,+13671234567,CA,CAN,+1,true,Testing Canada Phone,Should return result when it matches mobile_begin_with,"returns +13671234567,CAN", 122 | +1 111 1234567,,,,,,,false,,Should not return result when it does not match mobile_begin_with,"returns ", 123 | +237 612345678,,,+237612345678,CM,CMR,+237,true,Testing Cameroon Phone,Should return result when it matches mobile_begin_with,"returns +237612345678,CMR", 124 | +237 112345678,,,,,,,false,,Should not return result when it does not match mobile_begin_with,"returns ", 125 | +687 812345,,,+687812345,NC,NCL,+687,true,Testing New Caledonia Phone,Should return result when it matches mobile_begin_with,"returns +687812345,NCL", 126 | +687 512345,,,+687512345,NC,NCL,+687,true,Testing New Caledonia Phone,Should return result when NCL number starts with 5,"returns +687512345,NCL", 127 | +687 112345,,,,,,,false,,Should not return result when it does not match mobile_begin_with,"returns ", 128 | +380 73 123 45 67,,,+380731234567,UA,UKR,+380,true,Testing Ukraine Phone,Should return result when it matches mobile_begin_with,"returns +380731234567,UKR", 129 | +380 11 123 45 67,,,,,,,false,,Should not return result when it does not match mobile_begin_with,"returns ", 130 | +61(0)488888888,,,+61488888888,AU,AUS,+61,true,,test phone with trunk prefix,Austrilia phone with trunk prefix (0), 131 | +7(8)9234567890,,,+79234567890,RU,RUS,+7,true,,,Russian Federation phone with trunk prefix (8), 132 | +691(0)1234567,,,+6911234567,FM,FSM,+691,true,,,Micronesia with trunk prefix (0), 133 | +298 212345,,,+298212345,FO,FRO,+298,true,,test phone with no mobile_begin_with,Test 1, 134 | +17215201993,,,+17215201993,SX,SXM,+1,true,,[CORE-1562] add new phone number rules for `+17215201993、+5164518135、+6062311120、+16782069397`,Test +17215201993, 135 | +5164518135,,,+5164518135,,,,false,,,Test +5164518135, 136 | +6062311120,,,+6062311120,MY,MYS,+60,true,,,Test +6062311120, 137 | +16782069397,,,+16782069397,US,USA,+1,true,,,Test +16782069397, 138 | +85293785433,,,+85293785433,HK,HKG,+852,true,,Landline phone number test,"Test mobile phone number, should success", 139 | +85223785433,,,,,,,false,,,"Test landline phone number without 3rd parameter, should fail", 140 | +85223785433,,true,+85223785433,HK,HKG,+852,true,,,"Test landline phone number with 3rd parameter, should success", 141 | 85293785433,HKG,,+85293785433,HK,HKG,+852,true,,,"Test mobile phone number without plus sign, should success", 142 | 85223785433,HKG,,,,,,false,,,"Test landline phone number without plus sign without 3rd parameter, should fail", 143 | 85223785433,HKG,true,+85223785433,HK,HKG,+852,true,,,"Test landline phone number without plus sign with 3rd parameter, should success", 144 | 93785433,HKG,,+85293785433,HK,HKG,+852,true,,,"Test mobile phone number without plus sign nor country code, should success", 145 | 23785433,HKG,,,,,,false,,,"Test landline phone number without plus sign nor country code without 3rd parameter, should fail", 146 | 23785433,HKG,true,+85223785433,HK,HKG,+852,true,,,"Test landline phone number without plus sign nor country code with 3rd parameter, should success", 147 | +85293785433,HKG,,+85293785433,HK,HKG,+852,true,,#190 phone number with plus sign BUT without country code (intentionally wrong input),"1. with +, country code, and country, should get the result", 148 | 85293785433,HKG,,+85293785433,HK,HKG,+852,true,,,"2. without +, with country code, with country, should get the result", 149 | +93785433,HKG,,,,,,false,,,"3a. with +, without country code, with country, should get empty array", 150 | +41414141,NO,,,,,,false,,,"3b. with +, without country code, with country, should get empty array", 151 | +2011231234,USA,,,,,,false,,,"3c. with +, without country code, with country, should get empty array", 152 | 93785433,HKG,,+85293785433,HK,HKG,+852,true,,,"4a. without +, without country code, with country, should get the result", 153 | 2014125632,USA,,+12014125632,US,USA,+1,true,,,"4b. without +, without country code, with country, should get the result", 154 | 41414141,NO,,+4741414141,NO,NOR,+47,true,,,"4c. without +, without country code, with country, should get the result", 155 | +4741414141,,,+4741414141,NO,NOR,+47,true,,,"5a. with +, with country code, without country, should get the result", 156 | +85296587452,,,+85296587452,HK,HKG,+852,true,,,"5b. with +, with country code, without country, should get the result", 157 | +13612145896,,,+13612145896,US,USA,+1,true,,,"5c. with +, with country code, without country, should get the result", 158 | 13612145896,,,+13612145896,US,USA,+1,true,,,"6a. without +, with country code, without country, should get the result", 159 | 4741414141,,,+14741414141,CA,CAN,+1,true,,,"6b. without +, with country code, without country, will get canada", 160 | 4761414141,,,,,,,false,,,"6b. without +, with country code, without country, default USA and should get empty result", 161 | 96587452,,,,,,,false,,,"6c. without +, with country code, without country, default USA and should get empty result", 162 | +96587452,,,,,,,false,,,"7a. with +, without country code, without country, should get empty result", 163 | +3612145896,,,,,,,false,,,"7b. with +, without country code, without country, should get empty result", 164 | +41414141,,,,,,,false,,,"7c. with +, without country code, without country, should get empty result", 165 | 96587452,,,,,,,false,,,"8a. without +, without country code, without country, should get empty result", 166 | 3612145896,,,+13612145896,US,USA,+1,true,,,"8b. without +, without country code, without country, default USA, should get result", 167 | 41414141,,,,,,,false,,,"8c. without +, without country code, without country, should get empty result", 168 | +44 079111 23456,,,+447911123456,GB,GBR,+44,true,,Test strict detect switch,"returns +447911123456,GBR", 169 | +44 079111 23456,,,,,,,false,,,returns empty result for strict detect,true 170 | +44 079111 23456,,,+447911123456,GB,GBR,+44,true,,"returns +447911123456,GBR for explicitly false",false, 171 | +4710000000,,,,,,,false,Testing NO / SJ numbers,Should not be valid NO or SJ,returns, 172 | +4779000000,,,+4779000000,SJ,SJM,+47,true,,Should be SJ (Svalbard / Jan Mayen),"returns +4779000000,SJM", 173 | +36 50 1234567,,,+36501234567,HU,HUN,+36,true,,Hungary phone number 50 prefix,"returns +36501234567,HUN", 174 | +996 226123123,,,+996226123123,KG,KGZ,+996,true,,,Kyrgyzstan test 1, 175 | +996 206123123,,,+996206123123,KG,KGZ,+996,true,,,Kyrgyzstan test 2, 176 | +996 312583123,,,+996312583123,KG,KGZ,+996,true,,,Kyrgyzstan test 4, 177 | +996 312973123,,,+996312973123,KG,KGZ,+996,true,,,Kyrgyzstan test 5, 178 | +996 912973123,,,+996912973123,KG,KGZ,+996,true,,,Kyrgyzstan test 6, 179 | +996 312573123,,,,,,,false,,,Kyrgyzstan test 7, 180 | 048 999 999,XK,,+38348999999,XK,XKX,+383,true,Testing Kosovo number,,, 181 | +1 3292021234,,,+13292021234,US,USA,+1,true,,#389 (1),"returns +13292021234,USA", 182 | +1 4722021234,,,+14722021234,US,USA,+1,true,,#389 (2),"returns +14722021234,USA", 183 | +599 4161234,,,+5994161234,BQ,BES,+599,true,,,"returns BES 1", 184 | +599 7001234,,,+5997001234,BQ,BES,+599,true,,,"returns BES 2", 185 | +599 9583 1517,,,+59995831517,CW,CUW,+599,true,,,"returns ANT 1", 186 | +599 9683 1517,,,+59996831517,CW,CUW,+599,true,,,"returns ANT 2", 187 | +1 (353) 555-8900,,,+13535558900,US,USA,+1,true,,353 area code,"returns +13535558900,USA", 188 | +1 (645) 555-1234,,,+16455551234,US,USA,+1,true,,645 area code,"returns +16455551234,USA", 189 | +387 620 12345,,,+38762012345,BA,BIH,+387,true,,Bosnia and Herzegovina 8 digit number,"returns +38762012345,BIH", 190 | +387 6031 12345,,,+387603112345,BA,BIH,+387,true,,Bosnia and Herzegovina 9 digit number,"returns +387603112345,BIH", 191 | -------------------------------------------------------------------------------- /test_generate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let allOutput = [ 4 | [ 5 | 'input_phone', 6 | 'input_country', 7 | 'validate_prefix', 8 | 'output_phone', 9 | 'output_country_alpha2', 10 | 'output_country_alpha3', 11 | 'desc1', 12 | 'desc2', 13 | 'test_desc' 14 | ] 15 | ]; 16 | let outputLine = []; 17 | let description = []; 18 | 19 | const countryPhoneData = require('../data/country_phone_data'); 20 | 21 | function describe(desc, func) { 22 | description.push(desc); 23 | func(); 24 | } 25 | 26 | function test(desc, func) { 27 | func(); 28 | if (description.length === 0) { 29 | description = ['', ''].concat(description); 30 | } 31 | if (description.length === 1) { 32 | description = [''].concat(description); 33 | } 34 | outputLine = outputLine.concat(description); 35 | outputLine.push(desc); 36 | allOutput.push(outputLine); 37 | outputLine = []; 38 | description = []; 39 | } 40 | 41 | function expect(output) { 42 | return { 43 | toEqual: function(result) { 44 | if (!result || result.length === 0) { 45 | outputLine.push(''); 46 | outputLine.push(''); 47 | outputLine.push(''); 48 | } else { 49 | const countryIso3 = result[1]; 50 | const countryIso2 = countryPhoneData.find((d) => d.alpha3 === countryIso3).alpha2; 51 | outputLine.push(result[0]); 52 | outputLine.push(countryIso2); 53 | outputLine.push(result[1]); 54 | } 55 | } 56 | }; 57 | } 58 | 59 | function phone(arg1, arg2, arg3) { 60 | outputLine.push(arg1 || ''); 61 | outputLine.push(arg2 || ''); 62 | outputLine.push(arg3 || ''); 63 | } 64 | 65 | describe('Testing input parameter Phone', () => { 66 | describe('Test 1', () => { 67 | const number = '(852) 569-8900'; 68 | const result = []; 69 | test('returns ' + result, () => { 70 | expect(phone(number)).toEqual(result); 71 | }); 72 | }); 73 | 74 | describe('Test 2', () => { 75 | const number = '+1 (817) 569-8900'; 76 | const result = ['+18175698900', 'USA']; 77 | test('returns ' + result, () => { 78 | expect(phone(number)).toEqual(result); 79 | }); 80 | }); 81 | 82 | 83 | describe('Test 3', () => { 84 | const number = '+852 6569-8900'; 85 | const result = ['+85265698900', 'HKG']; 86 | test('returns ' + result, () => { 87 | expect(phone(number)).toEqual(result); 88 | }); 89 | }); 90 | 91 | describe('Test 4', () => { 92 | const number = '+852 6569-8900'; 93 | const country = 'HKG'; 94 | const result = ['+85265698900', 'HKG']; 95 | test('returns ' + result, () => { 96 | expect(phone(number, country)).toEqual(result); 97 | }); 98 | }); 99 | 100 | describe('Test 5', () => { 101 | const number = null; 102 | const country = 'HKG'; 103 | const result = []; 104 | test('returns ' + result, () => { 105 | expect(phone(number, country)).toEqual(result); 106 | }); 107 | }); 108 | 109 | describe('Test 6', () => { 110 | test('should remove the leadings zero when country is CIV', () => { 111 | expect(phone('+225 05345678', 'CIV')).toEqual(['+22505345678', 'CIV']); 112 | }); 113 | 114 | test('should remove the leadings zero when country is COG', () => { 115 | expect(phone('+242 012345678', 'COG')).toEqual(['+242012345678', 'COG']); 116 | }); 117 | }); 118 | }); 119 | 120 | describe('Testing USA Phone', () => { 121 | describe('Test 1', () => { 122 | const number = '(852) 569-8900'; 123 | const country = ''; 124 | const result = []; 125 | test('returns ' + result, () => { 126 | expect(phone(number, country)).toEqual(result); 127 | }); 128 | }); 129 | 130 | describe('Test 2', () => { 131 | const number = '+1 (817) 569-8900'; 132 | const country = ''; 133 | const result = ['+18175698900', 'USA']; 134 | 135 | test('returns ' + result, () => { 136 | expect(phone(number, country)).toEqual(result); 137 | }); 138 | }); 139 | 140 | describe('Test 3', () => { 141 | const number = '+1 (817) 569-8900'; 142 | const country = null; 143 | const result = ['+18175698900', 'USA']; 144 | test('returns ' + result, () => { 145 | expect(phone(number, country)).toEqual(result); 146 | }); 147 | }); 148 | 149 | 150 | describe('Test 4', () => { 151 | const number = '2121234567'; 152 | const country = ''; 153 | const result = ['+12121234567', 'USA']; 154 | test('returns ' + result, () => { 155 | expect(phone(number, country)).toEqual(result); 156 | }); 157 | }); 158 | 159 | describe('Test 5, does not provide country, should match canada phone number', () => { 160 | const number = '22-6569-8900'; 161 | const country = ''; 162 | const result = ['+12265698900', 'CAN']; 163 | test('returns ' + result, () => { 164 | expect(phone(number, country)).toEqual(result); 165 | }); 166 | }); 167 | 168 | describe('Test 6', () => { 169 | const number = '22-5569-8900'; 170 | const country = ''; 171 | const result = ['+12255698900', 'USA']; 172 | test('returns ' + result, () => { 173 | expect(phone(number, country)).toEqual(result); 174 | }); 175 | }); 176 | 177 | describe('Test 7', () => { 178 | const number = '+1 (817) 569-8900'; 179 | const country = 'United States'; 180 | const result = ['+18175698900', 'USA']; 181 | test('returns ' + result, () => { 182 | expect(phone(number, country)).toEqual(result); 183 | }); 184 | }); 185 | 186 | describe('Test 8', () => { 187 | const number = '+1 (817) 569-8900'; 188 | const country = 'United States '; 189 | const result = ['+18175698900', 'USA']; 190 | test('returns ' + result, () => { 191 | expect(phone(number, country)).toEqual(result); 192 | }); 193 | }); 194 | 195 | describe('Test 9', () => { 196 | const number = '+1 (817) 569-8900'; 197 | const country = 'USA'; 198 | const result = ['+18175698900', 'USA']; 199 | 200 | test('returns ' + result, () => { 201 | expect(phone(number, country)).toEqual(result); 202 | }); 203 | }); 204 | 205 | describe('Test 10', () => { 206 | const number = '+1 (817) 569-8900'; 207 | const country = 'USA '; 208 | const result = ['+18175698900', 'USA']; 209 | test('returns ' + result, () => { 210 | expect(phone(number, country)).toEqual(result); 211 | }); 212 | }); 213 | 214 | describe('Test 11', () => { 215 | const number = '+1 (817) 569-8900'; 216 | const country = 'US'; 217 | const result = ['+18175698900', 'USA']; 218 | test('returns ' + result, () => { 219 | expect(phone(number, country)).toEqual(result); 220 | }); 221 | }); 222 | 223 | describe('Test 12', () => { 224 | const number = '+1 (817) 569-8900'; 225 | const country = ' US'; 226 | const result = ['+18175698900', 'USA']; 227 | test('returns ' + result, () => { 228 | expect(phone(number, country)).toEqual(result); 229 | }); 230 | }); 231 | 232 | 233 | describe('Test 13', () => { 234 | const number = '+1 (817) 569-8900'; 235 | const country = 'HKG'; 236 | const result = []; 237 | test('returns ' + result, () => { 238 | expect(phone(number, country)).toEqual(result); 239 | }); 240 | }); 241 | 242 | describe('Test 14', () => { 243 | const number = '+1 (888) 569-8900'; 244 | const result = ['+18885698900', 'USA']; 245 | test('returns ' + result, () => { 246 | expect(phone(number)).toEqual(result); 247 | }); 248 | }); 249 | }); 250 | 251 | describe('Testing default Canada phone number', () => { 252 | describe('Test 1, does not provide country, should match canada phone number', () => { 253 | const number = '+1905-555-1234'; 254 | const country = ''; 255 | const result = ['+19055551234', 'CAN']; 256 | test('returns ' + result, () => { 257 | expect(phone(number, country)).toEqual(result); 258 | }); 259 | }); 260 | 261 | describe('Test 2, does not provide country and plus sign, should match canada phone number', () => { 262 | const number = '519-555-1234'; 263 | const country = ''; 264 | const result = ['+15195551234', 'CAN']; 265 | test('returns ' + result, () => { 266 | expect(phone(number, country)).toEqual(result); 267 | }); 268 | }); 269 | 270 | describe('Test 3, does not provide country and plus sign but with "1", should match nothing', () => { 271 | const number = '1519-555-1234'; 272 | const country = ''; 273 | const result = []; 274 | test('returns ' + result, () => { 275 | expect(phone(number, country)).toEqual(result); 276 | }); 277 | }); 278 | }); 279 | 280 | describe('Testing +1 but NOT in USA', () => { 281 | describe('+1 340 United States Virgin Islands', () => { 282 | const number = '+1 340 1234 567'; 283 | const country = 'VIR'; 284 | const result = ['+13401234567', 'VIR']; 285 | test('returns ' + result, () => { 286 | expect(phone(number, country)).toEqual(result); 287 | }); 288 | }); 289 | 290 | describe('+1 670 Northern Mariana Islands', () => { 291 | const number = '+1 670 1234 567'; 292 | const country = 'MNP'; 293 | const result = ['+16701234567', 'MNP']; 294 | test('returns ' + result, () => { 295 | expect(phone(number, country)).toEqual(result); 296 | }); 297 | }); 298 | 299 | 300 | describe('+1 671 Guam', () => { 301 | const number = '+1 671 1234 567'; 302 | const country = 'GUM'; 303 | const result = ['+16711234567', 'GUM']; 304 | test('returns ' + result, () => { 305 | expect(phone(number, country)).toEqual(result); 306 | }); 307 | }); 308 | 309 | describe('+1 684 American Samoa', () => { 310 | const number = '+1 684 1234 567'; 311 | const country = 'ASM'; 312 | const result = []; 313 | test('returns ' + result, () => { 314 | expect(phone(number, country)).toEqual(result); 315 | }); 316 | }); 317 | 318 | describe('+1 684 American Samoa', () => { 319 | const number = '+1 684 2584 567'; 320 | const country = 'ASM'; 321 | const result = ['+16842584567', 'ASM']; 322 | test('returns ' + result, () => { 323 | expect(phone(number, country)).toEqual(result); 324 | }); 325 | }); 326 | 327 | describe('+1 684 American Samoa', () => { 328 | const number = '+1 684 7334 567'; 329 | const country = 'ASM'; 330 | const result = ['+16847334567', 'ASM']; 331 | test('returns ' + result, () => { 332 | expect(phone(number, country)).toEqual(result); 333 | }); 334 | }); 335 | 336 | describe('+1 787 / 939 Puerto Rico', () => { 337 | const number = '+1 787 1234 567'; 338 | const country = 'PRI'; 339 | const result = ['+17871234567', 'PRI']; 340 | test('returns ' + result, () => { 341 | expect(phone(number, country)).toEqual(result); 342 | }); 343 | }); 344 | 345 | describe('+1 787 / 939 Puerto Rico', () => { 346 | const number = '+1 939 1234 567'; 347 | const country = 'PRI'; 348 | const result = ['+19391234567', 'PRI']; 349 | test('returns ' + result, () => { 350 | expect(phone(number, country)).toEqual(result); 351 | }); 352 | }); 353 | 354 | describe('+1 242 Bahamas', () => { 355 | const number = '+1 242 1234 567'; 356 | const country = 'BHS'; 357 | const result = ['+12421234567', 'BHS']; 358 | test('returns ' + result, () => { 359 | expect(phone(number, country)).toEqual(result); 360 | }); 361 | }); 362 | describe('+1 246 Barbados', () => { 363 | const number = '+1 246 1234 567'; 364 | const country = 'BRB'; 365 | const result = ['+12461234567', 'BRB']; 366 | test('returns ' + result, () => { 367 | expect(phone(number, country)).toEqual(result); 368 | }); 369 | }); 370 | 371 | describe('+1 264 Anguilla', () => { 372 | const number = '+1 264 1234 567'; 373 | const country = 'AIA'; 374 | const result = []; 375 | test('returns ' + result, () => { 376 | expect(phone(number, country)).toEqual(result); 377 | }); 378 | }); 379 | 380 | describe('+1 264 Anguilla', () => { 381 | const number = '+1 264 5234 567'; 382 | const country = 'AIA'; 383 | const result = ['+12645234567', 'AIA']; 384 | test('returns ' + result, () => { 385 | expect(phone(number, country)).toEqual(result); 386 | }); 387 | }); 388 | 389 | describe('+1 264 Anguilla', () => { 390 | const number = '+1 264 7234 567'; 391 | const country = 'AIA'; 392 | const result = ['+12647234567', 'AIA']; 393 | test('returns ' + result, () => { 394 | expect(phone(number, country)).toEqual(result); 395 | }); 396 | }); 397 | 398 | describe('+1 268 Antigua and Barbuda', () => { 399 | const number = '+1 268 1234 567'; 400 | const country = 'ATG'; 401 | const result = []; 402 | test('returns ' + result, () => { 403 | expect(phone(number, country)).toEqual(result); 404 | }); 405 | }); 406 | 407 | describe('+1 268 Antigua and Barbuda', () => { 408 | const number = '+1 268 7234 567'; 409 | const country = 'ATG'; 410 | const result = ['+12687234567', 'ATG']; 411 | test('returns ' + result, () => { 412 | expect(phone(number, country)).toEqual(result); 413 | }); 414 | }); 415 | 416 | describe('+1 284 British Virgin Islands', () => { 417 | const number = '+1 284 1234 567'; 418 | const country = 'VGB'; 419 | const result = ['+12841234567', 'VGB']; 420 | test('returns ' + result, () => { 421 | expect(phone(number, country)).toEqual(result); 422 | }); 423 | }); 424 | 425 | 426 | describe('+1 345 Cayman Islands', () => { 427 | const number = '+1 345 1234 567'; 428 | const country = 'CYM'; 429 | const result = ['+13451234567', 'CYM']; 430 | test('returns ' + result, () => { 431 | expect(phone(number, country)).toEqual(result); 432 | }); 433 | }); 434 | 435 | describe('+1 441 Bermuda', () => { 436 | const number = '+1 441 1234 567'; 437 | const country = 'BMU'; 438 | const result = []; 439 | test('returns ' + result, () => { 440 | expect(phone(number, country)).toEqual(result); 441 | }); 442 | }); 443 | 444 | 445 | describe('+1 441 Bermuda', () => { 446 | const number = '+1 441 3234 567'; 447 | const country = 'BMU'; 448 | const result = ['+14413234567', 'BMU']; 449 | test('returns ' + result, () => { 450 | expect(phone(number, country)).toEqual(result); 451 | }); 452 | }); 453 | 454 | describe('+1 441 Bermuda', () => { 455 | const number = '+1 441 5234 567'; 456 | const country = 'BMU'; 457 | const result = ['+14415234567', 'BMU']; 458 | test('returns ' + result, () => { 459 | expect(phone(number, country)).toEqual(result); 460 | }); 461 | }); 462 | 463 | describe('+1 441 Bermuda', () => { 464 | const number = '+1 441 7234 567'; 465 | const country = 'BMU'; 466 | const result = ['+14417234567', 'BMU']; 467 | test('returns ' + result, () => { 468 | expect(phone(number, country)).toEqual(result); 469 | }); 470 | }); 471 | 472 | 473 | describe('+1 473 Grenada', () => { 474 | const number = '+1 473 1234 567'; 475 | const country = 'GRD'; 476 | const result = ['+14731234567', 'GRD']; 477 | test('returns ' + result, () => { 478 | expect(phone(number, country)).toEqual(result); 479 | }); 480 | }); 481 | 482 | 483 | describe('+1 649 Turks and Caicos Islands', () => { 484 | const number = '+1 649 1234 567'; 485 | const country = 'TCA'; 486 | const result = []; 487 | test('returns ' + result, () => { 488 | expect(phone(number, country)).toEqual(result); 489 | }); 490 | }); 491 | 492 | describe('+1 649 Turks and Caicos Islands', () => { 493 | const number = '+1 649 2234 567'; 494 | const country = 'TCA'; 495 | const result = ['+16492234567', 'TCA']; 496 | test('returns ' + result, () => { 497 | expect(phone(number, country)).toEqual(result); 498 | }); 499 | }); 500 | 501 | describe('+1 664 Montserrat', () => { 502 | const number = '+1 664 1234 567'; 503 | const country = 'MSR'; 504 | const result = ['+16641234567', 'MSR']; 505 | test('returns ' + result, () => { 506 | expect(phone(number, country)).toEqual(result); 507 | }); 508 | }); 509 | 510 | 511 | describe('+1 721 Sint Maarten', () => { 512 | const number = '+1 721 1234 567'; 513 | const country = 'SXM'; 514 | const result = ['+17211234567', 'SXM']; 515 | test('returns ' + result, () => { 516 | expect(phone(number, country)).toEqual(result); 517 | }); 518 | }); 519 | 520 | describe('+1 758 Saint Lucia', () => { 521 | const number = '+1 758 1234 567'; 522 | const country = 'LCA'; 523 | const result = ['+17581234567', 'LCA']; 524 | test('returns ' + result, () => { 525 | expect(phone(number, country)).toEqual(result); 526 | }); 527 | }); 528 | 529 | describe('+1 767 Dominica', () => { 530 | const number = '+1 767 1234 567'; 531 | const country = 'DMA'; 532 | const result = ['+17671234567', 'DMA']; 533 | test('returns ' + result, () => { 534 | expect(phone(number, country)).toEqual(result); 535 | }); 536 | }); 537 | 538 | describe('+1 784 Saint Vincent and the Grenadines', () => { 539 | const number = '+1 784 1234 567'; 540 | const country = 'VCT'; 541 | const result = ['+17841234567', 'VCT']; 542 | test('returns ' + result, () => { 543 | expect(phone(number, country)).toEqual(result); 544 | }); 545 | }); 546 | 547 | 548 | describe('+1 809 / 829 / 849 Dominican Republic', () => { 549 | const number = '+1 809 1234 567'; 550 | const country = 'DOM'; 551 | const result = ['+18091234567', 'DOM']; 552 | test('returns ' + result, () => { 553 | expect(phone(number, country)).toEqual(result); 554 | }); 555 | }); 556 | 557 | describe('+1 809 / 829 / 849 Dominican Republic', () => { 558 | const number = '+1 829 1234 567'; 559 | const country = 'DOM'; 560 | const result = ['+18291234567', 'DOM']; 561 | test('returns ' + result, () => { 562 | expect(phone(number, country)).toEqual(result); 563 | }); 564 | }); 565 | 566 | describe('+1 809 / 829 / 849 Dominican Republic', () => { 567 | const number = '+1 849 1234 567'; 568 | const country = 'DOM'; 569 | const result = ['+18491234567', 'DOM']; 570 | test('returns ' + result, () => { 571 | expect(phone(number, country)).toEqual(result); 572 | }); 573 | }); 574 | 575 | 576 | describe('+1 868 Trinidad and Tobago', () => { 577 | const number = '+1 868 1234 567'; 578 | const country = 'TTO'; 579 | const result = ['+18681234567', 'TTO']; 580 | test('returns ' + result, () => { 581 | expect(phone(number, country)).toEqual(result); 582 | }); 583 | }); 584 | 585 | 586 | describe('+1 869 Saint Kitts and Nevis', () => { 587 | const number = '+1 869 1234 567'; 588 | const country = 'KNA'; 589 | const result = ['+18691234567', 'KNA']; 590 | test('returns ' + result, () => { 591 | expect(phone(number, country)).toEqual(result); 592 | }); 593 | }); 594 | 595 | 596 | describe('+1 876 Jamaica', () => { 597 | const number = '+1 876 1234 567'; 598 | const country = 'JAM'; 599 | const result = ['+18761234567', 'JAM']; 600 | test('returns ' + result, () => { 601 | expect(phone(number, country)).toEqual(result); 602 | }); 603 | }); 604 | }); 605 | 606 | describe('Testing MEX Phone', () => { 607 | // valid +phone, null 608 | // valid +phone, valid iso 609 | // valid +phone, invalid iso 610 | // valid +phone, valid name 611 | // valid +phone, invalid name 612 | 613 | describe('Test 1', () => { 614 | const number = '+52 1 762 100 9517'; 615 | const country = null; 616 | const result = ['+5217621009517', 'MEX']; 617 | test('returns ' + result, () => { 618 | expect(phone(number, country)).toEqual(result); 619 | }); 620 | }); 621 | 622 | 623 | describe('Test 2', () => { 624 | const number = '+52 1 762 100 9517'; 625 | const country = 'MEX'; 626 | const result = ['+5217621009517', 'MEX']; 627 | test('returns ' + result, () => { 628 | expect(phone(number, country)).toEqual(result); 629 | }); 630 | }); 631 | describe('Test 3', () => { 632 | const number = '+52 1 762 100 9517'; 633 | const country = 'USA'; 634 | const result = []; 635 | test('returns ' + result, () => { 636 | expect(phone(number, country)).toEqual(result); 637 | }); 638 | }); 639 | describe('Test 4', () => { 640 | const number = '+52 1 762 100 9517'; 641 | const country = 'Mexico'; 642 | const result = ['+5217621009517', 'MEX']; 643 | test('returns ' + result, () => { 644 | expect(phone(number, country)).toEqual(result); 645 | }); 646 | }); 647 | describe('Test 5', () => { 648 | const number = '+52 1 762 100 9517'; 649 | const country = 'United States'; 650 | const result = []; 651 | test('returns ' + result, () => { 652 | expect(phone(number, country)).toEqual(result); 653 | }); 654 | }); 655 | 656 | // invalid +phone, null 657 | // invalid +phone, valid iso 658 | // invalid +phone, invalid iso 659 | // invalid +phone, valid name 660 | // invalid +phone, invalid name 661 | 662 | 663 | describe('Test 6', () => { 664 | const number = '+52 62 100 9517'; 665 | const country = null; 666 | const result = []; 667 | test('returns ' + result, () => { 668 | expect(phone(number, country)).toEqual(result); 669 | }); 670 | }); 671 | describe('Test 7', () => { 672 | const number = '+52 62 100 9517'; 673 | const country = 'MEX'; 674 | const result = []; 675 | test('returns ' + result, () => { 676 | expect(phone(number, country)).toEqual(result); 677 | }); 678 | }); 679 | describe('Test 8', () => { 680 | const number = '+52 62 100 9517'; 681 | const country = 'USA'; 682 | const result = []; 683 | test('returns ' + result, () => { 684 | expect(phone(number, country)).toEqual(result); 685 | }); 686 | }); 687 | describe('Test 9', () => { 688 | const number = '+52 62 100 9517'; 689 | const country = 'Mexico'; 690 | const result = []; 691 | test('returns ' + result, () => { 692 | expect(phone(number, country)).toEqual(result); 693 | }); 694 | }); 695 | describe('Test 10', () => { 696 | const number = '+52 62 100 9517'; 697 | const country = 'United States'; 698 | const result = []; 699 | test('returns ' + result, () => { 700 | expect(phone(number, country)).toEqual(result); 701 | }); 702 | }); 703 | 704 | // valid phone, null 705 | // valid phone, valid iso 706 | // valid phone, invalid iso 707 | // valid phone, valid name 708 | // valid phone, invalid name 709 | 710 | 711 | describe('Test 11', () => { 712 | const number = '52762 100 9517'; 713 | const country = null; 714 | const result = []; 715 | test('returns ' + result, () => { 716 | expect(phone(number, country)).toEqual(result); 717 | }); 718 | }); 719 | describe('Test 12', () => { 720 | const number = '762 100 9517'; 721 | const country = 'MEX'; 722 | const result = ['+527621009517', 'MEX']; 723 | test('returns ' + result, () => { 724 | expect(phone(number, country)).toEqual(result); 725 | }); 726 | }); 727 | describe('Test 13', () => { 728 | const number = '762 100 9517'; 729 | const country = 'MEXINVALID'; 730 | const result = []; 731 | test('returns ' + result, () => { 732 | expect(phone(number, country)).toEqual(result); 733 | }); 734 | }); 735 | describe('Test 14', () => { 736 | const number = '762 100 9517'; 737 | const country = 'Mexico'; 738 | const result = ['+527621009517', 'MEX']; 739 | test('returns ' + result, () => { 740 | expect(phone(number, country)).toEqual(result); 741 | }); 742 | }); 743 | describe('Test 15', () => { 744 | const number = '762 100 9517'; 745 | const country = 'Mexico Invalid'; 746 | const result = []; 747 | test('returns ' + result, () => { 748 | expect(phone(number, country)).toEqual(result); 749 | }); 750 | }); 751 | }); 752 | 753 | 754 | describe('Testing HKG Phone Quick Test', () => { 755 | describe('Test 1', () => { 756 | const number = '6123-6123'; 757 | const country = 'HKG'; 758 | const result = ['+85261236123', 'HKG']; 759 | test('returns ' + result, () => { 760 | expect(phone(number, country)).toEqual(result); 761 | }); 762 | }); 763 | }); 764 | 765 | 766 | describe('Testing BRA Phone Quick Test', () => { 767 | describe('Test 1', () => { 768 | const number = '+55 11 9 6123 1234'; 769 | const country = 'BRA'; 770 | const result = ['+5511961231234', 'BRA']; 771 | test('returns ' + result, () => { 772 | expect(phone(number, country)).toEqual(result); 773 | }); 774 | }); 775 | 776 | describe('Test 4', () => { 777 | const number = '+55 69 8 6123 1234'; 778 | const country = 'BRA'; 779 | const result = ['+5569861231234', 'BRA']; 780 | test('returns ' + result, () => { 781 | expect(phone(number, country)).toEqual(result); 782 | }); 783 | }); 784 | 785 | describe('Test 5', () => { 786 | const number = '+55 65 9 9123 4567'; 787 | const country = 'BRA'; 788 | const result = ['+5565991234567', 'BRA']; 789 | test('returns ' + result, () => { 790 | expect(phone(number, country)).toEqual(result); 791 | }); 792 | }); 793 | 794 | describe('Test 6', () => { 795 | const number = '+5599988311895'; 796 | const country = 'BRA'; 797 | const result = ['+5599988311895', 'BRA']; 798 | test('returns ' + result, () => { 799 | expect(phone(number, country)).toEqual(result); 800 | }); 801 | }); 802 | }); 803 | 804 | describe('Testing PRI Phone Quick Test', () => { 805 | describe('Test 1', () => { 806 | const number = '+1-787-672-9999'; 807 | const country = 'PRI'; 808 | const result = ['+17876729999', 'PRI']; 809 | test('returns ' + result, () => { 810 | expect(phone(number, country)).toEqual(result); 811 | }); 812 | }); 813 | 814 | describe('Test 2', () => { 815 | const number = '17876729999'; 816 | const country = 'PRI'; 817 | const result = ['+17876729999', 'PRI']; 818 | test('returns ' + result, () => { 819 | expect(phone(number, country)).toEqual(result); 820 | }); 821 | }); 822 | 823 | describe('Test 3', () => { 824 | const number = '7876729999'; 825 | const country = 'PRI'; 826 | const result = ['+17876729999', 'PRI']; 827 | test('returns ' + result, () => { 828 | expect(phone(number, country)).toEqual(result); 829 | }); 830 | }); 831 | }); 832 | 833 | // input --> output 834 | // 89234567890, RUS --> +79234567890, RUS 835 | // +79234567890, RUS --> +79234567890, RUS 836 | // +79234567890 ---> +79234567890, RUS 837 | // +70234567890, RUS ---> invalid 838 | // 9234567890, RUS ---> +79234567890, RUS 839 | 840 | 841 | describe('Testing RUS Phone Quick Test', () => { 842 | describe('Test 1', () => { 843 | const number = '89234567890'; // remove the 8, treat it as 923456789; 844 | const country = 'RUS'; 845 | const result = ['+79234567890', 'RUS']; 846 | test('returns ' + result, () => { 847 | expect(phone(number, country)).toEqual(result); 848 | }); 849 | }); 850 | 851 | describe('Test 2', () => { 852 | const number = '+79234567890'; 853 | const country = 'RUS'; 854 | const result = ['+79234567890', 'RUS']; 855 | test('returns ' + result, () => { 856 | expect(phone(number, country)).toEqual(result); 857 | }); 858 | }); 859 | 860 | describe('Test 3', () => { 861 | const number = '+79234567890'; 862 | const country = ''; 863 | const result = ['+79234567890', 'RUS']; 864 | test('returns ' + result, () => { 865 | expect(phone(number, country)).toEqual(result); 866 | }); 867 | }); 868 | 869 | describe('Test 4', () => { 870 | const number = '+70234567890'; 871 | const country = 'RUS'; 872 | const result = []; // as 0 is not a valid prefix, must be 9 873 | test('returns ' + result, () => { 874 | expect(phone(number, country)).toEqual(result); 875 | }); 876 | }); 877 | 878 | describe('Test 5', () => { 879 | const number = '+79234567890'; 880 | const country = 'USA'; 881 | const result = []; 882 | test('returns ' + result, () => { 883 | expect(phone(number, country)).toEqual(result); 884 | }); 885 | }); 886 | }); 887 | 888 | describe('Testing THA Phone Quick Test', () => { 889 | describe('Test 1', () => { 890 | const number = '0812345678'; // remove the leading ; 891 | const country = 'THA'; 892 | const result = ['+66812345678', 'THA']; 893 | test('returns ' + result, () => { 894 | expect(phone(number, country)).toEqual(result); 895 | }); 896 | }); 897 | 898 | describe('Test 2', () => { 899 | const number = '0912345678'; // remove the leading ; 900 | const country = 'THA'; 901 | const result = ['+66912345678', 'THA']; 902 | test('returns ' + result, () => { 903 | expect(phone(number, country)).toEqual(result); 904 | }); 905 | }); 906 | 907 | describe('Test 3', () => { 908 | const number = '812345678'; 909 | const country = 'THA'; 910 | const result = ['+66812345678', 'THA']; 911 | test('returns ' + result, () => { 912 | expect(phone(number, country)).toEqual(result); 913 | }); 914 | }); 915 | }); 916 | 917 | 918 | describe('Testing TZA Phone Quick Test', () => { 919 | describe('Test 1', () => { 920 | const number = '0714795861'; // remove the leading ; 921 | const country = 'TZA'; 922 | const result = ['+255714795861', 'TZA']; 923 | test('returns ' + result, () => { 924 | expect(phone(number, country)).toEqual(result); 925 | }); 926 | }); 927 | 928 | describe('Test 2', () => { 929 | const number = '0684795861'; // remove the leading ; 930 | const country = 'TZA'; 931 | const result = ['+255684795861', 'TZA']; 932 | test('returns ' + result, () => { 933 | expect(phone(number, country)).toEqual(result); 934 | }); 935 | }); 936 | 937 | describe('Test 3', () => { 938 | const number = '714795861'; 939 | const country = 'TZA'; 940 | const result = ['+255714795861', 'TZA']; 941 | test('returns ' + result, () => { 942 | expect(phone(number, country)).toEqual(result); 943 | }); 944 | }); 945 | }); 946 | 947 | describe('Testing KAZ Phone Quick Test', () => { 948 | describe('Test 1', () => { 949 | const number = '+77012345678'; 950 | const country = 'KAZ'; 951 | const result = ['+77012345678', 'KAZ']; 952 | test('returns ' + result, () => { 953 | expect(phone(number, country)).toEqual(result); 954 | }); 955 | }); 956 | 957 | describe('Test 2', () => { 958 | const number = '+77412345678'; 959 | const country = 'KAZ'; 960 | const result = ['+77412345678', 'KAZ']; 961 | test('returns ' + result, () => { 962 | expect(phone(number, country)).toEqual(result); 963 | }); 964 | }); 965 | 966 | describe('Test 3', () => { 967 | const number = '+77712345678'; 968 | const country = 'KAZ'; 969 | const result = ['+77712345678', 'KAZ']; 970 | test('returns ' + result, () => { 971 | expect(phone(number, country)).toEqual(result); 972 | }); 973 | }); 974 | }); 975 | 976 | 977 | describe('Testing PAN Phone Quick Test', () => { 978 | describe('Test 1', () => { 979 | const number = '+507 61234567'; 980 | const country = 'PAN'; 981 | const result = ['+50761234567', 'PAN']; 982 | test('returns ' + result, () => { 983 | expect(phone(number, country)).toEqual(result); 984 | }); 985 | }); 986 | 987 | 988 | describe('Test 2', () => { 989 | const number = '+507 51234567'; // start from 5 is landlines 990 | const country = 'PAN'; 991 | const result = []; 992 | test('returns ' + result, () => { 993 | expect(phone(number, country)).toEqual(result); 994 | }); 995 | }); 996 | }); 997 | 998 | describe('Testing MUS Phone Quick Test', () => { 999 | describe('Test 1', () => { 1000 | const number = '+230 51234567'; 1001 | const result = ['+23051234567', 'MUS']; 1002 | test('returns ' + result, () => { 1003 | expect(phone(number)).toEqual(result); 1004 | }); 1005 | }); 1006 | 1007 | 1008 | describe('Test 2', () => { 1009 | const number = '+230 5123-4567'; 1010 | const result = ['+23051234567', 'MUS']; 1011 | test('returns ' + result, () => { 1012 | expect(phone(number)).toEqual(result); 1013 | }); 1014 | }); 1015 | 1016 | describe('Test 3', () => { 1017 | const number = '+230 6123-4567'; // Landlines 1018 | const result = []; 1019 | test('returns ' + result, () => { 1020 | expect(phone(number)).toEqual(result); 1021 | }); 1022 | }); 1023 | 1024 | describe('Test 4', () => { 1025 | const number = '+230 6123-4567'; // Country code not match with number 1026 | const country = 'HKG'; 1027 | const result = []; 1028 | test('returns ' + result, () => { 1029 | expect(phone(number, country)).toEqual(result); 1030 | }); 1031 | }); 1032 | }); 1033 | 1034 | 1035 | describe('Testing CHN Phone Quick Test', () => { 1036 | // Test for new pattern (199, 198, 166) 1037 | describe('Test for pattern 199', () => { 1038 | const number = '+86 199 51343779'; 1039 | const result = ['+8619951343779', 'CHN']; 1040 | test('returns ' + result, () => { 1041 | expect(phone(number)).toEqual(result); 1042 | }); 1043 | }); 1044 | 1045 | describe('Test for pattern 198', () => { 1046 | const number = '+86 198 51343779'; 1047 | const result = ['+8619851343779', 'CHN']; 1048 | test('returns ' + result, () => { 1049 | expect(phone(number)).toEqual(result); 1050 | }); 1051 | }); 1052 | 1053 | describe('Test for pattern 166', () => { 1054 | const number = '+86 166 51343779'; 1055 | const result = ['+8616651343779', 'CHN']; 1056 | test('returns ' + result, () => { 1057 | expect(phone(number)).toEqual(result); 1058 | }); 1059 | }); 1060 | }); 1061 | 1062 | 1063 | describe('Testing ARG numbers', () => { 1064 | describe('Test for number without 9 prefix', () => { 1065 | const number = '+54 233 123 4567'; 1066 | const result = ['+542331234567', 'ARG']; 1067 | test('returns ' + result, () => { 1068 | expect(phone(number)).toEqual(result); 1069 | }); 1070 | }); 1071 | 1072 | describe('Test for number with 9 prefix', () => { 1073 | const number = '+54 9 233 123 4567'; 1074 | const result = ['+542331234567', 'ARG']; 1075 | test('returns ' + result, () => { 1076 | expect(phone(number)).toEqual(result); 1077 | }); 1078 | }); 1079 | 1080 | describe('Test for number with 15 prefix', () => { 1081 | const number = '+54 15 233 123 4567'; 1082 | const result = []; 1083 | test('returns ' + result, () => { 1084 | expect(phone(number)).toEqual(result); 1085 | }); 1086 | }); 1087 | }); 1088 | 1089 | 1090 | describe('Testing GRL numbers', () => { 1091 | describe('Test for numbers starting with 5', () => { 1092 | const number = '+299 555299'; 1093 | const result = ['+299555299', 'GRL']; 1094 | test('returns ' + result, () => { 1095 | expect(phone(number)).toEqual(result); 1096 | }); 1097 | }); 1098 | describe('Test for numbers starting with 2', () => { 1099 | const number = '+299 233299'; 1100 | const result = ['+299233299', 'GRL']; 1101 | test('returns ' + result, () => { 1102 | expect(phone(number)).toEqual(result); 1103 | }); 1104 | }); 1105 | describe('Test for landlines', () => { 1106 | const number = '+299 321000'; 1107 | const result = []; 1108 | test('returns ' + result, () => { 1109 | expect(phone(number)).toEqual(result); 1110 | }); 1111 | }); 1112 | }); 1113 | 1114 | 1115 | describe( 'Testing MMR Phone', () => { 1116 | describe('Test for 8 digits mobile numbers ', () => { 1117 | const number = '+95 9 55 00000'; 1118 | const result = ['+9595500000', 'MMR']; 1119 | test('returns ' + result, () => { 1120 | expect(phone(number)).toEqual(result); 1121 | }); 1122 | }); 1123 | describe('Test for 9 digits mobile numbers ', () => { 1124 | const number = '+95 9 30 000 000'; 1125 | const result = ['+95930000000', 'MMR']; 1126 | test('returns ' + result, () => { 1127 | expect(phone(number)).toEqual(result); 1128 | }); 1129 | }); 1130 | describe('Test 10 digits mobile numbers', () => { 1131 | const number = '+95 9 426 00 0000'; 1132 | const result = ['+959426000000', 'MMR']; 1133 | test('returns ' + result, () => { 1134 | expect(phone(number)).toEqual(result); 1135 | }); 1136 | }); 1137 | describe('Test land lines', () => { 1138 | const number = '+95 1 1234567'; //Landlines 1139 | const result = []; 1140 | test('returns ' + result, () => { 1141 | expect(phone(number)).toEqual(result); 1142 | }); 1143 | }); 1144 | }); 1145 | 1146 | 1147 | describe( 'Testing Canada Phone', () => { 1148 | describe('Should return result when it matches mobile_begin_with', () => { 1149 | const number = '+1 367 1234567'; 1150 | const result = ['+13671234567', 'CAN']; 1151 | test('returns ' + result, () => { 1152 | expect(phone(number)).toEqual(result); 1153 | }); 1154 | }); 1155 | describe('Should not return result when it does not match mobile_begin_with', () => { 1156 | const number = '+1 111 1234567'; 1157 | const result = []; 1158 | test('returns ' + result, () => { 1159 | expect(phone(number)).toEqual(result); 1160 | }); 1161 | }); 1162 | }); 1163 | 1164 | 1165 | describe( 'Testing Cameroon Phone', () => { 1166 | describe('Should return result when it matches mobile_begin_with', () => { 1167 | const number = '+237 612345678'; 1168 | const result = ['+237612345678', 'CMR']; 1169 | test('returns ' + result, () => { 1170 | expect(phone(number)).toEqual(result); 1171 | }); 1172 | }); 1173 | describe('Should not return result when it does not match mobile_begin_with', () => { 1174 | const number = '+237 112345678'; 1175 | const result = []; 1176 | test('returns ' + result, () => { 1177 | expect(phone(number)).toEqual(result); 1178 | }); 1179 | }); 1180 | }); 1181 | 1182 | 1183 | describe( 'Testing New Caledonia Phone', () => { 1184 | describe('Should return result when it matches mobile_begin_with', () => { 1185 | const number = '+687 812345'; 1186 | const result = ['+687812345', 'NCL']; 1187 | test('returns ' + result, () => { 1188 | expect(phone(number)).toEqual(result); 1189 | }); 1190 | }); 1191 | describe('Should not return result when it does not match mobile_begin_with', () => { 1192 | const number = '+687 112345'; 1193 | const result = []; 1194 | test('returns ' + result, () => { 1195 | expect(phone(number)).toEqual(result); 1196 | }); 1197 | }); 1198 | }); 1199 | 1200 | 1201 | describe( 'Testing Ukraine Phone', () => { 1202 | describe('Should return result when it matches mobile_begin_with', () => { 1203 | const number = '+380 73 123 45 67'; 1204 | const result = ['+380731234567', 'UKR']; 1205 | test('returns ' + result, () => { 1206 | expect(phone(number)).toEqual(result); 1207 | }); 1208 | }); 1209 | describe('Should not return result when it does not match mobile_begin_with', () => { 1210 | const number = '+380 11 123 45 67'; 1211 | const result = []; 1212 | test('returns ' + result, () => { 1213 | expect(phone(number)).toEqual(result); 1214 | }); 1215 | }); 1216 | }); 1217 | 1218 | 1219 | describe('test phone with trunk prefix', () => { 1220 | test('Austrilia phone with trunk prefix (0)', () => { 1221 | const number = '+61(0)488888888'; 1222 | const result = ['+61488888888', 'AUS']; 1223 | expect(phone(number)).toEqual(result); 1224 | }); 1225 | 1226 | test('Russian Federation phone with trunk prefix (8)', () => { 1227 | const number = '+7(8)9234567890'; 1228 | const result = ['+79234567890', 'RUS']; 1229 | expect(phone(number)).toEqual(result); 1230 | }); 1231 | 1232 | test('Micronesia with trunk prefix (0)', () => { 1233 | const number = '+691(0)1234567'; 1234 | const result = ['+6911234567', 'FSM']; 1235 | expect(phone(number)).toEqual(result); 1236 | }); 1237 | }); 1238 | 1239 | describe('test phone with no mobile_begin_with', () => { 1240 | test('Test 1', () => { 1241 | const number = '+298 212345'; 1242 | const result = ['+298212345', 'FRO']; 1243 | expect(phone(number)).toEqual(result); 1244 | }); 1245 | }); 1246 | 1247 | describe('[CORE-1562] add new phone number rules for `+17215201993、+5164518135、+6062311120、+16782069397`', () => { 1248 | test('Test +17215201993', () => { 1249 | const number = '+17215201993'; 1250 | const result = ['+17215201993', 'SXM']; 1251 | expect(phone(number)).toEqual(result); 1252 | }); 1253 | 1254 | test('Test +5164518135', () => { 1255 | const number = '+5164518135'; 1256 | const result = ['+5164518135', 'PER']; 1257 | expect(phone(number)).toEqual(result); 1258 | }); 1259 | 1260 | test('Test +6062311120', () => { 1261 | const number = '+6062311120'; 1262 | const result = ['+6062311120', 'MYS']; 1263 | expect(phone(number)).toEqual(result); 1264 | }); 1265 | 1266 | test('Test +16782069397', () => { 1267 | const number = '+16782069397'; 1268 | const result = ['+16782069397', 'USA']; 1269 | expect(phone(number)).toEqual(result); 1270 | }); 1271 | }); 1272 | 1273 | 1274 | describe('Landline phone number test', () => { 1275 | test('Test mobile phone number, should success', () => { 1276 | const number = '+85293785433'; 1277 | const result = ['+85293785433', 'HKG']; 1278 | expect(phone(number)).toEqual(result); 1279 | }); 1280 | 1281 | test('Test landline phone number without 3rd parameter, should fail', () => { 1282 | const number = '+85223785433'; 1283 | const result = []; 1284 | expect(phone(number)).toEqual(result); 1285 | }); 1286 | 1287 | test('Test landline phone number with 3rd parameter, should success', () => { 1288 | const number = '+85223785433'; 1289 | const result = ['+85223785433', 'HKG']; 1290 | expect(phone(number, '', true)).toEqual(result); 1291 | }); 1292 | 1293 | test('Test mobile phone number without plus sign, should success', () => { 1294 | const number = '85293785433'; 1295 | const result = ['+85293785433', 'HKG']; 1296 | expect(phone(number, 'HKG')).toEqual(result); 1297 | }); 1298 | 1299 | test('Test landline phone number without plus sign without 3rd parameter, should fail', () => { 1300 | const number = '85223785433'; 1301 | const result = []; 1302 | expect(phone(number, 'HKG')).toEqual(result); 1303 | }); 1304 | 1305 | test('Test landline phone number without plus sign with 3rd parameter, should success', () => { 1306 | const number = '85223785433'; 1307 | const result = ['+85223785433', 'HKG']; 1308 | expect(phone(number, 'HKG', true)).toEqual(result); 1309 | }); 1310 | 1311 | test('Test mobile phone number without plus sign nor country code, should success', () => { 1312 | const number = '93785433'; 1313 | const result = ['+85293785433', 'HKG']; 1314 | expect(phone(number, 'HKG')).toEqual(result); 1315 | }); 1316 | 1317 | test('Test landline phone number without plus sign nor country code without 3rd parameter, should fail', () => { 1318 | const number = '23785433'; 1319 | const result = []; 1320 | expect(phone(number, 'HKG')).toEqual(result); 1321 | }); 1322 | 1323 | test('Test landline phone number without plus sign nor country code with 3rd parameter, should success', () => { 1324 | const number = '23785433'; 1325 | const result = ['+85223785433', 'HKG']; 1326 | expect(phone(number, 'HKG', true)).toEqual(result); 1327 | }); 1328 | }); 1329 | 1330 | describe('#190 phone number with plus sign BUT without country code (intentionally wrong input)', () => { 1331 | test('1. with +, country code, and country, should get the result', () => { 1332 | const number = '+85293785433'; 1333 | const country = 'HKG'; 1334 | const result = ['+85293785433', 'HKG']; 1335 | expect(phone(number, country)).toEqual(result); 1336 | }); 1337 | 1338 | test('2. without +, with country code, with country, should get the result', () => { 1339 | const number = '85293785433'; 1340 | const country = 'HKG'; 1341 | const result = ['+85293785433', 'HKG']; 1342 | expect(phone(number, country)).toEqual(result); 1343 | }); 1344 | 1345 | test('3a. with +, without country code, with country, should get empty array', () => { 1346 | const number = '+93785433'; 1347 | const country = 'HKG'; 1348 | const result = []; 1349 | expect(phone(number, country)).toEqual(result); 1350 | }); 1351 | 1352 | test('3b. with +, without country code, with country, should get empty array', () => { 1353 | const number = '+41414141'; 1354 | const country = 'NO'; 1355 | const result = []; 1356 | expect(phone(number, country)).toEqual(result); 1357 | }); 1358 | 1359 | test('3c. with +, without country code, with country, should get empty array', () => { 1360 | const number = '+2011231234'; 1361 | const country = 'USA'; 1362 | const result = []; 1363 | expect(phone(number, country)).toEqual(result); 1364 | }); 1365 | 1366 | test('4a. without +, without country code, with country, should get the result', () => { 1367 | const number = '93785433'; 1368 | const country = 'HKG'; 1369 | const result = ['+85293785433', 'HKG']; 1370 | expect(phone(number, country)).toEqual(result); 1371 | }); 1372 | 1373 | test('4b. without +, without country code, with country, should get the result', () => { 1374 | const number = '2014125632'; 1375 | const country = 'USA'; 1376 | const result = ['+12014125632', 'USA']; 1377 | expect(phone(number, country)).toEqual(result); 1378 | }); 1379 | 1380 | test('4c. without +, without country code, with country, should get the result', () => { 1381 | const number = '41414141'; 1382 | const country = 'NO'; 1383 | const result = ['+4741414141', 'NOR']; 1384 | expect(phone(number, country)).toEqual(result); 1385 | }); 1386 | 1387 | test('5a. with +, with country code, without country, should get the result', () => { 1388 | const number = '+4741414141'; 1389 | const result = ['+4741414141', 'NOR']; 1390 | expect(phone(number)).toEqual(result); 1391 | }); 1392 | 1393 | test('5b. with +, with country code, without country, should get the result', () => { 1394 | const number = '+85296587452'; 1395 | const result = ['+85296587452', 'HKG']; 1396 | expect(phone(number)).toEqual(result); 1397 | }); 1398 | 1399 | test('5c. with +, with country code, without country, should get the result', () => { 1400 | const number = '+13612145896'; 1401 | const result = ['+13612145896', 'USA']; 1402 | expect(phone(number)).toEqual(result); 1403 | }); 1404 | 1405 | test('6a. without +, with country code, without country, should get the result', () => { 1406 | const number = '13612145896'; 1407 | const result = ['+13612145896', 'USA']; 1408 | expect(phone(number)).toEqual(result); 1409 | }); 1410 | 1411 | test('6b. without +, with country code, without country, default USA and should get empty result', () => { 1412 | const number = '4741414141'; 1413 | const result = []; 1414 | expect(phone(number)).toEqual(result); 1415 | }); 1416 | 1417 | test('6c. without +, with country code, without country, default USA and should get empty result', () => { 1418 | const number = '96587452'; 1419 | const result = []; 1420 | expect(phone(number)).toEqual(result); 1421 | }); 1422 | 1423 | test('7a. with +, without country code, without country, should get empty result', () => { 1424 | const number = '+96587452'; 1425 | const result = []; 1426 | expect(phone(number)).toEqual(result); 1427 | }); 1428 | 1429 | test('7b. with +, without country code, without country, should get empty result', () => { 1430 | const number = '+3612145896'; 1431 | const result = []; 1432 | expect(phone(number)).toEqual(result); 1433 | }); 1434 | 1435 | test('7c. with +, without country code, without country, should get empty result', () => { 1436 | const number = '+41414141'; 1437 | const result = []; 1438 | expect(phone(number)).toEqual(result); 1439 | }); 1440 | 1441 | test('8a. without +, without country code, without country, should get empty result', () => { 1442 | const number = '96587452'; 1443 | const result = []; 1444 | expect(phone(number)).toEqual(result); 1445 | }); 1446 | 1447 | test('8b. without +, without country code, without country, default USA, should get result', () => { 1448 | const number = '3612145896'; 1449 | const result = ['+13612145896', 'USA']; 1450 | expect(phone(number)).toEqual(result); 1451 | }); 1452 | 1453 | test('8c. without +, without country code, without country, should get empty result', () => { 1454 | const number = '41414141'; 1455 | const result = []; 1456 | expect(phone(number)).toEqual(result); 1457 | }); 1458 | }); 1459 | 1460 | const {unparse} = require('papaparse'); 1461 | const fs = require('fs'); 1462 | 1463 | const outputCsv = unparse(allOutput, { 1464 | header: true 1465 | }); 1466 | 1467 | fs.writeFileSync(`${__dirname}/data.csv`, outputCsv); -------------------------------------------------------------------------------- /src/data/country_phone_data.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | alpha2: 'US', 4 | alpha3: 'USA', 5 | country_code: '1', 6 | country_name: 'United States', 7 | mobile_begin_with: ['201', '202', '203', '205', '206', '207', '208', '209', '210', '212', '213', '214', '215', 8 | '216', '217', '218', '219', '220', '223', '224', '225', '227', '228', '229', '231', '234', '239', '240', 9 | '248', '251', '252', '253', '254', '256', '260', '262', '267', '269', '270', '272', '274', '276', '278', 10 | '281', '283', '301', '302', '303', '304', '305', '307', '308', '309', '310', '312', '313', '314', '315', 11 | '316', '317', '318', '319', '320', '321', '323', '325', '327', '329', '330', '331', '332', '334', '336', '337', 12 | '339', '341', '346', '347', '351', '352', '353', '360', '361', '364', '369', '380', '385', '386', '401', '402', 13 | '404', '405', '406', '407', '408', '409', '410', '412', '413', '414', '415', '417', '419', '423', '424', 14 | '425', '430', '432', '434', '435', '440', '441', '442', '443', '445', '447', '458', '463', '464', '469', '470', '472', '475', 15 | '478', '479', '480', '484', '501', '502', '503', '504', '505', '507', '508', '509', '510', '512', '513', 16 | '515', '516', '517', '518', '520', '530', '531', '534', '539', '540', '541', '551', '557', '559', '561', 17 | '562', '563', '564', '567', '570', '571', '572', '573', '574', '575', '580', '582', '585', '586', '601', '602', 18 | '603', '605', '606', '607', '608', '609', '610', '612', '614', '615', '616', '617', '618', '619', '620', 19 | '623', '626', '627', '628', '629', '630', '631', '636', '640', '641', '645', '646', '650', '651', '656', '657', '659', '660', 20 | '661', '662', '667', '669', '678', '679', '680', '681', '682', '689', '701', '702', '703', '704', '706', '707', 21 | '708', '712', '713', '714', '715', '716', '717', '718', '719', '720', '724', '725', '726', '727', '728', '730', '731', 22 | '732', '734', '737', '740', '743', '747', '752', '754', '757', '760', '762', '763', '764', '765', '769', '770', '771', 23 | '772', '773', '774', '775', '779', '781', '785', '786', '787', '801', '802', '803', '804', '805', '806', '808', 24 | '810', '812', '813', '814', '815', '816', '817', '818', '820', '828', '830', '831', '832', '835', '838', '840', '843', '845', 25 | '847', '848', '850', '854', '856', '857', '858', '859', '860', '862', '863', '864', '865', '870', '872', 26 | '878', '901', '903', '904', '906', '907', '908', '909', '910', '912', '913', '914', '915', '916', '917', 27 | '918', '919', '920', '925', '927', '928', '929', '930', '931', '934', '935', '936', '937', '938', '939', '940', '941', '945', 28 | '947', '949', '951', '952', '954', '956', '957', '959', '970', '971', '972', '973', '975', '978', '979', 29 | '980', '984', '985', '986', '989', '888', '800', '833', '844', '855', '866', '877', '279', '340', '983', '448', '943', '363', 30 | '326', '839', '826', '948', '924', '686' 31 | ], 32 | phone_number_lengths: [10] 33 | }, 34 | // https://en.wikipedia.org/wiki/Telephone_numbers_in_Aruba 35 | { 36 | alpha2: 'AW', 37 | alpha3: 'ABW', 38 | country_code: '297', 39 | country_name: 'Aruba', 40 | mobile_begin_with: ['56', '59', '64', '73', '74', '99'], 41 | phone_number_lengths: [7] 42 | }, 43 | { 44 | alpha2: 'AF', 45 | alpha3: 'AFG', 46 | country_code: '93', 47 | country_name: 'Afghanistan', 48 | mobile_begin_with: ['7'], 49 | phone_number_lengths: [9] 50 | }, 51 | { 52 | alpha2: 'AO', 53 | alpha3: 'AGO', 54 | country_code: '244', 55 | country_name: 'Angola', 56 | mobile_begin_with: ['9'], 57 | phone_number_lengths: [9] 58 | }, 59 | { 60 | alpha2: 'AI', 61 | alpha3: 'AIA', 62 | country_code: '1', 63 | country_name: 'Anguilla', 64 | mobile_begin_with: ['2642', '2644', '2645', '2647'], 65 | phone_number_lengths: [10] 66 | }, 67 | { 68 | alpha2: 'AX', 69 | alpha3: 'ALA', 70 | country_code: '358', 71 | country_name: 'Åland Islands', 72 | mobile_begin_with: ['18'], 73 | phone_number_lengths: [6, 7, 8] 74 | }, 75 | { 76 | alpha2: 'AL', 77 | alpha3: 'ALB', 78 | country_code: '355', 79 | country_name: 'Albania', 80 | mobile_begin_with: ['6'], 81 | phone_number_lengths: [9] 82 | }, 83 | { 84 | alpha2: 'AD', 85 | alpha3: 'AND', 86 | country_code: '376', 87 | country_name: 'Andorra', 88 | mobile_begin_with: ['3', '4', '6'], 89 | phone_number_lengths: [6] 90 | }, 91 | // https://en.wikipedia.org/wiki/Telephone_numbers_in_Cura%C3%A7ao_and_the_Caribbean_Netherlands 92 | { 93 | alpha2: "BQ", 94 | alpha3: "BES", 95 | country_code: "599", 96 | country_name: "Caribbean Netherlands", 97 | mobile_begin_with: ['3', '416', '700', '701','795'], 98 | phone_number_lengths: [7] 99 | }, 100 | { 101 | alpha2: 'AE', 102 | alpha3: 'ARE', 103 | country_code: '971', 104 | country_name: 'United Arab Emirates', 105 | mobile_begin_with: ['5'], 106 | phone_number_lengths: [9] 107 | }, 108 | { 109 | alpha2: 'AR', 110 | alpha3: 'ARG', 111 | country_code: '54', 112 | country_name: 'Argentina', 113 | mobile_begin_with: ['1', '2', '3'], // Same for mobile and landlines 114 | phone_number_lengths: [8, 9, 10, 11, 12] 115 | }, 116 | { 117 | alpha2: 'AM', 118 | alpha3: 'ARM', 119 | country_code: '374', 120 | country_name: 'Armenia', 121 | mobile_begin_with: ['3', '4', '5', '7', '9'], 122 | phone_number_lengths: [8] 123 | }, 124 | // http://www.howtocallabroad.com/results.php?callfrom=united_states&callto=american_samoa 125 | { 126 | alpha2: 'AS', 127 | alpha3: 'ASM', 128 | country_code: '1', 129 | country_name: 'American Samoa', 130 | mobile_begin_with: ['684733', '684258'], 131 | phone_number_lengths: [10] 132 | }, 133 | // {alpha2: "AQ", alpha3: "ATA", country_code: "672", country_name: "Antarctica", mobile_begin_with: [], phone_number_lengths: []}, 134 | // {alpha2: "TF", alpha3: "ATF", country_code: "", country_name: "French Southern Territories", mobile_begin_with: [], phone_number_lengths: []}, 135 | // http://www.howtocallabroad.com/results.php?callfrom=united_states&callto=antigua_barbuda 136 | { 137 | alpha2: 'AG', 138 | alpha3: 'ATG', 139 | country_code: '1', 140 | country_name: 'Antigua and Barbuda', 141 | mobile_begin_with: ['2687'], 142 | phone_number_lengths: [10] 143 | }, 144 | { 145 | alpha2: 'AU', 146 | alpha3: 'AUS', 147 | country_code: '61', 148 | country_name: 'Australia', 149 | mobile_begin_with: ['4'], 150 | phone_number_lengths: [9] 151 | }, 152 | { 153 | alpha2: 'AT', 154 | alpha3: 'AUT', 155 | country_code: '43', 156 | country_name: 'Austria', 157 | mobile_begin_with: ['6'], 158 | phone_number_lengths: [10, 11, 12, 13, 14] 159 | }, 160 | { 161 | alpha2: 'AZ', 162 | alpha3: 'AZE', 163 | country_code: '994', 164 | country_name: 'Azerbaijan', 165 | mobile_begin_with: ['10', '50', '51', '55', '60', '70', '77', '99'], 166 | phone_number_lengths: [9] 167 | }, 168 | { 169 | alpha2: 'BI', 170 | alpha3: 'BDI', 171 | country_code: '257', 172 | country_name: 'Burundi', 173 | mobile_begin_with: ['71', '72', '75', '76', '77', '79', '29', '61', '68', '69'], 174 | phone_number_lengths: [8] 175 | }, 176 | { 177 | alpha2: 'BE', 178 | alpha3: 'BEL', 179 | country_code: '32', 180 | country_name: 'Belgium', 181 | mobile_begin_with: ['4', '3'], 182 | phone_number_lengths: [9, 8] 183 | }, 184 | { 185 | alpha2: 'BJ', 186 | alpha3: 'BEN', 187 | country_code: '229', 188 | country_name: 'Benin', 189 | mobile_begin_with: ['4', '6', '9'], 190 | phone_number_lengths: [8] 191 | }, 192 | { 193 | alpha2: 'BF', 194 | alpha3: 'BFA', 195 | country_code: '226', 196 | country_name: 'Burkina Faso', 197 | mobile_begin_with: ['6', '7'], 198 | phone_number_lengths: [8] 199 | }, 200 | { 201 | alpha2: 'BD', 202 | alpha3: 'BGD', 203 | country_code: '880', 204 | country_name: 'Bangladesh', 205 | mobile_begin_with: ['1'], 206 | phone_number_lengths: [8, 9, 10] 207 | }, 208 | { 209 | alpha2: 'BG', 210 | alpha3: 'BGR', 211 | country_code: '359', 212 | country_name: 'Bulgaria', 213 | mobile_begin_with: ['87', '88', '89', '98', '99', '43'], 214 | phone_number_lengths: [8, 9] 215 | }, 216 | { 217 | alpha2: 'BH', 218 | alpha3: 'BHR', 219 | country_code: '973', 220 | country_name: 'Bahrain', 221 | mobile_begin_with: ['3'], 222 | phone_number_lengths: [8] 223 | }, 224 | { 225 | alpha2: 'BS', 226 | alpha3: 'BHS', 227 | country_code: '1', 228 | country_name: 'Bahamas', 229 | mobile_begin_with: ['242'], 230 | phone_number_lengths: [10] 231 | }, 232 | { 233 | alpha2: 'BA', 234 | alpha3: 'BIH', 235 | country_code: '387', 236 | country_name: 'Bosnia and Herzegovina', 237 | mobile_begin_with: ['6'], 238 | phone_number_lengths: [8, 9] 239 | }, 240 | // {alpha2: "BL", alpha3: "BLM", country_code: "590", country_name: "Saint Barthélemy", mobile_begin_with: [], phone_number_lengths: []}, 241 | { 242 | alpha2: 'BY', 243 | alpha3: 'BLR', 244 | country_code: '375', 245 | country_name: 'Belarus', 246 | mobile_begin_with: ['25', '29', '33', '44'], 247 | phone_number_lengths: [9] 248 | }, 249 | { 250 | alpha2: 'BZ', 251 | alpha3: 'BLZ', 252 | country_code: '501', 253 | country_name: 'Belize', 254 | mobile_begin_with: ['6'], 255 | phone_number_lengths: [7] 256 | }, 257 | // http://www.howtocallabroad.com/results.php?callfrom=united_states&callto=bermuda 258 | { 259 | alpha2: 'BM', 260 | alpha3: 'BMU', 261 | country_code: '1', 262 | country_name: 'Bermuda', 263 | mobile_begin_with: ['4413', '4415', '4417'], 264 | phone_number_lengths: [10] 265 | }, 266 | { 267 | alpha2: 'BO', 268 | alpha3: 'BOL', 269 | country_code: '591', 270 | country_name: 'Bolivia', 271 | mobile_begin_with: ['6', '7'], 272 | phone_number_lengths: [8] 273 | }, 274 | { 275 | alpha2: 'BR', 276 | alpha3: 'BRA', 277 | country_code: '55', 278 | country_name: 'Brazil', 279 | mobile_begin_with: [ 280 | '119', '129', '139', '149', '159', '169', '179', '189', '199', '219', '229', '249', '279', '289', 281 | '319', '329', '339', '349', '359', '379', '389', 282 | '419', '429', '439', '449', '459', '469', '479', '489', '499', 283 | '519', '539', '549', '559', 284 | '619', '629', '639', '649', '659', '669', '679', '689', '699', 285 | '719', '739', '749', '759', '779', '799', 286 | '819', '829', '839', '849', '859', '869', '879', '889', '899', 287 | '919', '929', '939', '949', '959', '969', '979', '989', '999', 288 | ], 289 | phone_number_lengths: [10, 11] 290 | }, 291 | { 292 | alpha2: 'BB', 293 | alpha3: 'BRB', 294 | country_code: '1', 295 | country_name: 'Barbados', 296 | mobile_begin_with: ['246'], 297 | phone_number_lengths: [10] 298 | }, 299 | { 300 | alpha2: 'BN', 301 | alpha3: 'BRN', 302 | country_code: '673', 303 | country_name: 'Brunei Darussalam', 304 | mobile_begin_with: ['7', '8'], 305 | phone_number_lengths: [7] 306 | }, 307 | { 308 | alpha2: 'BT', 309 | alpha3: 'BTN', 310 | country_code: '975', 311 | country_name: 'Bhutan', 312 | mobile_begin_with: ['17'], 313 | phone_number_lengths: [8] 314 | }, 315 | // {alpha2: "BV", alpha3: "BVT", country_code: "", country_name: "Bouvet Island", mobile_begin_with: [], phone_number_lengths: []}, 316 | { 317 | alpha2: 'BW', 318 | alpha3: 'BWA', 319 | country_code: '267', 320 | country_name: 'Botswana', 321 | mobile_begin_with: ['71', '72', '73', '74', '75', '76', '77', '78', '79'], 322 | phone_number_lengths: [8] 323 | }, 324 | { 325 | alpha2: 'CF', 326 | alpha3: 'CAF', 327 | country_code: '236', 328 | country_name: 'Central African Republic', 329 | mobile_begin_with: ['7'], 330 | phone_number_lengths: [8] 331 | }, 332 | 333 | // http://www.howtocallabroad.com/canada/ 334 | // http://areacode.org/ 335 | // http://countrycode.org/canada 336 | { 337 | alpha2: 'CA', 338 | alpha3: 'CAN', 339 | country_code: '1', 340 | country_name: 'Canada', 341 | mobile_begin_with: [ 342 | '204', '226', '236', '249', '250', '263', '289', '306', '343', '354', 343 | '365', '367', '368', '403', '416', '418', '431', '437', '438', '450', 344 | '468', '474', '506', '514', '519', '548', '579', '581', '584', '587', 345 | '600', '604', '613', '639', '647', '672', '683', '705', '709', '742', 346 | '753', '778', '780', '782', '807', '819', '825', '867', '873', '902', 347 | '905', '428', '382', '942'], 348 | phone_number_lengths: [10] 349 | }, 350 | // {alpha2: "CC", alpha3: "CCK", country_code: "61", country_name: "Cocos (Keeling) Islands", mobile_begin_with: [], phone_number_lengths: []}, 351 | { 352 | alpha2: 'CH', 353 | alpha3: 'CHE', 354 | country_code: '41', 355 | country_name: 'Switzerland', 356 | mobile_begin_with: ['74', '75', '76', '77', '78', '79'], 357 | phone_number_lengths: [9] 358 | }, 359 | { 360 | alpha2: 'CL', 361 | alpha3: 'CHL', 362 | country_code: '56', 363 | country_name: 'Chile', 364 | mobile_begin_with: ['9'], 365 | phone_number_lengths: [9] 366 | }, 367 | { 368 | alpha2: 'CN', 369 | alpha3: 'CHN', 370 | country_code: '86', 371 | country_name: 'China', 372 | mobile_begin_with: ['13', '14', '15', '17', '18', '19', '16'], 373 | phone_number_lengths: [11] 374 | }, 375 | { 376 | alpha2: 'CI', 377 | alpha3: 'CIV', 378 | country_code: '225', 379 | country_name: "Côte D'Ivoire", 380 | mobile_begin_with: ['0', '4', '5', '6', '7', '8'], 381 | phone_number_lengths: [10] 382 | }, 383 | { 384 | alpha2: 'CM', 385 | alpha3: 'CMR', 386 | country_code: '237', 387 | country_name: 'Cameroon', 388 | mobile_begin_with: ['6'], 389 | phone_number_lengths: [9] 390 | }, 391 | { 392 | alpha2: 'CD', 393 | alpha3: 'COD', 394 | country_code: '243', 395 | country_name: 'Congo, The Democratic Republic Of The', 396 | mobile_begin_with: ['8', '9'], 397 | phone_number_lengths: [9] 398 | }, 399 | { 400 | alpha2: 'CG', 401 | alpha3: 'COG', 402 | country_code: '242', 403 | country_name: 'Congo', 404 | mobile_begin_with: ['0'], 405 | phone_number_lengths: [9] 406 | }, 407 | { 408 | alpha2: 'CK', 409 | alpha3: 'COK', 410 | country_code: '682', 411 | country_name: 'Cook Islands', 412 | mobile_begin_with: ['5', '7'], 413 | phone_number_lengths: [5] 414 | }, 415 | { 416 | alpha2: 'CO', 417 | alpha3: 'COL', 418 | country_code: '57', 419 | country_name: 'Colombia', 420 | mobile_begin_with: ['3'], 421 | phone_number_lengths: [10] 422 | }, 423 | { 424 | alpha2: 'CW', 425 | alpha3: 'CUW', 426 | country_code: '599', 427 | country_name: 'Curaçao', 428 | mobile_begin_with: ['95', '96'], 429 | phone_number_lengths: [8] 430 | }, 431 | { 432 | alpha2: 'KM', 433 | alpha3: 'COM', 434 | country_code: '269', 435 | country_name: 'Comoros', 436 | mobile_begin_with: ['3', '76'], 437 | phone_number_lengths: [7] 438 | }, 439 | { 440 | alpha2: 'CV', 441 | alpha3: 'CPV', 442 | country_code: '238', 443 | country_name: 'Cape Verde', 444 | mobile_begin_with: ['5', '9'], 445 | phone_number_lengths: [7] 446 | }, 447 | { 448 | alpha2: 'CR', 449 | alpha3: 'CRI', 450 | country_code: '506', 451 | country_name: 'Costa Rica', 452 | mobile_begin_with: ['5', '6', '7', '8'], 453 | phone_number_lengths: [8] 454 | }, 455 | { 456 | alpha2: 'CU', 457 | alpha3: 'CUB', 458 | country_code: '53', 459 | country_name: 'Cuba', 460 | mobile_begin_with: ['5', '6'], 461 | phone_number_lengths: [8] 462 | }, 463 | // {alpha2: "CX", alpha3: "CXR", country_code: "61", country_name: "Christmas Island", mobile_begin_with: [], phone_number_lengths: []}, 464 | { 465 | alpha2: 'KY', 466 | alpha3: 'CYM', 467 | country_code: '1', 468 | country_name: 'Cayman Islands', 469 | mobile_begin_with: ['345'], 470 | phone_number_lengths: [10] 471 | }, 472 | { 473 | alpha2: 'CY', 474 | alpha3: 'CYP', 475 | country_code: '357', 476 | country_name: 'Cyprus', 477 | mobile_begin_with: ['9'], 478 | phone_number_lengths: [8] 479 | }, 480 | { 481 | alpha2: 'CZ', 482 | alpha3: 'CZE', 483 | country_code: '420', 484 | country_name: 'Czech Republic', 485 | mobile_begin_with: ['6', '7'], 486 | phone_number_lengths: [9] 487 | }, 488 | { 489 | alpha2: 'DE', 490 | alpha3: 'DEU', 491 | country_code: '49', 492 | country_name: 'Germany', 493 | mobile_begin_with: ['15', '16', '17'], 494 | phone_number_lengths: [10, 11] 495 | }, 496 | { 497 | alpha2: 'DJ', 498 | alpha3: 'DJI', 499 | country_code: '253', 500 | country_name: 'Djibouti', 501 | mobile_begin_with: ['77'], 502 | phone_number_lengths: [8] 503 | }, 504 | { 505 | alpha2: 'DM', 506 | alpha3: 'DMA', 507 | country_code: '1', 508 | country_name: 'Dominica', 509 | mobile_begin_with: ['767'], 510 | phone_number_lengths: [10] 511 | }, 512 | { 513 | alpha2: 'DK', 514 | alpha3: 'DNK', 515 | country_code: '45', 516 | country_name: 'Denmark', 517 | mobile_begin_with: [ 518 | '2', '30', '31', '40', '41', '42', '50', '51', '52', '53', '60', '61', '71', '81', '91', '92', '93', 519 | '342', '344', '345', '346', '347', '348', '349', '356', '357', '359', '362', 520 | '365', '366', '389', '398', '431', '441', '462', '466', '468', '472', '474', 521 | '476', '478', '485', '486', '488', '489', '493', '494', '495', '496', '498', 522 | '499', '542', '543', '545', '551', '552', '556', '571', '572', '573', '574', 523 | '577', '579', '584', '586', '587', '589', '597', '598', '627', '629', '641', 524 | '649', '658', '662', '663', '664', '665', '667', '692', '693', '694', '697', 525 | '771', '772', '782', '783', '785', '786', '788', '789', '826', '827', '829' 526 | ], 527 | phone_number_lengths: [8] 528 | }, 529 | { 530 | alpha2: 'DO', 531 | alpha3: 'DOM', 532 | country_code: '1', 533 | country_name: 'Dominican Republic', 534 | mobile_begin_with: ['809', '829', '849'], 535 | phone_number_lengths: [10] 536 | }, 537 | { 538 | alpha2: 'DZ', 539 | alpha3: 'DZA', 540 | country_code: '213', 541 | country_name: 'Algeria', 542 | mobile_begin_with: ['5', '6', '7'], 543 | phone_number_lengths: [9] 544 | }, 545 | { 546 | alpha2: 'EC', 547 | alpha3: 'ECU', 548 | country_code: '593', 549 | country_name: 'Ecuador', 550 | mobile_begin_with: ['9'], 551 | phone_number_lengths: [9] 552 | }, 553 | { 554 | alpha2: 'EG', 555 | alpha3: 'EGY', 556 | country_code: '20', 557 | country_name: 'Egypt', 558 | mobile_begin_with: ['1'], 559 | phone_number_lengths: [10, 8] 560 | }, 561 | { 562 | alpha2: 'ER', 563 | alpha3: 'ERI', 564 | country_code: '291', 565 | country_name: 'Eritrea', 566 | mobile_begin_with: ['1', '7', '8'], 567 | phone_number_lengths: [7] 568 | }, 569 | // {alpha2: "EH", alpha3: "ESH", country_code: "212", country_name: "Western Sahara", mobile_begin_with: [], phone_number_lengths: []}, 570 | { 571 | alpha2: 'ES', 572 | alpha3: 'ESP', 573 | country_code: '34', 574 | country_name: 'Spain', 575 | mobile_begin_with: ['6', '7'], 576 | phone_number_lengths: [9] 577 | }, 578 | { 579 | alpha2: 'EE', 580 | alpha3: 'EST', 581 | country_code: '372', 582 | country_name: 'Estonia', 583 | mobile_begin_with: ['5', '81', '82', '83'], 584 | phone_number_lengths: [7, 8] 585 | }, 586 | { 587 | alpha2: 'ET', 588 | alpha3: 'ETH', 589 | country_code: '251', 590 | country_name: 'Ethiopia', 591 | mobile_begin_with: ['7','9'], 592 | phone_number_lengths: [9] 593 | }, 594 | { 595 | alpha2: 'FI', 596 | alpha3: 'FIN', 597 | country_code: '358', 598 | country_name: 'Finland', 599 | mobile_begin_with: ['4', '5'], 600 | phone_number_lengths: [6, 7, 9, 10] 601 | }, 602 | { 603 | alpha2: 'FJ', 604 | alpha3: 'FJI', 605 | country_code: '679', 606 | country_name: 'Fiji', 607 | mobile_begin_with: ['2', '7', '8', '9'], 608 | phone_number_lengths: [7] 609 | }, 610 | { 611 | alpha2: 'FK', 612 | alpha3: 'FLK', 613 | country_code: '500', 614 | country_name: 'Falkland Islands (Malvinas)', 615 | mobile_begin_with: ['5', '6'], 616 | phone_number_lengths: [5] 617 | }, 618 | { 619 | alpha2: 'FR', 620 | alpha3: 'FRA', 621 | country_code: '33', 622 | country_name: 'France', 623 | mobile_begin_with: ['6', '7'], 624 | phone_number_lengths: [9] 625 | }, 626 | { 627 | alpha2: 'FO', 628 | alpha3: 'FRO', 629 | country_code: '298', 630 | country_name: 'Faroe Islands', 631 | mobile_begin_with: [], 632 | phone_number_lengths: [6] 633 | }, 634 | { 635 | alpha2: 'FM', 636 | alpha3: 'FSM', 637 | country_code: '691', 638 | country_name: 'Micronesia, Federated States Of', 639 | mobile_begin_with: [], 640 | phone_number_lengths: [7] 641 | }, 642 | { 643 | alpha2: 'GA', 644 | alpha3: 'GAB', 645 | country_code: '241', 646 | country_name: 'Gabon', 647 | mobile_begin_with: ['2', '3', '4', '5', '6', '7'], 648 | phone_number_lengths: [7] 649 | }, 650 | { 651 | alpha2: 'GB', 652 | alpha3: 'GBR', 653 | country_code: '44', 654 | country_name: 'United Kingdom', 655 | mobile_begin_with: ['7'], 656 | phone_number_lengths: [10] 657 | }, 658 | { 659 | alpha2: 'GE', 660 | alpha3: 'GEO', 661 | country_code: '995', 662 | country_name: 'Georgia', 663 | mobile_begin_with: ['5', '7'], 664 | phone_number_lengths: [9] 665 | }, 666 | // {alpha2: "GG", alpha3: "GGY", country_code: "44", country_name: "Guernsey", mobile_begin_with: [], phone_number_lengths: []}, 667 | { 668 | alpha2: 'GH', 669 | alpha3: 'GHA', 670 | country_code: '233', 671 | country_name: 'Ghana', 672 | mobile_begin_with: ['2', '5'], 673 | phone_number_lengths: [9] 674 | }, 675 | { 676 | alpha2: 'GI', 677 | alpha3: 'GIB', 678 | country_code: '350', 679 | country_name: 'Gibraltar', 680 | mobile_begin_with: ['5'], 681 | phone_number_lengths: [8] 682 | }, 683 | { 684 | alpha2: 'GN', 685 | alpha3: 'GIN', 686 | country_code: '224', 687 | country_name: 'Guinea', 688 | mobile_begin_with: ['6'], 689 | phone_number_lengths: [9] 690 | }, 691 | { 692 | alpha2: 'GP', 693 | alpha3: 'GLP', 694 | country_code: '590', 695 | country_name: 'Guadeloupe', 696 | mobile_begin_with: ['690', '691'], 697 | phone_number_lengths: [9] 698 | }, 699 | { 700 | alpha2: 'GM', 701 | alpha3: 'GMB', 702 | country_code: '220', 703 | country_name: 'Gambia', 704 | mobile_begin_with: ['7', '9'], 705 | phone_number_lengths: [7] 706 | }, 707 | { 708 | alpha2: 'GW', 709 | alpha3: 'GNB', 710 | country_code: '245', 711 | country_name: 'Guinea-Bissau', 712 | mobile_begin_with: ['5', '6', '7'], 713 | phone_number_lengths: [7] 714 | }, 715 | { 716 | alpha2: 'GQ', 717 | alpha3: 'GNQ', 718 | country_code: '240', 719 | country_name: 'Equatorial Guinea', 720 | mobile_begin_with: ['222', '551'], 721 | phone_number_lengths: [9] 722 | }, 723 | { 724 | alpha2: 'GR', 725 | alpha3: 'GRC', 726 | country_code: '30', 727 | country_name: 'Greece', 728 | mobile_begin_with: ['6'], 729 | phone_number_lengths: [10] 730 | }, 731 | { 732 | alpha2: 'GD', 733 | alpha3: 'GRD', 734 | country_code: '1', 735 | country_name: 'Grenada', 736 | mobile_begin_with: ['473'], 737 | phone_number_lengths: [10] 738 | }, 739 | { 740 | alpha2: 'GL', 741 | alpha3: 'GRL', 742 | country_code: '299', 743 | country_name: 'Greenland', 744 | mobile_begin_with: ['2', '4', '5'], 745 | phone_number_lengths: [6] 746 | }, 747 | { 748 | alpha2: 'GT', 749 | alpha3: 'GTM', 750 | country_code: '502', 751 | country_name: 'Guatemala', 752 | mobile_begin_with: ['3', '4', '5'], 753 | phone_number_lengths: [8] 754 | }, 755 | { 756 | alpha2: 'GF', 757 | alpha3: 'GUF', 758 | country_code: '594', 759 | country_name: 'French Guiana', 760 | mobile_begin_with: ['694'], 761 | phone_number_lengths: [9] 762 | }, 763 | { 764 | alpha2: 'GU', 765 | alpha3: 'GUM', 766 | country_code: '1', 767 | country_name: 'Guam', 768 | mobile_begin_with: ['671'], 769 | phone_number_lengths: [10] 770 | }, 771 | { 772 | alpha2: 'GY', 773 | alpha3: 'GUY', 774 | country_code: '592', 775 | country_name: 'Guyana', 776 | mobile_begin_with: ['6'], 777 | phone_number_lengths: [7] 778 | }, 779 | { 780 | alpha2: 'HK', 781 | alpha3: 'HKG', 782 | country_code: '852', 783 | country_name: 'Hong Kong', 784 | mobile_begin_with: ['4', '5', '6', '70', '71', '72', '73', '81', '82', '83', '84', '85', '86', '87', '88', '89', '9'], 785 | phone_number_lengths: [8] 786 | }, 787 | // {alpha2: "HM", alpha3: "HMD", country_code: "", country_name: "Heard and McDonald Islands", mobile_begin_with: [], phone_number_lengths: []}, 788 | { 789 | alpha2: 'HN', 790 | alpha3: 'HND', 791 | country_code: '504', 792 | country_name: 'Honduras', 793 | mobile_begin_with: ['3', '7', '8', '9'], 794 | phone_number_lengths: [8] 795 | }, 796 | { 797 | alpha2: 'HR', 798 | alpha3: 'HRV', 799 | country_code: '385', 800 | country_name: 'Croatia', 801 | mobile_begin_with: ['9'], 802 | phone_number_lengths: [8, 9] 803 | }, 804 | { 805 | alpha2: 'HT', 806 | alpha3: 'HTI', 807 | country_code: '509', 808 | country_name: 'Haiti', 809 | mobile_begin_with: ['3', '4'], 810 | phone_number_lengths: [8] 811 | }, 812 | { 813 | alpha2: 'HU', 814 | alpha3: 'HUN', 815 | country_code: '36', 816 | country_name: 'Hungary', 817 | mobile_begin_with: ['20', '30', '31', '50', '70'], 818 | phone_number_lengths: [9] 819 | }, 820 | { 821 | alpha2: 'ID', 822 | alpha3: 'IDN', 823 | country_code: '62', 824 | country_name: 'Indonesia', 825 | mobile_begin_with: ['8'], 826 | phone_number_lengths: [9, 10, 11, 12] 827 | }, 828 | // {alpha2: "IM", alpha3: "IMN", country_code: "44", country_name: "Isle of Man", mobile_begin_with: [], phone_number_lengths: []}, 829 | { 830 | alpha2: 'IN', 831 | alpha3: 'IND', 832 | country_code: '91', 833 | country_name: 'India', 834 | mobile_begin_with: ['6', '7', '8', '9'], 835 | phone_number_lengths: [10] 836 | }, 837 | // {alpha2: "IO", alpha3: "IOT", country_code: "246", country_name: "British Indian Ocean Territory", mobile_begin_with: [], phone_number_lengths: []}, 838 | { 839 | alpha2: 'IE', 840 | alpha3: 'IRL', 841 | country_code: '353', 842 | country_name: 'Ireland', 843 | mobile_begin_with: ['82', '83', '84', '85', '86', '87', '88', '89'], 844 | phone_number_lengths: [9] 845 | }, 846 | { 847 | alpha2: 'IR', 848 | alpha3: 'IRN', 849 | country_code: '98', 850 | country_name: 'Iran, Islamic Republic Of', 851 | mobile_begin_with: ['9'], 852 | phone_number_lengths: [10] 853 | }, 854 | { 855 | alpha2: 'IQ', 856 | alpha3: 'IRQ', 857 | country_code: '964', 858 | country_name: 'Iraq', 859 | mobile_begin_with: ['7'], 860 | phone_number_lengths: [10] 861 | }, 862 | { 863 | alpha2: 'IS', 864 | alpha3: 'ISL', 865 | country_code: '354', 866 | country_name: 'Iceland', 867 | mobile_begin_with: ['6', '7', '8'], 868 | phone_number_lengths: [7] 869 | }, 870 | { 871 | alpha2: 'IL', 872 | alpha3: 'ISR', 873 | country_code: '972', 874 | country_name: 'Israel', 875 | mobile_begin_with: ['5'], 876 | phone_number_lengths: [9] 877 | }, 878 | { 879 | alpha2: 'IT', 880 | alpha3: 'ITA', 881 | country_code: '39', 882 | country_name: 'Italy', 883 | mobile_begin_with: ['3'], 884 | phone_number_lengths: [9, 10] 885 | }, 886 | { 887 | alpha2: 'JM', 888 | alpha3: 'JAM', 889 | country_code: '1', 890 | country_name: 'Jamaica', 891 | mobile_begin_with: ['876'], 892 | phone_number_lengths: [10] 893 | }, 894 | // {alpha2: "JE", alpha3: "JEY", country_code: "44", country_name: "Jersey", mobile_begin_with: [], phone_number_lengths: []}, 895 | { 896 | alpha2: 'JO', 897 | alpha3: 'JOR', 898 | country_code: '962', 899 | country_name: 'Jordan', 900 | mobile_begin_with: ['7'], 901 | phone_number_lengths: [9] 902 | }, 903 | { 904 | alpha2: 'JP', 905 | alpha3: 'JPN', 906 | country_code: '81', 907 | country_name: 'Japan', 908 | mobile_begin_with: ['70', '80', '90'], 909 | phone_number_lengths: [10] 910 | }, 911 | { 912 | alpha2: 'KZ', 913 | alpha3: 'KAZ', 914 | country_code: '7', 915 | country_name: 'Kazakhstan', 916 | mobile_begin_with: ['70', '74', '77'], 917 | phone_number_lengths: [10] 918 | }, 919 | { 920 | alpha2: 'KE', 921 | alpha3: 'KEN', 922 | country_code: '254', 923 | country_name: 'Kenya', 924 | mobile_begin_with: ['7', '1'], 925 | phone_number_lengths: [9] 926 | }, 927 | { 928 | alpha2: 'KG', 929 | alpha3: 'KGZ', 930 | country_code: '996', 931 | country_name: 'Kyrgyzstan', 932 | mobile_begin_with: ['20', '22', '31258', '312973', '5', '600', '7', '88', '912', '99'], 933 | phone_number_lengths: [9] 934 | }, 935 | { 936 | alpha2: 'KH', 937 | alpha3: 'KHM', 938 | country_code: '855', 939 | country_name: 'Cambodia', 940 | mobile_begin_with: ['1', '6', '7', '8', '9'], 941 | phone_number_lengths: [8, 9] 942 | }, 943 | { 944 | alpha2: 'KI', 945 | alpha3: 'KIR', 946 | country_code: '686', 947 | country_name: 'Kiribati', 948 | mobile_begin_with: ['9', '30'], 949 | phone_number_lengths: [5] 950 | }, 951 | { 952 | alpha2: 'KN', 953 | alpha3: 'KNA', 954 | country_code: '1', 955 | country_name: 'Saint Kitts And Nevis', 956 | mobile_begin_with: ['869'], 957 | phone_number_lengths: [10] 958 | }, 959 | { 960 | alpha2: 'KR', 961 | alpha3: 'KOR', 962 | country_code: '82', 963 | country_name: 'Korea, Republic of', 964 | mobile_begin_with: ['1'], 965 | phone_number_lengths: [9, 10] 966 | }, 967 | // https://www.howtocallabroad.com/kosovo/ 968 | // https://en.wikipedia.org/wiki/Telephone_numbers_in_Kosovo 969 | { 970 | alpha2: "XK", 971 | alpha3: "XKX", 972 | country_code: "383", 973 | country_name: "Kosovo, Republic of", 974 | mobile_begin_with: ["43", "44", "45", "46", "47", "48", "49"], 975 | phone_number_lengths: [8], 976 | }, 977 | { 978 | alpha2: 'KW', 979 | alpha3: 'KWT', 980 | country_code: '965', 981 | country_name: 'Kuwait', 982 | mobile_begin_with: ['5', '6', '9'], 983 | phone_number_lengths: [8] 984 | }, 985 | { 986 | alpha2: 'LA', 987 | alpha3: 'LAO', 988 | country_code: '856', 989 | country_name: "Lao People's Democratic Republic", 990 | mobile_begin_with: ['20'], 991 | phone_number_lengths: [10] 992 | }, 993 | { 994 | alpha2: 'LB', 995 | alpha3: 'LBN', 996 | country_code: '961', 997 | country_name: 'Lebanon', 998 | mobile_begin_with: ['3', '7', '8'], 999 | phone_number_lengths: [7, 8] 1000 | }, 1001 | { 1002 | alpha2: 'LR', 1003 | alpha3: 'LBR', 1004 | country_code: '231', 1005 | country_name: 'Liberia', 1006 | mobile_begin_with: ['4', '5', '6', '7'], 1007 | phone_number_lengths: [7, 8] 1008 | }, 1009 | { 1010 | alpha2: 'LY', 1011 | alpha3: 'LBY', 1012 | country_code: '218', 1013 | country_name: 'Libyan Arab Jamahiriya', 1014 | mobile_begin_with: ['9'], 1015 | phone_number_lengths: [9] 1016 | }, 1017 | { 1018 | alpha2: 'LC', 1019 | alpha3: 'LCA', 1020 | country_code: '1', 1021 | country_name: 'Saint Lucia', 1022 | mobile_begin_with: ['758'], 1023 | phone_number_lengths: [10] 1024 | }, 1025 | { 1026 | alpha2: 'LI', 1027 | alpha3: 'LIE', 1028 | country_code: '423', 1029 | country_name: 'Liechtenstein', 1030 | mobile_begin_with: ['7'], 1031 | phone_number_lengths: [7] 1032 | }, 1033 | { 1034 | alpha2: 'LK', 1035 | alpha3: 'LKA', 1036 | country_code: '94', 1037 | country_name: 'Sri Lanka', 1038 | mobile_begin_with: ['7'], 1039 | phone_number_lengths: [9] 1040 | }, 1041 | { 1042 | alpha2: 'LS', 1043 | alpha3: 'LSO', 1044 | country_code: '266', 1045 | country_name: 'Lesotho', 1046 | mobile_begin_with: ['5', '6'], 1047 | phone_number_lengths: [8] 1048 | }, 1049 | { 1050 | alpha2: 'LT', 1051 | alpha3: 'LTU', 1052 | country_code: '370', 1053 | country_name: 'Lithuania', 1054 | mobile_begin_with: ['6'], 1055 | phone_number_lengths: [8] 1056 | }, 1057 | { 1058 | alpha2: 'LU', 1059 | alpha3: 'LUX', 1060 | country_code: '352', 1061 | country_name: 'Luxembourg', 1062 | mobile_begin_with: ['6'], 1063 | phone_number_lengths: [9] 1064 | }, 1065 | { 1066 | alpha2: 'LV', 1067 | alpha3: 'LVA', 1068 | country_code: '371', 1069 | country_name: 'Latvia', 1070 | mobile_begin_with: ['2'], 1071 | phone_number_lengths: [8] 1072 | }, 1073 | { 1074 | alpha2: 'MO', 1075 | alpha3: 'MAC', 1076 | country_code: '853', 1077 | country_name: 'Macao', 1078 | mobile_begin_with: ['6'], 1079 | phone_number_lengths: [8] 1080 | }, 1081 | // {alpha2: "MF", alpha3: "MAF", country_code: "590", country_name: "Saint Martin", mobile_begin_with: [], phone_number_lengths: []}, 1082 | { 1083 | alpha2: 'MA', 1084 | alpha3: 'MAR', 1085 | country_code: '212', 1086 | country_name: 'Morocco', 1087 | mobile_begin_with: ['6', '7'], 1088 | phone_number_lengths: [9] 1089 | }, 1090 | { 1091 | alpha2: 'MC', 1092 | alpha3: 'MCO', 1093 | country_code: '377', 1094 | country_name: 'Monaco', 1095 | mobile_begin_with: ['4', '6'], 1096 | phone_number_lengths: [8, 9] 1097 | }, 1098 | { 1099 | alpha2: 'MD', 1100 | alpha3: 'MDA', 1101 | country_code: '373', 1102 | country_name: 'Moldova, Republic of', 1103 | mobile_begin_with: ['6', '7'], 1104 | phone_number_lengths: [8] 1105 | }, 1106 | { 1107 | alpha2: 'MG', 1108 | alpha3: 'MDG', 1109 | country_code: '261', 1110 | country_name: 'Madagascar', 1111 | mobile_begin_with: ['3'], 1112 | phone_number_lengths: [9] 1113 | }, 1114 | { 1115 | alpha2: 'MV', 1116 | alpha3: 'MDV', 1117 | country_code: '960', 1118 | country_name: 'Maldives', 1119 | mobile_begin_with: ['7', '9'], 1120 | phone_number_lengths: [7] 1121 | }, 1122 | { 1123 | alpha2: 'MX', 1124 | alpha3: 'MEX', 1125 | country_code: '52', 1126 | country_name: 'Mexico', 1127 | mobile_begin_with: [''], 1128 | phone_number_lengths: [10, 11] 1129 | }, 1130 | { 1131 | alpha2: 'MH', 1132 | alpha3: 'MHL', 1133 | country_code: '692', 1134 | country_name: 'Marshall Islands', 1135 | mobile_begin_with: [], 1136 | phone_number_lengths: [7] 1137 | }, 1138 | { 1139 | alpha2: 'MK', 1140 | alpha3: 'MKD', 1141 | country_code: '389', 1142 | country_name: 'Macedonia, the Former Yugoslav Republic Of', 1143 | mobile_begin_with: ['7'], 1144 | phone_number_lengths: [8] 1145 | }, 1146 | { 1147 | alpha2: 'ML', 1148 | alpha3: 'MLI', 1149 | country_code: '223', 1150 | country_name: 'Mali', 1151 | mobile_begin_with: ['6', '7'], 1152 | phone_number_lengths: [8] 1153 | }, 1154 | { 1155 | alpha2: 'MT', 1156 | alpha3: 'MLT', 1157 | country_code: '356', 1158 | country_name: 'Malta', 1159 | mobile_begin_with: ['7', '9'], 1160 | phone_number_lengths: [8] 1161 | }, 1162 | { 1163 | alpha2: 'MM', 1164 | alpha3: 'MMR', 1165 | country_code: '95', 1166 | country_name: 'Myanmar', 1167 | mobile_begin_with: ['9'], 1168 | phone_number_lengths: [8, 9, 10] 1169 | }, 1170 | { 1171 | alpha2: 'ME', 1172 | alpha3: 'MNE', 1173 | country_code: '382', 1174 | country_name: 'Montenegro', 1175 | mobile_begin_with: ['6'], 1176 | phone_number_lengths: [8] 1177 | }, 1178 | { 1179 | alpha2: 'MN', 1180 | alpha3: 'MNG', 1181 | country_code: '976', 1182 | country_name: 'Mongolia', 1183 | mobile_begin_with: ['5', '8', '9'], 1184 | phone_number_lengths: [8] 1185 | }, 1186 | { 1187 | alpha2: 'MP', 1188 | alpha3: 'MNP', 1189 | country_code: '1', 1190 | country_name: 'Northern Mariana Islands', 1191 | mobile_begin_with: ['670'], 1192 | phone_number_lengths: [10] 1193 | }, 1194 | { 1195 | alpha2: 'MZ', 1196 | alpha3: 'MOZ', 1197 | country_code: '258', 1198 | country_name: 'Mozambique', 1199 | mobile_begin_with: ['8'], 1200 | phone_number_lengths: [9] 1201 | }, 1202 | { 1203 | alpha2: 'MR', 1204 | alpha3: 'MRT', 1205 | country_code: '222', 1206 | country_name: 'Mauritania', 1207 | mobile_begin_with: [], 1208 | phone_number_lengths: [8] 1209 | }, 1210 | { 1211 | alpha2: 'MS', 1212 | alpha3: 'MSR', 1213 | country_code: '1', 1214 | country_name: 'Montserrat', 1215 | mobile_begin_with: ['664'], 1216 | phone_number_lengths: [10] 1217 | }, 1218 | { 1219 | alpha2: 'MQ', 1220 | alpha3: 'MTQ', 1221 | country_code: '596', 1222 | country_name: 'Martinique', 1223 | mobile_begin_with: ['696', '697'], 1224 | phone_number_lengths: [9] 1225 | }, 1226 | { 1227 | alpha2: 'MU', 1228 | alpha3: 'MUS', 1229 | country_code: '230', 1230 | country_name: 'Mauritius', 1231 | mobile_begin_with: ['5'], 1232 | phone_number_lengths: [8] 1233 | }, 1234 | { 1235 | alpha2: 'MW', 1236 | alpha3: 'MWI', 1237 | country_code: '265', 1238 | country_name: 'Malawi', 1239 | mobile_begin_with: ['77', '88', '99'], 1240 | phone_number_lengths: [9] 1241 | }, 1242 | { 1243 | alpha2: 'MY', 1244 | alpha3: 'MYS', 1245 | country_code: '60', 1246 | country_name: 'Malaysia', 1247 | mobile_begin_with: ['1', '6'], 1248 | phone_number_lengths: [9, 10, 8] 1249 | }, 1250 | { 1251 | alpha2: 'YT', 1252 | alpha3: 'MYT', 1253 | country_code: '262', 1254 | country_name: 'Mayotte', 1255 | mobile_begin_with: ['639'], 1256 | phone_number_lengths: [9] 1257 | }, 1258 | { 1259 | alpha2: 'NA', 1260 | alpha3: 'NAM', 1261 | country_code: '264', 1262 | country_name: 'Namibia', 1263 | mobile_begin_with: ['60', '81', '82', '85'], 1264 | phone_number_lengths: [9] 1265 | }, 1266 | { 1267 | alpha2: 'NC', 1268 | alpha3: 'NCL', 1269 | country_code: '687', 1270 | country_name: 'New Caledonia', 1271 | mobile_begin_with: ['5', '7', '8', '9'], 1272 | phone_number_lengths: [6] 1273 | }, 1274 | { 1275 | alpha2: 'NE', 1276 | alpha3: 'NER', 1277 | country_code: '227', 1278 | country_name: 'Niger', 1279 | mobile_begin_with: ['9'], 1280 | phone_number_lengths: [8] 1281 | }, 1282 | { 1283 | alpha2: 'NF', 1284 | alpha3: 'NFK', 1285 | country_code: '672', 1286 | country_name: 'Norfolk Island', 1287 | mobile_begin_with: ['5', '8'], 1288 | phone_number_lengths: [5] 1289 | }, 1290 | { 1291 | alpha2: 'NG', 1292 | alpha3: 'NGA', 1293 | country_code: '234', 1294 | country_name: 'Nigeria', 1295 | mobile_begin_with: ['70', '80', '81', '90', '91'], 1296 | phone_number_lengths: [10] 1297 | }, 1298 | { 1299 | alpha2: 'NI', 1300 | alpha3: 'NIC', 1301 | country_code: '505', 1302 | country_name: 'Nicaragua', 1303 | mobile_begin_with: ['7', '8'], 1304 | phone_number_lengths: [8] 1305 | }, 1306 | { 1307 | alpha2: 'NU', 1308 | alpha3: 'NIU', 1309 | country_code: '683', 1310 | country_name: 'Niue', 1311 | mobile_begin_with: [], 1312 | phone_number_lengths: [4] 1313 | }, 1314 | { 1315 | alpha2: 'NL', 1316 | alpha3: 'NLD', 1317 | country_code: '31', 1318 | country_name: 'Netherlands', 1319 | mobile_begin_with: ['6', '97'], 1320 | phone_number_lengths: [9, 11] 1321 | }, 1322 | { 1323 | alpha2: 'NO', 1324 | alpha3: 'NOR', 1325 | country_code: '47', 1326 | country_name: 'Norway', 1327 | mobile_begin_with: ['4', '9'], 1328 | phone_number_lengths: [8] 1329 | }, 1330 | { 1331 | alpha2: 'NP', 1332 | alpha3: 'NPL', 1333 | country_code: '977', 1334 | country_name: 'Nepal', 1335 | mobile_begin_with: ['97', '98'], 1336 | phone_number_lengths: [10] 1337 | }, 1338 | { 1339 | alpha2: 'NR', 1340 | alpha3: 'NRU', 1341 | country_code: '674', 1342 | country_name: 'Nauru', 1343 | mobile_begin_with: ['555'], 1344 | phone_number_lengths: [7] 1345 | }, 1346 | { 1347 | alpha2: 'NZ', 1348 | alpha3: 'NZL', 1349 | country_code: '64', 1350 | country_name: 'New Zealand', 1351 | mobile_begin_with: ['2'], 1352 | phone_number_lengths: [8, 9, 10] 1353 | }, 1354 | { 1355 | alpha2: 'OM', 1356 | alpha3: 'OMN', 1357 | country_code: '968', 1358 | country_name: 'Oman', 1359 | mobile_begin_with: ['7', '9'], 1360 | phone_number_lengths: [8] 1361 | }, 1362 | { 1363 | alpha2: 'PK', 1364 | alpha3: 'PAK', 1365 | country_code: '92', 1366 | country_name: 'Pakistan', 1367 | mobile_begin_with: ['3'], 1368 | phone_number_lengths: [10] 1369 | }, 1370 | { 1371 | alpha2: 'PA', 1372 | alpha3: 'PAN', 1373 | country_code: '507', 1374 | country_name: 'Panama', 1375 | mobile_begin_with: ['6'], 1376 | phone_number_lengths: [8] 1377 | }, 1378 | // {alpha2: "PN", alpha3: "PCN", country_code: "", country_name: "Pitcairn", mobile_begin_with: [], phone_number_lengths: []}, 1379 | { 1380 | alpha2: 'PE', 1381 | alpha3: 'PER', 1382 | country_code: '51', 1383 | country_name: 'Peru', 1384 | mobile_begin_with: ['9'], 1385 | phone_number_lengths: [9] 1386 | }, 1387 | { 1388 | alpha2: 'PH', 1389 | alpha3: 'PHL', 1390 | country_code: '63', 1391 | country_name: 'Philippines', 1392 | mobile_begin_with: ['9'], 1393 | phone_number_lengths: [10] 1394 | }, 1395 | { 1396 | alpha2: 'PW', 1397 | alpha3: 'PLW', 1398 | country_code: '680', 1399 | country_name: 'Palau', 1400 | mobile_begin_with: [], 1401 | phone_number_lengths: [7] 1402 | }, 1403 | { 1404 | alpha2: 'PG', 1405 | alpha3: 'PNG', 1406 | country_code: '675', 1407 | country_name: 'Papua New Guinea', 1408 | mobile_begin_with: ['7'], 1409 | phone_number_lengths: [8] 1410 | }, 1411 | { 1412 | alpha2: 'PL', 1413 | alpha3: 'POL', 1414 | country_code: '48', 1415 | country_name: 'Poland', 1416 | mobile_begin_with: ['4', '5', '6', '7', '8'], 1417 | phone_number_lengths: [9] 1418 | }, 1419 | { 1420 | alpha2: 'PR', 1421 | alpha3: 'PRI', 1422 | country_code: '1', 1423 | country_name: 'Puerto Rico', 1424 | mobile_begin_with: ['787', '939'], 1425 | phone_number_lengths: [10] 1426 | }, 1427 | // {alpha2: "KP", alpha3: "PRK", country_code: "850", country_name: "Korea, Democratic People's Republic Of", mobile_begin_with: [], phone_number_lengths: []}, 1428 | { 1429 | alpha2: 'PT', 1430 | alpha3: 'PRT', 1431 | country_code: '351', 1432 | country_name: 'Portugal', 1433 | mobile_begin_with: ['9'], 1434 | phone_number_lengths: [9] 1435 | }, 1436 | { 1437 | alpha2: 'PY', 1438 | alpha3: 'PRY', 1439 | country_code: '595', 1440 | country_name: 'Paraguay', 1441 | mobile_begin_with: ['9'], 1442 | phone_number_lengths: [9] 1443 | }, 1444 | { 1445 | alpha2: 'PS', 1446 | alpha3: 'PSE', 1447 | country_code: '970', 1448 | country_name: 'Palestinian Territory, Occupied', 1449 | mobile_begin_with: ['5'], 1450 | phone_number_lengths: [9] 1451 | }, 1452 | { 1453 | alpha2: 'PF', 1454 | alpha3: 'PYF', 1455 | country_code: '689', 1456 | country_name: 'French Polynesia', 1457 | mobile_begin_with: ['8'], 1458 | phone_number_lengths: [8] 1459 | }, 1460 | { 1461 | alpha2: 'QA', 1462 | alpha3: 'QAT', 1463 | country_code: '974', 1464 | country_name: 'Qatar', 1465 | mobile_begin_with: ['3', '5', '6', '7'], 1466 | phone_number_lengths: [8] 1467 | }, 1468 | { 1469 | alpha2: 'RE', 1470 | alpha3: 'REU', 1471 | country_code: '262', 1472 | country_name: 'Réunion', 1473 | mobile_begin_with: ['692', '693'], 1474 | phone_number_lengths: [9] 1475 | }, 1476 | { 1477 | alpha2: 'RO', 1478 | alpha3: 'ROU', 1479 | country_code: '40', 1480 | country_name: 'Romania', 1481 | mobile_begin_with: ['7'], 1482 | phone_number_lengths: [9] 1483 | }, 1484 | { 1485 | alpha2: 'RU', 1486 | alpha3: 'RUS', 1487 | country_code: '7', 1488 | country_name: 'Russian Federation', 1489 | mobile_begin_with: ['9', '495', '498', '499', '835'], 1490 | phone_number_lengths: [10] 1491 | }, 1492 | { 1493 | alpha2: 'RW', 1494 | alpha3: 'RWA', 1495 | country_code: '250', 1496 | country_name: 'Rwanda', 1497 | mobile_begin_with: ['7'], 1498 | phone_number_lengths: [9] 1499 | }, 1500 | { 1501 | alpha2: 'SA', 1502 | alpha3: 'SAU', 1503 | country_code: '966', 1504 | country_name: 'Saudi Arabia', 1505 | mobile_begin_with: ['5'], 1506 | phone_number_lengths: [9] 1507 | }, 1508 | { 1509 | alpha2: 'SD', 1510 | alpha3: 'SDN', 1511 | country_code: '249', 1512 | country_name: 'Sudan', 1513 | mobile_begin_with: ['9'], 1514 | phone_number_lengths: [9] 1515 | }, 1516 | { 1517 | alpha2: 'SS', 1518 | alpha3: 'SSD', 1519 | country_code: '211', 1520 | country_name: 'South Sudan', 1521 | mobile_begin_with: ['9'], 1522 | phone_number_lengths: [9] 1523 | }, 1524 | { 1525 | alpha2: 'SN', 1526 | alpha3: 'SEN', 1527 | country_code: '221', 1528 | country_name: 'Senegal', 1529 | mobile_begin_with: ['7'], 1530 | phone_number_lengths: [9] 1531 | }, 1532 | { 1533 | alpha2: 'SG', 1534 | alpha3: 'SGP', 1535 | country_code: '65', 1536 | country_name: 'Singapore', 1537 | mobile_begin_with: ['8', '9'], 1538 | phone_number_lengths: [8] 1539 | }, 1540 | // {alpha2: "GS", alpha3: "SGS", country_code: "500", country_name: "South Georgia and the South Sandwich Islands", mobile_begin_with: [], phone_number_lengths: []}, 1541 | { 1542 | alpha2: 'SH', 1543 | alpha3: 'SHN', 1544 | country_code: '290', 1545 | country_name: 'Saint Helena', 1546 | mobile_begin_with: [], 1547 | phone_number_lengths: [4] 1548 | }, 1549 | { 1550 | alpha2: 'SJ', 1551 | alpha3: 'SJM', 1552 | country_code: '47', 1553 | country_name: 'Svalbard And Jan Mayen', 1554 | mobile_begin_with: ['79'], 1555 | phone_number_lengths: [8] 1556 | }, 1557 | { 1558 | alpha2: 'SB', 1559 | alpha3: 'SLB', 1560 | country_code: '677', 1561 | country_name: 'Solomon Islands', 1562 | mobile_begin_with: ['7', '8'], 1563 | phone_number_lengths: [7] 1564 | }, 1565 | { 1566 | alpha2: 'SL', 1567 | alpha3: 'SLE', 1568 | country_code: '232', 1569 | country_name: 'Sierra Leone', 1570 | mobile_begin_with: ['21', '25', '30', '33', '34', '40', '44', '50', '55', '76', '77', '78', '79', '88'], 1571 | phone_number_lengths: [8] 1572 | }, 1573 | { 1574 | alpha2: 'SV', 1575 | alpha3: 'SLV', 1576 | country_code: '503', 1577 | country_name: 'El Salvador', 1578 | mobile_begin_with: ['6', '7'], 1579 | phone_number_lengths: [8] 1580 | }, 1581 | { 1582 | alpha2: 'SM', 1583 | alpha3: 'SMR', 1584 | country_code: '378', 1585 | country_name: 'San Marino', 1586 | mobile_begin_with: ['3', '6'], 1587 | phone_number_lengths: [10] 1588 | }, 1589 | { 1590 | alpha2: 'SO', 1591 | alpha3: 'SOM', 1592 | country_code: '252', 1593 | country_name: 'Somalia', 1594 | mobile_begin_with: ['61', '62', '63', '65', '66', '68', '69', '71', '90'], 1595 | phone_number_lengths: [9] 1596 | }, 1597 | { 1598 | alpha2: 'SX', 1599 | alpha3: 'SXM', 1600 | country_code: '1', 1601 | country_name: 'Sint Maarten', 1602 | mobile_begin_with: ['721'], 1603 | phone_number_lengths: [10] 1604 | }, 1605 | { 1606 | alpha2: 'PM', 1607 | alpha3: 'SPM', 1608 | country_code: '508', 1609 | country_name: 'Saint Pierre And Miquelon', 1610 | mobile_begin_with: ['55', '41'], 1611 | phone_number_lengths: [6] 1612 | }, 1613 | { 1614 | alpha2: 'RS', 1615 | alpha3: 'SRB', 1616 | country_code: '381', 1617 | country_name: 'Serbia', 1618 | mobile_begin_with: ['6'], 1619 | phone_number_lengths: [8, 9] 1620 | }, 1621 | { 1622 | alpha2: 'ST', 1623 | alpha3: 'STP', 1624 | country_code: '239', 1625 | country_name: 'Sao Tome and Principe', 1626 | mobile_begin_with: ['98', '99'], 1627 | phone_number_lengths: [7] 1628 | }, 1629 | { 1630 | alpha2: 'SR', 1631 | alpha3: 'SUR', 1632 | country_code: '597', 1633 | country_name: 'Suriname', 1634 | mobile_begin_with: ['6', '7', '8'], 1635 | phone_number_lengths: [7] 1636 | }, 1637 | { 1638 | alpha2: 'SK', 1639 | alpha3: 'SVK', 1640 | country_code: '421', 1641 | country_name: 'Slovakia', 1642 | mobile_begin_with: ['9'], 1643 | phone_number_lengths: [9] 1644 | }, 1645 | { 1646 | alpha2: 'SI', 1647 | alpha3: 'SVN', 1648 | country_code: '386', 1649 | country_name: 'Slovenia', 1650 | mobile_begin_with: ['3', '4', '5', '6', '7'], 1651 | phone_number_lengths: [8] 1652 | }, 1653 | { 1654 | alpha2: 'SE', 1655 | alpha3: 'SWE', 1656 | country_code: '46', 1657 | country_name: 'Sweden', 1658 | mobile_begin_with: ['7'], 1659 | phone_number_lengths: [9] 1660 | }, 1661 | { 1662 | alpha2: 'SZ', 1663 | alpha3: 'SWZ', 1664 | country_code: '268', 1665 | country_name: 'Swaziland', 1666 | mobile_begin_with: ['76', '77', '78', '79'], 1667 | phone_number_lengths: [8] 1668 | }, 1669 | { 1670 | alpha2: 'SC', 1671 | alpha3: 'SYC', 1672 | country_code: '248', 1673 | country_name: 'Seychelles', 1674 | mobile_begin_with: ['2'], 1675 | phone_number_lengths: [7] 1676 | }, 1677 | { 1678 | alpha2: 'SY', 1679 | alpha3: 'SYR', 1680 | country_code: '963', 1681 | country_name: 'Syrian Arab Republic', 1682 | mobile_begin_with: ['9'], 1683 | phone_number_lengths: [9] 1684 | }, 1685 | // http://www.howtocallabroad.com/turks-caicos/ 1686 | { 1687 | alpha2: 'TC', 1688 | alpha3: 'TCA', 1689 | country_code: '1', 1690 | country_name: 'Turks and Caicos Islands', 1691 | mobile_begin_with: ['6492', '6493', '6494'], 1692 | phone_number_lengths: [10] 1693 | }, 1694 | { 1695 | alpha2: 'TD', 1696 | alpha3: 'TCD', 1697 | country_code: '235', 1698 | country_name: 'Chad', 1699 | mobile_begin_with: ['6', '7', '9'], 1700 | phone_number_lengths: [8] 1701 | }, 1702 | { 1703 | alpha2: 'TG', 1704 | alpha3: 'TGO', 1705 | country_code: '228', 1706 | country_name: 'Togo', 1707 | mobile_begin_with: ['9'], 1708 | phone_number_lengths: [8] 1709 | }, 1710 | { 1711 | alpha2: 'TH', 1712 | alpha3: 'THA', 1713 | country_code: '66', 1714 | country_name: 'Thailand', 1715 | mobile_begin_with: ['6', '8', '9'], 1716 | phone_number_lengths: [9] 1717 | }, 1718 | { 1719 | alpha2: 'TJ', 1720 | alpha3: 'TJK', 1721 | country_code: '992', 1722 | country_name: 'Tajikistan', 1723 | mobile_begin_with: ['9'], 1724 | phone_number_lengths: [9] 1725 | }, 1726 | { 1727 | alpha2: 'TK', 1728 | alpha3: 'TKL', 1729 | country_code: '690', 1730 | country_name: 'Tokelau', 1731 | mobile_begin_with: [], 1732 | phone_number_lengths: [4] 1733 | }, 1734 | { 1735 | alpha2: 'TM', 1736 | alpha3: 'TKM', 1737 | country_code: '993', 1738 | country_name: 'Turkmenistan', 1739 | mobile_begin_with: ['6'], 1740 | phone_number_lengths: [8] 1741 | }, 1742 | { 1743 | alpha2: 'TL', 1744 | alpha3: 'TLS', 1745 | country_code: '670', 1746 | country_name: 'Timor-Leste', 1747 | mobile_begin_with: ['7'], 1748 | phone_number_lengths: [8] 1749 | }, 1750 | { 1751 | alpha2: 'TO', 1752 | alpha3: 'TON', 1753 | country_code: '676', 1754 | country_name: 'Tonga', 1755 | mobile_begin_with: [], 1756 | phone_number_lengths: [5] 1757 | }, 1758 | { 1759 | alpha2: 'TT', 1760 | alpha3: 'TTO', 1761 | country_code: '1', 1762 | country_name: 'Trinidad and Tobago', 1763 | mobile_begin_with: ['868'], 1764 | phone_number_lengths: [10] 1765 | }, 1766 | { 1767 | alpha2: 'TN', 1768 | alpha3: 'TUN', 1769 | country_code: '216', 1770 | country_name: 'Tunisia', 1771 | mobile_begin_with: ['2', '4', '5', '9'], 1772 | phone_number_lengths: [8] 1773 | }, 1774 | { 1775 | alpha2: 'TR', 1776 | alpha3: 'TUR', 1777 | country_code: '90', 1778 | country_name: 'Turkey', 1779 | mobile_begin_with: ['5'], 1780 | phone_number_lengths: [10] 1781 | }, 1782 | { 1783 | alpha2: 'TV', 1784 | alpha3: 'TUV', 1785 | country_code: '688', 1786 | country_name: 'Tuvalu', 1787 | mobile_begin_with: [], 1788 | phone_number_lengths: [5] 1789 | }, 1790 | { 1791 | alpha2: 'TW', 1792 | alpha3: 'TWN', 1793 | country_code: '886', 1794 | country_name: 'Taiwan', 1795 | mobile_begin_with: ['9'], 1796 | phone_number_lengths: [9] 1797 | }, 1798 | { 1799 | alpha2: 'TZ', 1800 | alpha3: 'TZA', 1801 | country_code: '255', 1802 | country_name: 'Tanzania, United Republic of', 1803 | mobile_begin_with: ['7', '6'], 1804 | phone_number_lengths: [9] 1805 | }, 1806 | { 1807 | alpha2: 'UG', 1808 | alpha3: 'UGA', 1809 | country_code: '256', 1810 | country_name: 'Uganda', 1811 | mobile_begin_with: ['7'], 1812 | phone_number_lengths: [9] 1813 | }, 1814 | { 1815 | alpha2: 'UA', 1816 | alpha3: 'UKR', 1817 | country_code: '380', 1818 | country_name: 'Ukraine', 1819 | mobile_begin_with: ['39', '50', '63', '66', '67', '68', '73', '75', '77', '9'], 1820 | phone_number_lengths: [9] 1821 | }, 1822 | // {alpha2: "UM", alpha3: "UMI", country_code: "", country_name: "United States Minor Outlying Islands", mobile_begin_with: [], phone_number_lengths: []}, 1823 | { 1824 | alpha2: 'UY', 1825 | alpha3: 'URY', 1826 | country_code: '598', 1827 | country_name: 'Uruguay', 1828 | mobile_begin_with: ['9'], 1829 | phone_number_lengths: [8] 1830 | }, 1831 | { 1832 | alpha2: 'UZ', 1833 | alpha3: 'UZB', 1834 | country_code: '998', 1835 | country_name: 'Uzbekistan', 1836 | mobile_begin_with: ['9', '88', '33'], 1837 | phone_number_lengths: [9] 1838 | }, 1839 | // {alpha2: "VA", alpha3: "VAT", country_code: "39", country_name: "Holy See (Vatican City State)", mobile_begin_with: [], phone_number_lengths: []}, 1840 | { 1841 | alpha2: 'VC', 1842 | alpha3: 'VCT', 1843 | country_code: '1', 1844 | country_name: 'Saint Vincent And The Grenedines', 1845 | mobile_begin_with: ['784'], 1846 | phone_number_lengths: [10] 1847 | }, 1848 | { 1849 | alpha2: 'VE', 1850 | alpha3: 'VEN', 1851 | country_code: '58', 1852 | country_name: 'Venezuela, Bolivarian Republic of', 1853 | mobile_begin_with: ['4'], 1854 | phone_number_lengths: [10] 1855 | }, 1856 | { 1857 | alpha2: 'VG', 1858 | alpha3: 'VGB', 1859 | country_code: '1', 1860 | country_name: 'Virgin Islands, British', 1861 | mobile_begin_with: ['284'], 1862 | phone_number_lengths: [10] 1863 | }, 1864 | { 1865 | alpha2: 'VI', 1866 | alpha3: 'VIR', 1867 | country_code: '1', 1868 | country_name: 'Virgin Islands, U.S.', 1869 | mobile_begin_with: ['340'], 1870 | phone_number_lengths: [10] 1871 | }, 1872 | { 1873 | alpha2: 'VN', 1874 | alpha3: 'VNM', 1875 | country_code: '84', 1876 | country_name: 'Viet Nam', 1877 | mobile_begin_with: ['8', '9', '3', '7', '5'], 1878 | phone_number_lengths: [9] 1879 | }, 1880 | { 1881 | alpha2: 'VU', 1882 | alpha3: 'VUT', 1883 | country_code: '678', 1884 | country_name: 'Vanuatu', 1885 | mobile_begin_with: ['5', '7'], 1886 | phone_number_lengths: [7] 1887 | }, 1888 | { 1889 | alpha2: 'WF', 1890 | alpha3: 'WLF', 1891 | country_code: '681', 1892 | country_name: 'Wallis and Futuna', 1893 | mobile_begin_with: [], 1894 | phone_number_lengths: [6] 1895 | }, 1896 | { 1897 | alpha2: 'WS', 1898 | alpha3: 'WSM', 1899 | country_code: '685', 1900 | country_name: 'Samoa', 1901 | mobile_begin_with: ['7'], 1902 | phone_number_lengths: [7] 1903 | }, 1904 | { 1905 | alpha2: 'YE', 1906 | alpha3: 'YEM', 1907 | country_code: '967', 1908 | country_name: 'Yemen', 1909 | mobile_begin_with: ['7'], 1910 | phone_number_lengths: [9] 1911 | }, 1912 | { 1913 | alpha2: 'ZA', 1914 | alpha3: 'ZAF', 1915 | country_code: '27', 1916 | country_name: 'South Africa', 1917 | mobile_begin_with: ['1', '2', '3', '4', '5', '6', '7', '8'], 1918 | phone_number_lengths: [9] 1919 | }, 1920 | { 1921 | alpha2: 'ZM', 1922 | alpha3: 'ZMB', 1923 | country_code: '260', 1924 | country_name: 'Zambia', 1925 | mobile_begin_with: ['9', '7'], 1926 | phone_number_lengths: [9] 1927 | }, 1928 | { 1929 | alpha2: 'ZW', 1930 | alpha3: 'ZWE', 1931 | country_code: '263', 1932 | country_name: 'Zimbabwe', 1933 | mobile_begin_with: ['71', '73', '77', '78'], 1934 | phone_number_lengths: [9] 1935 | } 1936 | ]; 1937 | --------------------------------------------------------------------------------