Java를 사용하여 전화번호를 국제 형식(E.164)으로 변환하는 가장 좋은 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/187216

문제

Java를 사용하여 전화번호를 국제 형식(E.164)으로 변환하는 가장 좋은 방법은 무엇입니까?

'전화번호'와 국가 ID(ISO 국가 코드라고 가정)가 주어지면 이를 표준 E.164 국제 형식 전화번호로 변환하고 싶습니다.

나는 그것을 손으로 아주 쉽게 할 수 있다고 확신합니다. 그러나 그것이 모든 상황에서 올바르게 작동할 것이라고 확신할 수는 없습니다.

이를 달성하기 위해 어떤 Java 프레임워크/라이브러리/유틸리티를 권장하시겠습니까?

추신'전화번호'는 일반 대중이 식별할 수 있는 모든 것이 될 수 있습니다.

* (510) 786-0404
* 1-800-GOT-MILK
* +44-(0)800-7310658

마지막 것은 제가 가장 좋아하는 것입니다. 영국에서 일부 사람들이 전화번호를 쓰는 방식은 +44를 사용하거나 0을 사용해야 함을 의미합니다.

E.164 형식 번호는 모두 숫자여야 하며 전체 국제 국가 코드(예: +44)를 사용해야 합니다.

도움이 되었습니까?

해결책

Google은 전화 번호로 작업하기위한 라이브러리를 제공합니다. 그들이 Android에 사용하는 것과 동일합니다

http://code.google.com/p/libphonenumber/

String swissNumberStr = "044 668 18 00"
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
  PhoneNumber swissNumberProto = phoneUtil.parse(swissNumberStr, "CH");
} catch (NumberParseException e) {
  System.err.println("NumberParseException was thrown: " + e.toString());
}

// Produces "+41 44 668 18 00"
System.out.println(phoneUtil.format(swissNumberProto, PhoneNumberFormat.INTERNATIONAL));
// Produces "044 668 18 00"
System.out.println(phoneUtil.format(swissNumberProto, PhoneNumberFormat.NATIONAL));
// Produces "+41446681800"
System.out.println(phoneUtil.format(swissNumberProto, PhoneNumberFormat.E164));

다른 팁

이런 글을 써본 경험에 비추어 볼 때 100% 신뢰도를 갖는 것은 정말 어렵습니다.이를 위해 우리가 가지고 있는 데이터를 처리하는 데 합리적으로 적합하지만 모든 국가에 적용할 수는 없는 몇 가지 Java 코드를 작성했습니다.당신이 물어봐야 할 질문은 다음과 같습니다

국가 간에 문자-숫자 매핑이 일관됩니까?미국에서는 이를 많이 사용하지만(예: 1800-GOT-MILK) 호주에서는 일례로 매우 드뭅니다.당신이 해야 할 일은 문제의 국가가 다를 경우(그렇지 않을 수도 있음) 해당 국가에 대해 올바른 매핑을 수행하고 있는지 확인하는 것입니다.다른 알파벳을 사용하는 국가(예: 러시아의 키릴 문자와 이전 동부 블록 국가)가 어떤 국가인지 모르겠습니다.

당신은 당신의 해결책이 100%가 아닐 것이라는 점을 받아들여야 하며 그렇게 될 것이라고 기대해서는 안 됩니다."최선의 추측" 접근 방식을 취해야 합니다.예를 들어, 호주에서는 132345가 유효한 전화번호이고 1300 123 456도 유효한 전화번호인지 알 수 있는 실제 방법은 없습니다. 그러나 이 패턴은 13xx 번호에 대한 유일한 두 가지 패턴이며 해외에서는 전화를 걸 수 없습니다.

또한 지역(지역번호)을 확인하고 싶은지 물어봐야 합니다.미국은 지역번호 둘째자리가 1이나 0인 시스템을 사용하는 것 같아요.한때 이런 일이 있었을 수도 있지만 여전히 적용되는지는 확실하지 않습니다.어떤 경우이든 다른 많은 국가에는 다른 규칙이 있습니다.호주에서 유선전화 및 휴대전화의 유효한 지역번호는 두 자리입니다(첫 번째는 0).08, 03, 04는 모두 유효합니다.01은 그렇지 않아요.그것을 어떻게 충족시키나요?원하시나요?

국가마다 표기하는 자릿수에 관계없이 서로 다른 규칙을 사용합니다."표준"이 아닌 다른 것을 받아들이고 싶은지 결정해야 합니다.다음은 모두 호주에서 일반적입니다.

  • (02) 1234 5678
  • 02 1234 5678
  • 0411 123 123 (근데 04 1112 3456 본 적 없음)
  • 131 123
  • 13 1123
  • 131 123
  • 1 300 123 123
  • 1300 123 123
  • 02-1234-5678
  • 1300-234-234
  • +44 78 1234 1234
  • +44 (0)78 1234 1234
  • +44-78-1234-1234
  • +44-(0)78-1234-1234
  • 0011 44 ​​78 1234 1234 (0011은 표준 국제전화 코드입니다)
  • (44) 078 1234 1234 (비공통)

