36

I have been storing phone numbers as longs and I would like to simply add hyphens when printing the phone number as a string.

I tried using DecimalFormat but that doesn't like the hyphen. Probably because it is meant for formatting decimal numbers and not longs.

long phoneFmt = 123456789L;
DecimalFormat phoneFmt = new DecimalFormat("###-###-####");
System.out.println(phoneFmt.format(phoneNum)); //doesn't work as I had hoped

Ideally, I would like to have parenthesis on the area code too.

new DecimalFormat("(###)-###-####");

What is the correct way to do this?

1
  • 12
    Storing phone numbers in a numeric type such as long is not a good idea. Phone numbers are really a kind of labels, not numbers that you'd want to do calculations with. What if a phone number starts with 0 - you couldn't store that in a numeric type. Commented Feb 25, 2011 at 7:48

18 Answers 18

53

You can use String.replaceFirst with regex method like

    long phoneNum = 123456789L;
    System.out.println(String.valueOf(phoneNum).replaceFirst("(\\d{3})(\\d{3})(\\d+)", "($1)-$2-$3"));
Sign up to request clarification or add additional context in comments.

2 Comments

I used this to generate random ID numbers that follow a specific format. Thanks.
Regex is fine, but in a tight loop, this will be very slow.
28

To get your desired output:

long phoneFmt = 123456789L;
//get a 12 digits String, filling with left '0' (on the prefix)   
DecimalFormat phoneDecimalFmt = new DecimalFormat("0000000000");
String phoneRawString= phoneDecimalFmt.format(phoneFmt);

java.text.MessageFormat phoneMsgFmt=new java.text.MessageFormat("({0})-{1}-{2}");
    //suposing a grouping of 3-3-4
String[] phoneNumArr={phoneRawString.substring(0, 3),
          phoneRawString.substring(3,6),
          phoneRawString.substring(6)};

System.out.println(phoneMsgFmt.format(phoneNumArr));

The result at the Console looks like this:

(012)-345-6789

For storing phone numbers, you should consider using a data type other than numbers.

Comments

21

The easiest way to do this is by using the built in MaskFormatter in the javax.swing.text library.

You can do something like this :

import javax.swing.text.MaskFormatter;

String phoneMask= "###-###-####";
String phoneNumber= "123423452345";

MaskFormatter maskFormatter= new MaskFormatter(phoneMask);
maskFormatter.setValueContainsLiteralCharacters(false);
maskFormatter.valueToString(phoneNumber) ;

2 Comments

Very easy if you combine it with a DecimalFormat. The MaskFormatter's checked ParseException is annoying though.
Works nice. I made it an utility method.
9

If you really need the right way then you can use Google's recently open sourced libphonenumber

2 Comments

I don't think another library is necessary. There must be an easy way to do it with all the different Java formatting APIs. I just don't know which one to use.
@styfle: formatting alone is not your problem, storing a phonenumber in a long is.
9

You could also use https://github.com/googlei18n/libphonenumber. Here is an example:

import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;

String s = "18005551234";
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
Phonenumber.PhoneNumber phoneNumber = phoneUtil.parse(s, Locale.US.getCountry());
String formatted = phoneUtil.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);

Here you can get the library on your classpath: http://mvnrepository.com/artifact/com.googlecode.libphonenumber/libphonenumber

Comments

7

This is how I ended up doing it:

private String printPhone(Long phoneNum) {
    StringBuilder sb = new StringBuilder(15);
    StringBuilder temp = new StringBuilder(phoneNum.toString());

    while (temp.length() < 10)
        temp.insert(0, "0");

    char[] chars = temp.toString().toCharArray();

    sb.append("(");
    for (int i = 0; i < chars.length; i++) {
        if (i == 3)
            sb.append(") ");
        else if (i == 6)
            sb.append("-");
        sb.append(chars[i]);
    }

    return sb.toString();
}

