9

I have a list of mobile numbers with country code like "919638095998"number. I have referred the libphonenumber google example also but in that first we need to pass the country 2 digit code, which I don't know initially. So how can I know that the number is from which country?

I have also got one solution as manually extract the code one by one digit from mobile number and then compare with country code. But it is a long task and also it will give me bad performance. Can anyone suggest a proper solution?

midhunhk
  • 5,560
  • 7
  • 52
  • 83
Nency
  • 482
  • 1
  • 8
  • 21
  • why is it a long task? it's very simple: take the first 2 digits from the string (using something like a subString() method) and then retrieve the right country from a service or your own country code db table. – Th0rndike Sep 04 '12 at 08:19
  • 7
    but every country do not have two digits for country code.Some country has 1,2 or 3 country code. – Nency Sep 04 '12 at 08:20
  • It's not that simple since a country code isn't always 2 digets. US for example has a length of 1 (1) while Madagascar has a length of 3 (212) – Janoz Sep 04 '12 at 08:27

9 Answers9

12

libphonenumber does that for you. All you have to do is add the + sign before your phone number and omit the country code when parsing the phone number.

String numberStr = "+919638095998";
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
    Phonenumber.PhoneNumber numberProto = phoneUtil.parse(numberStr, "");

    System.out.println("Country code: " + numberProto.getCountryCode());
    //This prints "Country code: 91"
} catch (NumberParseException e) {
    System.err.println("NumberParseException was thrown: " + e.toString());
}
João Neves
  • 944
  • 1
  • 13
  • 18
9

There is a list of all the phone numbers available for country codes on Wikipedia. It is here

http://en.wikipedia.org/wiki/List_of_country_calling_codes

I would create two hashmaps. One with all the four digit codes and one containing both the two and three digit codes.

Hashmap fourdigitcodes;

//check if first digit is 7
if(firstdigit==7)
  //country definitely russia
else
   if country code begins with 1.
     Check the first four digits are in the hashmap with four digit codes and return the value 
     if no value is found then answer is certainly usa.
otherwise
     String country="";
     HashMap<String,String> ccode = new HashMap<String,String>();
     ccode.put("353","Ireland");//List all country codes
     ccode.put("49","Germany");
     String value = ccode.get("49");//See if I have a value for the first 2 digits
     if(value != null){
      country = value; //If I found a country for the first two digits we are done as the              first two digits of the country code consisting of two digits cannot be in a country code with 3
     }else{
      the country is certainly 3 digit. return the first three digits by entering the first 3 digits as the key of the hashmap countaining the first three digits. 
     }

In summary. If first digit is 7 Russian. If it is 1 check in the hashmap of four digit codes for the first four numbers if found a four digit code return the corresponding country.if not answer is USA otherwise check first two digits in the hashmap containing the 2 or 3 digits. If found two then return the answer other it is certainly a three digit code and return the corresponding country from the hash.

It will be tedious to make the hashmap but I think an efficient solution.