그리고 그것은 내 머리 꼭대기에서 벗어났습니다.한 국가의 경우.예를 들어 프랑스에서는 전화번호를 숫자 쌍(12 34 56 78)으로 쓰는 것이 일반적이며 다음과 같이 발음합니다.대신에:

un(하나), deux(둘), trois(셋), ...

그것은

douze (12), trente-quatre (34), ...

그 수준의 문화적 차이를 수용하고 싶나요?나는 그렇지 않다고 생각하지만 규칙을 너무 엄격하게 만드는 경우를 대비해 질문을 고려해 볼 가치가 있습니다.

또한 일부 사람들은 전화번호에 "ext" 또는 유사한 약어를 사용하여 내선 번호를 추가할 수도 있습니다.그 일을 처리하고 싶나요?

죄송합니다. 여기에는 코드가 없습니다.스스로에게 물어봐야 할 질문과 고려해야 할 문제의 목록입니다.다른 사람들이 말했듯이 일련의 정규식은 위의 많은 작업을 수행할 수 있지만 궁극적으로 전화번호 필드는 결국 (대부분) 자유 형식 텍스트입니다.

이것은 내 해결책이었습니다.

public static String FixPhoneNumber(Context ctx, String rawNumber)
{
    String      fixedNumber = "";

    // get current location iso code
    TelephonyManager    telMgr = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
    String              curLocale = telMgr.getNetworkCountryIso().toUpperCase();

    PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
    Phonenumber.PhoneNumber     phoneNumberProto;

    // gets the international dialling code for our current location
    String              curDCode = String.format("%d", phoneUtil.getCountryCodeForRegion(curLocale));
    String              ourDCode = "";

    if(rawNumber.indexOf("+") == 0)
    {
        int     bIndex = rawNumber.indexOf("(");
        int     hIndex = rawNumber.indexOf("-");
        int     eIndex = rawNumber.indexOf(" ");

        if(bIndex != -1)
        {
            ourDCode = rawNumber.substring(1, bIndex);
        }
        else if(hIndex != -1) 
        {               
            ourDCode = rawNumber.substring(1, hIndex);
        }
        else if(eIndex != -1)
        {
            ourDCode = rawNumber.substring(1, eIndex);
        }
        else
        {
            ourDCode = curDCode;
        }           
    }
    else
    {
        ourDCode = curDCode;
    }

    try 
    {
      phoneNumberProto = phoneUtil.parse(rawNumber, curLocale);
    } 

    catch (NumberParseException e) 
    {
      return rawNumber;
    }

    if(curDCode.compareTo(ourDCode) == 0)
        fixedNumber = phoneUtil.format(phoneNumberProto, PhoneNumberFormat.NATIONAL);
    else
        fixedNumber = phoneUtil.format(phoneNumberProto, PhoneNumberFormat.INTERNATIONAL);

    return fixedNumber.replace(" ", "");
}

나는 이것이 같은 문제를 겪는 사람에게 도움이되기를 바랍니다.

자유롭게 즐기고 사용하십시오.

답변 주셔서 감사합니다. 원래 질문에 언급 된 바와 같이, 나는 그것이 유효한 (진정한) 전화 번호와 같이 숫자를 표준 형식으로 서식하는 데 훨씬 더 관심이 있습니다.

현재 전화 번호 문자열 (사용자가 입력 한)과 소스 국가 컨텍스트 및 대상 국가 컨텍스트 (번호가 다이얼링되는 국가 및 국가에 전화 번호가있는 국가까지의 국가)를 취하는 수작업 코드가 있습니다. - 이것은 시스템에 알려져 있습니다) 그리고 다음 단계에서 다음과 같은 변환을 수행합니다.

  1. 숫자에서 모든 공백을 제거하십시오

  2. 모든 알파를 숫자로 변환-숫자로 문자 조회 테이블을 사용하여 숫자 (예 :> 2, b-> 2, c-> 2, d-> 3) 등 (나는 알지 못했습니다. 일부 키패드는 이것들을 다르게 배포한다는 것)

  3. 모든 문장 부호를 벗기십시오 - 앞의 '+'를 그대로 유지하는 경우 (숫자가 이미 어떤 종류의 국제 형식에있는 경우).

  4. 숫자에 국가 컨텍스트에 대한 국제 다이얼링 접두사가 있는지 확인하십시오. 예를 들어 소스 컨텍스트가 영국 인 경우 '00'으로 시작하는지 확인하고 '+'로 대체 할 것입니다. 나는 현재 '00'을 따르는 숫자가 대상 국가의 국제 다이얼링 코드가 이어지는 지 여부를 확인하지 않습니다. 나는 조회 테이블에서 소스 국가의 국제 다이얼링 접두사를 조회합니다 (예 : GB-> '00', 미국-> '011'등).

  5. 숫자에 국가 컨텍스트에 대한 로컬 다이얼링 접두사가 있는지 확인하십시오. 예를 들어 소스 컨텍스트가 영국인지 여부는 '0'으로 시작하는지 확인하고 '+'로 바꾸고 국제 다이얼링으로 대체 할 것입니다. 대상 국가에 대한 코드. 소스 국가의 로컬 다이얼링 접두사를 조회 테이블 (예 : GB-> '0', US-> '1'등) 및 다른 조회 테이블에서 대상 국가의 국제 다이얼링 코드를 찾습니다 ( eg'gb '='44 ', us ='1 ')