I understand that this does not support international numbers, but I'm not writing a "real" application so I'm not concerned about that. I only accept a 10 character long as a phone number. I just wanted to print it with some formatting.

Thanks for the responses.

Comments

6

The worst possible solution would be:

StringBuilder sb = new StringBuilder();
long tmp = phoneFmt;
sb.append("(");
sb.append(tmp / 10000000);
tmp = tmp % 10000000;
sb.append(")-");
sb.apppend(tmp / 10000);
tmp = tmp % 10000000;
sb.append("-");
sb.append(tmp);

1 Comment

I doubt that is the worst - developers can be very creative [:-)
4

You can implement your own method to do that for you, I recommend you to use something such as this. Using DecimalFormat and MessageFormat. With this method you can use pretty much whatever you want (String,Integer,Float,Double) and the output will be always right.

import java.text.DecimalFormat;
import java.text.MessageFormat;

/**
 * Created by Yamil Garcia Hernandez on 25/4/16.
 */

public class test {
    // Constants
    public static final DecimalFormat phoneFormatD = new DecimalFormat("0000000000");
    public static final MessageFormat phoneFormatM = new MessageFormat("({0}) {1}-{2}");

    // Example Method on a Main Class
    public static void main(String... args) {
        try {
            System.out.println(formatPhoneNumber("8091231234"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(formatPhoneNumber("18091231234"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(formatPhoneNumber("451231234"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(formatPhoneNumber("11231234"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(formatPhoneNumber("1231234"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(formatPhoneNumber("231234"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(formatPhoneNumber(""));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(formatPhoneNumber(0));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(formatPhoneNumber(8091231234f));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // Magic
    public static String formatPhoneNumber(Object phone) throws Exception {

        double p = 0;

        if (phone instanceof String)
            p = Double.valueOf((String) phone);

        if (phone instanceof Integer)
            p = (Integer) phone;

        if (phone instanceof Float)
            p = (Float) phone;

        if (phone instanceof Double)
            p = (Double) phone;

        if (p == 0 || String.valueOf(p) == "" || String.valueOf(p).length() < 7)
            throw new Exception("Paramenter is no valid");

        String fot = phoneFormatD.format(p);

        String extra = fot.length() > 10 ? fot.substring(0, fot.length() - 10) : "";
        fot = fot.length() > 10 ? fot.substring(fot.length() - 10, fot.length()) : fot;

        String[] arr = {
                (fot.charAt(0) != '0') ? fot.substring(0, 3) : (fot.charAt(1) != '0') ? fot.substring(1, 3) : fot.substring(2, 3),
                fot.substring(3, 6),
                fot.substring(6)
        };
        String r = phoneFormatM.format(arr);
        r = (r.contains("(0)")) ? r.replace("(0) ", "") : r;
        r = (extra != "") ? ("+" + extra + " " + r) : r;
        return (r);
    }
}

Result will be

(809) 123-1234
+1 (809) 123-1234
(45) 123-1234
(1) 123-1234
123-1234
023-1234
java.lang.NumberFormatException: empty String
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
    at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
    at java.lang.Double.parseDouble(Double.java:538)
    at java.lang.Double.valueOf(Double.java:502)
    at test.formatPhoneNumber(test.java:66)
    at test.main(test.java:45)
java.lang.Exception: Paramenter is no valid
    at test.formatPhoneNumber(test.java:78)
    at test.main(test.java:50)
(809) 123-1232

Comments

2

DecimalFormat doesn't allow arbitrary text within the number to be formatted, just as a prefix or a suffix. So it won't be able to help you there.

In my opinion, storing a phone number as a numeric value is wrong, entirely. What if I want to store an international number? Many countries use + to indicate a country code (e.g. +1 for USA/Canda), others use 00 (e.g. 001).

Both of those can't really be represented in a numeric data type ("Is that number 1555123 or 001555123?")

2 Comments

This should have rather been a comment rather than being a solution post, reason being it does not provide any possible solution, instead provides a remark/insight to the question asked. Well I could be wrong with my opinion.
I understand your concern, but sometimes the correct answer to questions like "How do I hammer in a nail if all I have is a loaded gun" is "don't do that".
2

You could use the substring and concatenation for easy formatting too.

telephoneNumber = "("+telephoneNumber.substring(0, 3)+")-"+telephoneNumber.substring(3, 6)+"-"+telephoneNumber.substring(6, 10);

But one thing to note is that you must check for the lenght of the telephone number field just to make sure that your formatting is safe.

Comments

2

U can format any string containing non numeric characters also to your desired format use my util class to format

usage is very simple

public static void main(String[] args){
    String num = "ab12345*&67890";

    System.out.println(PhoneNumberUtil.formateToPhoneNumber(num,"(XXX)-XXX-XXXX",10));
}

output: (123)-456-7890

u can specify any foramt such as XXX-XXX-XXXX and length of the phone number , if input length is greater than specified length then string will be trimmed.

Get my class from here: https://github.com/gajeralalji/PhoneNumberUtil/blob/master/PhoneNumberUtil.java

Comments

2
Pattern phoneNumber = Pattern.compile("(\\d{3})(\\d{3})(\\d{4})");
// ...
Matcher matcher = phoneNumber(numberAsLineOf10Symbols);
if (matcher.matches) {
    return "(" + matcher.group(1) + ")-" +matcher.group(2) + "-" + matcher.group(3);
}

Comments

1

I'd have thought you need to use a MessageFormat rather than DecimalFormat. That should be more flexible.

Comments

1

String formatterPhone = String.format("%s-%s-%s", phoneNumber.substring(0, 3), phoneNumber.substring(3, 6), phoneNumber.substring(6, 10));

1 Comment

Can you add informations on what exactly that code does? A code only answer without explaining what it does is less useful. Also, format it so it appears as code.
0

Using StringBuilder for performance.

long number = 12345678L;

System.out.println(getPhoneFormat(String.valueOf(number)));

public static String getPhoneFormat(String number)
{
    if (number == null || number.isEmpty() || number.length() < 6 || number.length() > 15)
    {
        return number;
    }

    return new StringBuilder("(").append(number.substring(0, 3))
            .append(") ").append(number.substring(3, 6))
            .append("-").append(number.substring(6))
            .toString();

}

Comments

0

Kotlin

val number = 088899998888

val phone = number.phoneFormatter()

fun String.phoneFormatter(): String { return this.replace("\\B(?=(\\d{4})+(?!\\d))".toRegex(), "-") }

The result will be 0888-9999-8888

Comments

0

I used this one

String columValue = "1234567890

String number = columValue.replaceFirst("(\d{3})(\d{3})(\d+)", "($1) $2-$3");

Comments

0

I wrote the following code

import java.io.IOException;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

/**
 * Produces a string suitable for representing phone numbers by formatting them according with the format string
 */
@Slf4j
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder(builderMethodName = "builderInternal")
public class PhoneNumberFormatter {

    /** Format string used to represent phone numbers */
    @Getter @Builder.Default private String formatString = "(###)###-";
    
    /** String used to represent null phone numbers */
    @Getter @Builder.Default private String nullString = "---";
    
    /** Pattern used for substitutions of phone numbers. 
     * Pounds (#) are replaced by phone digits unless they are escaped (\#) */
    private static final Pattern PATTERN = Pattern.compile("\\\\#|#");
   
    /** Returns a new formatter with default parameters */
    public static PhoneNumberFormatter of() {
        return builder().build();
    }
    
    /** Returns a new formatter with the format string */
    public static PhoneNumberFormatter of(String formatString) {
        return builder(formatString).build();
    }
    
    /** Create a builder object. Notice that lombok does most of the work in builderInternal
     * but we want to pass the format string to the builder method directly */
    public static PhoneNumberFormatterBuilder builder(String formatString) {
        Objects.requireNonNull(formatString, "formatString");
        return builder().formatString(formatString);
    }
    
    /** Create a new builder with default parameters. Notice that builderInternal is created by lombok */
    public static PhoneNumberFormatterBuilder builder() {
        return builderInternal();
    }
    
    /** Return a formatted string corresponding to the given user */
    public String format(String phoneNumber) {
        StringBuilder buf = new StringBuilder(32);
        formatTo(phoneNumber, buf);
        return buf.toString();
    }
    
    /** Append a formatted string corresponding to the given user to the given appendable */
    public void formatTo(String phoneNumber, Appendable appendable) {
        Objects.requireNonNull(appendable, "appendable");

        if (appendable instanceof StringBuilder) {
            doFormat(phoneNumber, (StringBuilder) appendable);
        } else {
            // buffer output to avoid writing to appendable in case of error
            StringBuilder buf = new StringBuilder(32);
            doFormat(phoneNumber, buf);
            try {
                appendable.append(buf);
            } catch (IOException e) {
                log.warn("Could not append phone number {} to {appendable}", phoneNumber, e);
            }
        }
    }
    
    /** Performs regex search and replacement of digits */
    private void doFormat(String phoneNumber, StringBuilder result) {
        if (phoneNumber == null) {
            result.append(nullString);
            return;
        }
        Matcher matcher = PATTERN.matcher(formatString);
        int digitIndex = 0;
        while (matcher.find()) {
            if (matcher.group().equals("\\#")) {
                matcher.appendReplacement(result, "#");
            } else if (digitIndex < phoneNumber.length()) {
                matcher.appendReplacement(result, String.valueOf(phoneNumber.charAt(digitIndex)));
                digitIndex++;
            } else {
                break; // Stop if there are no more digits in the phone number
            }
        }
        matcher.appendTail(result);
        result.append(phoneNumber.substring(digitIndex));
    }
    
}

This is some test code that exemplifies the usage:

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;

public class PhoneNumberFormatterTest {

  @Test
  public void nullArgsTest() {

    assertThrows(NullPointerException.class, () -> PhoneNumberFormatter.of(null),
    "Expected using null as a format string to fail, but it didn't");
    
    PhoneNumberFormatter f = PhoneNumberFormatter.of();
    assertEquals(f.getNullString(), f.format(null));
    
    f = PhoneNumberFormatter.builder().nullString("null phone").build();
    assertEquals("null phone", f.format(null));
    
    assertThrows(NullPointerException.class, () -> PhoneNumberFormatter.of().formatTo("12345", null),
    "Expected appending to a null appender to fail, but it didn't");
    
  }

  @Test
  public void validTests() {
      PhoneNumberFormatter f = PhoneNumberFormatter.of();
      String p = "1234567890";
      assertEquals("(123)456-7890", f.format(p));
      
      StringBuffer s = new StringBuffer("Hello this is a phone number: ");
      f.formatTo(p, s);
      assertEquals("Hello this is a phone number: (123)456-7890", s.toString());
      
      f = PhoneNumberFormatter.of("(###)###-####");
      assertEquals("(123)456-7890", f.format(p));
      assertEquals("(555)456-7890", f.format("5554567890"));      
      
      f = PhoneNumberFormatter.of("(###) ###-####");
      assertEquals("(123) 456-7890", f.format(p));
      
      f = PhoneNumberFormatter.of("+1(###)###-####");
      assertEquals("+1(123)456-7890", f.format(p));
      
      f = PhoneNumberFormatter.of("\\#(###)\\####-");
      assertEquals("#(123)#456-7890", f.format(p));
      
      f = PhoneNumberFormatter.of("\\\\#(###)\\####-");
      assertEquals("\\#(123)#456-7890", f.format(p));
      
      f = PhoneNumberFormatter.of("(###)###-####-####");
      assertEquals("(123)456-7890-####", f.format(p));
      
      
  }
  
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.