KennyBartMan
  • 940
  • 9
  • 21
  • Hmm I didn't realise that this corner case existed. It seems there are two 1 digit codes. Russian and the USA: So 1 and 7 are the codes here. If the first digit of a number is 7 you are guaranteed that the country is Russia/Kazakstan. They have the same country code. I would check this at the very beginning and not bother with the rest of the algorithm if this is the case. I am still thinknig about the rest – KennyBartMan Sep 04 '12 at 08:54
  • do you know?Us mobile number have the area code in mobile number or just 10 digits with +1? – Nency Sep 04 '12 at 09:06
  • Us mobile numbers do not have an area coda. No US phone number will start with the four digit code of another country. It is not possible. If the first digit is one AND the first four digits are not another code you know you are talking about a US or canadian number as they have the same code. – KennyBartMan Sep 04 '12 at 09:08
  • I mean other area like "Barbados" have "+1246xxxxxxxxxx".if mobile number does not have the area code and if we compare the first 4 digits followed by "1" and if that 4 digits as same as us 'countrycode'+'area code' then we consider true country but the reamining digits are not true mobile number so also need to check the mobile number length as per country. – Nency Sep 04 '12 at 09:09
  • I am not sure I understand. When given a phone number. 123456789.. we need to check if the first four digits are a country code(1234). If they are then we look the country up in the hashmap. If they are not the country is the US/Canada – KennyBartMan Sep 04 '12 at 09:12
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16228/discussion-between-nency-and-jonathan-cummins) – Nency Sep 04 '12 at 09:15
2
The below code will extract the country code from any given phone number, the logic is implemented based on. https://en.wikipedia.org/wiki/List_of_country_calling_codes
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

    /**
     * @author swapna * This class will fetch the country code from the incoming
     *         phone number with format <+><CTRY CODE><Phone Number> based on the
     *         data from https://en.wikipedia.org/wiki/List_of_country_calling_codes
     *
     */
    public enum PhoneNumberNCtryCode {
        Instance;

        private List<Integer> forCtryCodePrefix1 = new ArrayList<Integer>();
        @SuppressWarnings("serial")
        List<Integer> forCtryCodePrefix2 = new ArrayList<Integer>() {
            {
                add(0);
                add(7);
                add(8);

            }
        };
        @SuppressWarnings("serial")
        private List<Integer> forCtryCodePrefix3 = new ArrayList<Integer>() {
            {
                add(0);
                add(1);
                add(2);
                add(3);
                add(4);
                add(6);
                add(9);
            }
        };
        @SuppressWarnings("serial")
        private List<Integer> forCtryCodePrefix4 = new ArrayList<Integer>() {
            {
                add(0);
                add(1);
                add(3);
                add(4);
                add(5);
                add(6);
                add(7);
                add(8);
                add(9);
            }
        };
        @SuppressWarnings("serial")
        private List<Integer> forCtryCodePrefix5 = new ArrayList<Integer>() {
            {
                add(1);
                add(2);
                add(3);
                add(4);
                add(5);
                add(6);
                add(7);
                add(8);
            }
        };
        @SuppressWarnings("serial")
        private List<Integer> forCtryCodePrefix6 = new ArrayList<Integer>() {
            {
                add(0);
                add(1);
                add(3);
                add(4);
                add(5);
                add(6);

            }
        };
        private List<Integer> forCtryCodePrefix7 = new ArrayList<Integer>();
        @SuppressWarnings("serial")
        private List<Integer> forCtryCodePrefix8 = new ArrayList<Integer>() {
            {
                add(1);
                add(3);
                add(4);
                add(6);
                add(9);

            }
        };
        @SuppressWarnings("serial")
        private List<Integer> forCtryCodePrefix9 = new ArrayList<Integer>() {
            {
                add(1);
                add(2);
                add(3);
                add(4);
                add(5);
                add(8);
            }
        };
        @SuppressWarnings("serial")
        private Map<Integer, List<Integer>> countryCodeMap = new HashMap<Integer, List<Integer>>() {
            {
                put(1, forCtryCodePrefix1);
                put(2, forCtryCodePrefix2);
                put(3, forCtryCodePrefix3);
                put(4, forCtryCodePrefix4);
                put(5, forCtryCodePrefix5);
                put(6, forCtryCodePrefix6);
                put(7, forCtryCodePrefix7);
                put(8, forCtryCodePrefix8);
                put(9, forCtryCodePrefix9);

            }
        };

        /**
         * This method parses the phone number using the prefix Ctry Map
         * 
         * @param phoneNumber
         * @return
         */
        public int getCtryCode(String phoneNumber) {
            String ctryCodeAtIndex1 = phoneNumber.substring(1, 2);
            Integer ctryCode = 0;
            String ctryCodeStr = "0";

            List<Integer> ctryCodeList =        countryCodeMap.get(Integer.valueOf(ctryCodeAtIndex1));
            if (ctryCodeList.isEmpty()) {
                ctryCode = Integer.valueOf(ctryCodeAtIndex1);
                return ctryCode.intValue();
            }
            String ctryCodeAtIndex2 = phoneNumber.substring(2, 3);
            for (Integer ctryCodePrefix : ctryCodeList) {
                if (Integer.valueOf(ctryCodeAtIndex2) == ctryCodePrefix) {
                    ctryCodeStr = phoneNumber.substring(1, 3);
                    ctryCode = Integer.valueOf(ctryCodeStr);
                    return ctryCode.intValue();

                }
            }
            ctryCodeStr = phoneNumber.substring(1, 4);
            ctryCode = Integer.valueOf(ctryCodeStr);
            return ctryCode.intValue();
        }

    }