+44 (0) 1234-567-890 상황을 제외하고는 지금까지 내가 던진 모든 것에 대해 작동하는 것 같습니다.

글을 쓰는 것은 어렵지 않았습니다. 그리고 나는 내가 만나는 각 이상한 예외에 대해 특별한 케이스를 추가 할 수 있습니다. 그러나 표준 솔루션이 있는지 정말 알고 싶습니다.

전화 회사는 매일이 일을 다루는 것 같습니다. PSTN을 사용하여 숫자를 다이얼 할 때는 일관되지 않은 결과를 얻지 못합니다. 예를 들어, 미국 (휴대 전화와 동일한 영역 코드가있는 곳에서는 +1-123-456-7890 또는 011-1-123-456-7890에 전화를 걸 수 있습니다) (여기서 011은 국제 다이얼링 접두사입니다. 미국과 1은 미국의 국제 다이얼링 코드), 1-123-456-7890 (여기서 1은 미국의 로컬 다이얼링 접두사) 또는 456-7890 (당시 123 개의 영역 코드에 있다고 가정 함)입니다. 내부적 으로이 다이얼 숫자가 동일한 E.164 표준 형식으로 변환되고 소프트웨어에서 모두 변환된다고 가정합니다.

솔직히 말해서, 대부분의 기지가 이미 덮여있는 것처럼 들립니다.

영국에서 사용되는 +44 (0) 800 형식은 때때로 (잘못된) 성가 시며 E.123에 따라 성가시다. 이는 숫자를 표시하는 방법에 대한 ITU-T 권장 사항이다. E.123의 사본을 얻지 못했다면 볼만한 가치가 있습니다.

가치가있는 것에 대해 전화 네트워크 자체가 항상 E.164를 사용하지는 않습니다. 종종 PBX에 의해 생성 된 ISDN 신호 (또는 Steam Phone에있는 경우 네트워크에서)에 깃발이 생길 수 있습니다.

전화 번호가 각 국가에서 거의 다르게 작성되므로 매우 어려운 작업입니다.

우리는 숫자의 3 부분을 구문 분석하기 위해 Regexps (19 개의 형식을 지원) 목록을 유지 한 다음 해당 3 부분을 "+{1} {2} {3}"로 변환했습니다.

Regexps를보다 구체적으로 정렬 한 다음 구문 분석에 성공한 첫 번째를 가져갑니다.

일부 국가에서는 유효한 전화 번호로 112를 검증 할 수 있지만, 국가 코드를 고수하면 더 이상 유효하지 않습니다. 다른 국가에서는 112를 확인할 수 없지만 911을 유효한 전화 번호로 검증 할 수 있습니다.

Q를 7 키에, 9 키에 Z를 넣는 일부 전화를 보았습니다. 0 키에 Q와 Z를 넣는 일부 전화를 보았고 일부는 1 키에 Q와 Z를 넣는 것을 보았습니다.

어제 존재했던 지역 코드는 오늘날 존재하지 않을 수 있으며 그 반대도 마찬가지입니다.

북아메리카의 절반 (국가 코드 1)에서 두 번째 자리 규칙은 지역 코드의 경우 0 또는 1 이었지만 10 년 전에는 그 규칙이 사라졌습니다.

전화 번호를 E.164로 서식하는 데 사용할 수있는 표준 라이브러리 또는 프레임 워크를 알지 못합니다.

Caller-ID가 E.164로 제공 한 PBX를 포맷 해야하는 제품에 사용되는 솔루션은 적용 가능한 모든 국가에 대한 E.164 형식 정보를 포함하는 파일 (데이터베이스 테이블)을 배포하는 것입니다. 이는 생산 코드베이스를 변경 해야하는 애플리케이션을 업데이트 할 수 있다는 이점이 있습니다 (다양한 PSTN 네트워크의 모든 이상한 코너 케이스를 처리하기 위해).

테이블에는 각 국가 코드에 대한 행과 지역 코드 길이 및 가입자 길이에 관한 정보가 포함되어 있습니다. 영역 코드 및 가입자 번호 길이로 가능한 변형에 따라 국가에 대한 여러 항목이있을 수 있습니다.

뉴질랜드 PSTN (부분) 다이얼 플랜 사용 테이블의 예 ..

CC  AREA_CODE  AREA_CODE_LENGTH  SUBSCRIBER  SUBSCRIBER_LENGTH
64                            1              7
64         21                 2              7
64        275                 3              6

우리는 귀하가 설명한 것과 유사한 일을 수행합니다. 즉, 전체 번호가없는 캐릭터의 제공된 전화 번호를 벗어난 다음 전체 번호 계획 길이, 외부 액세스 코드 및 장거리/국제 액세스 코드와 관련된 다양한 규칙을 기반으로 형식을 구성합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top