swara
  • 21
  • 1
1

if it's not late

Just looking for this I found a Java and Javascript library maintained by Google ;)

See the repo: https://github.com/googlei18n/libphonenumber

Also there is a demo.

Good Luck!

Willem
  • 462
  • 4
  • 10
0

While using static data structures may be considered bad practice, country codes don't change much, so I think creating a list of them as a tree and parsing the number with this tree should be an easy to implement solution.

You could also put the list of country codes in an external file so it can be easily updated without changing the application code.

Wikipedia has the list of country codes here.

vainolo
  • 6,907
  • 4
  • 24
  • 47
  • i have list of country code but how can i extract the country code from mobile number? – Nency Sep 04 '12 at 08:21
  • do you have the mobile number? then parse it from left to right and try to match it with the country codes, organized as a tree like structure, as the one shown in the wikipedia link. – vainolo Sep 04 '12 at 08:43
  • is area code included in us mobile number?like "+1 242 xxxxxxxxxx – Nency Sep 04 '12 at 08:46
  • You can find the list of US area codes here: http://en.wikipedia.org/wiki/List_of_NANP_area_codes – vainolo Sep 04 '12 at 09:02
  • i don't want all area code, i have just asked that in us mobile number the area code is also included or just mobile number of 10 digits with country code +1? – Nency Sep 04 '12 at 09:04
  • of course it is included. Phone number is actually 7 digits. Area code are the first 3 digits from left to right – vainolo Sep 04 '12 at 09:16
0

If the country code is only 2 digit no. split the phone no into 2 with first substring having 2 digits and second one having the remaining 10 digit.

viks
  • 404
  • 2
  • 6
  • 14
  • please see the comment of Janoz.Its not always true that country code is always length of 2 digits. – Nency Sep 04 '12 at 08:30
  • Then check the phone no. with the code list to find if there is any matching ones.If no,remove the last no and repeat the check. – viks Sep 04 '12 at 08:32
  • The mobile can be of 11 digits as well. This logic won't work in that case – Rahul Mishra Jul 20 '20 at 15:31
0

Just doing a quick check from wikipedia, I figured that you need to do a max string search algo from the front. On a conflict, which does not seem to come, but incase, you can check the number of digits (NSN) to find the country code

An optimized way would be to create buckets. As from country code list. The maximum length of country code is 4, (unless you want to go into the precision of provinces in which case it will be 7, check zone 6). and then check for the existence from 4, 3, 2, 1. This will significantly reduce your search algorithm time. But yes the data size will be bigger. A classic case of time space tradeoff

Nitin Chhajer
  • 2,299
  • 1
  • 24
  • 35
0

If you take a look at your own link you can find the CountryCodeToRegionCodeMap class. It contains a list of probably all country codes. You could use that to create your own code to determine of the country code has a length of 1, 2 or 3. I can't believe this is the only place on the internet where such a list can be found.

Janoz
  • 953
  • 4
  • 9
0

Country code in mobile some time start with like +(plus)44, 0044, 44 and as said above some country may have variable length code. So best possible solution would be start from back as of now we know length of mobile number is 10. once you take those 10 digits, Then you can parse country code accordingly.

twid
  • 6,368
  • 4
  • 32
  • 50
  • 1
    But it is not necessary that every country mobile number length is 10 digits.Some country have 8 or 9 digits also. – Nency Sep 04 '12 at 08:51
  • Then we must store all country codes and length of mobile number for countries, and start parsing number from start with max possible match with country code That way you can get right country code. To cross check check length of mobile number(Without country code) is equal to length for corresponding country.. – twid Sep 06 '12 at 16:49
  • 1
    That might not be efficient – Shubham Chopra Feb 28 '19 at 07:21