Cómo formatear una cadena como número de teléfono en C #

163

Tengo una cadena "1112224444 'es un número de teléfono. Quiero formatear como 111-222-4444 antes de almacenarlo en un archivo. Está en un registro de datos y preferiría poder hacerlo sin asignar un nuevo variable.

Yo estaba pensando:

String.Format("{0:###-###-####}", i["MyPhone"].ToString() );

pero eso no parece hacer el truco.

** ACTUALIZACIÓN **

Okay. Fui con esta solución

Convert.ToInt64(i["Customer Phone"]).ToString("###-###-#### ####")

Ahora se estropea cuando la extensión tiene menos de 4 dígitos. Completará los números de la derecha. entonces

1112224444 333  becomes

11-221-244 3334

¿Algunas ideas?

Brian G
fuente
55
Tenga en cuenta que no todo el mundo tiene números de teléfono de 10 dígitos o utiliza el formato 111-222-4444.
Dour High Arch
Este fallará con números de teléfono empezando por 0
dano
Debe especificar si se trata solo de números de América del Norte o no.
Armstrongest
ADVERTENCIA: el hilo completo asume los números de teléfono de EE. UU. Use una biblioteca que admita números internacionales. nuget.org/packages/libphonenumber-csharp
Sean Anderson el

Respuestas:

204

Tenga en cuenta que esta respuesta funciona con tipos de datos numéricos (int, long). Si está comenzando con una cadena, primero deberá convertirla en un número. Además, tenga en cuenta que deberá validar que la cadena inicial tiene al menos 10 caracteres de longitud.

De una buena página llena de ejemplos:

String.Format("{0:(###) ###-####}", 8005551212);

    This will output "(800) 555-1212".

Aunque una expresión regular puede funcionar aún mejor, tenga en cuenta la antigua cita de programación:

Algunas personas, cuando se enfrentan a un problema, piensan: "Lo sé, usaré expresiones regulares". Ahora ellos tienen dos problemas.
--Jamie Zawinski, en comp.lang.emacs

Sean
fuente
¿Qué sucede, digamos si faltan algunos dígitos en el número de teléfono, como "800555" solamente? ¿Hay alguna manera de mostrar solo lo que está presente allí?
VoodooChild
11
Esta es una mala implementación porque si el código de área comienza con 0105555555 o algo así, terminará obteniendo (01) 555-5555 en lugar de (010) 555-5555. La razón es que si convierte el número de teléfono en un número, entonces se ve que el cero en el frente no es nada y, cuando lo formatea, el primer 0 se cae.
Paul Mendoza
3
@Paul Lea la definición del problema: "Tengo una cadena" 1112224444 'es un número de teléfono. Quiero formatear como 111-222-4444 antes de guardarlo en un archivo ".
Sean
39
Esto no funcionará si su número de teléfono es una cadena, como dicen las preguntas, a menos que primero lo convierta a un valor numérico.
JustinStolle
44
Sé que esto es solo repetir el comentario anterior, pero esta respuesta no respondió la pregunta. ¿Cómo formatea una cadena en un formato específico, en este caso un formato de número de teléfono?
dyslexicanaboko
168

Prefiero usar expresiones regulares:

Regex.Replace("1112224444", @"(\d{3})(\d{3})(\d{4})", "$1-$2-$3");
Ryan Duffield
fuente
44
Supongo que esto funcionaría, pero el formato .ToString () es más fácil de leer y debería funcionar mejor.
Joel Coehoorn
14
Si ya estoy lidiando con una cuerda, como ha dicho el afiche, lanzarla hacia atrás y volverla larga parece una tontería.
Ryan Duffield
Tal vez esto es lo que necesito después de todo. puede manejar la extensión mejor
Brian G
55
+1 para mantener el número como una cadena (dado que a menudo los números de teléfono utilizados para sistemas de SMS automatizados deben almacenarse en el formato +44)
Ed James
3
Estoy trabajando con diferentes formatos (por ejemplo, (111) 222-4444, 111.222.4444, etc.), pero los necesito normalizados a (111) 222-4444. También quería proteger contra números incompletos y usé la notación {n, m} . (Y disculpas por el formato, pero algunos de los formatos MD no funcionan para mí). // Remove non-digit characters var phoneDigits = Regex.Replace(crewMember.CellPhone, "[^\\d]", string.Empty); // Format the digits var phone = Regex.Replace(phoneDigits, @"(\d{1,3})(\d{0,3})(\d{0,4})", " ($1) $2-$3");
Craig Boland
46

Tendrás que dividirlo en subcadenas. Si bien podría hacerlo sin ninguna variable adicional, no sería particularmente agradable. Aquí hay una posible solución:

string phone = i["MyPhone"].ToString();
string area = phone.Substring(0, 3);
string major = phone.Substring(3, 3);
string minor = phone.Substring(6);
string formatted = string.Format("{0}-{1}-{2}", area, major, minor);
Jon Skeet
fuente
Jon, ¿estás seguro de que hacer tres subcadenas es mejor que usar string.format?
Pradeep
También uso String.Format, pero ¿cómo sugieres lograr el resultado sin usar String.Format?
Jon Skeet
2
Envolví eso en un if (phone.Length == 10) condición.
Zack Peterson el
Plus One: un pequeño punto: ese formato no parece tener paréntesis alrededor del código de área, tal vez lo estoy leyendo mal.
Mark Rogers
1
@ MarkRogers: La pregunta dice "Quiero formatear como 111-222-4444", no hay paréntesis allí.
Jon Skeet
28

Sugiero esto como una solución limpia para los números de EE. UU.

public static string PhoneNumber(string value)
{ 
    if (string.IsNullOrEmpty(value)) return string.Empty;
    value = new System.Text.RegularExpressions.Regex(@"\D")
        .Replace(value, string.Empty);
    value = value.TrimStart('1');
    if (value.Length == 7)
        return Convert.ToInt64(value).ToString("###-####");
    if (value.Length == 10)
        return Convert.ToInt64(value).ToString("###-###-####");
    if (value.Length > 10)
        return Convert.ToInt64(value)
            .ToString("###-###-#### " + new String('#', (value.Length - 10)));
    return value;
}
Jerry Nixon
fuente
1
Esto funcionó para mí con la excepción de que tuve que agregar un cheque para asegurarme de que el valor del teléfono no fuera NULL o Whitespace primero.
Caverman el
1
Esto funcionó para mí después de todos los anteriores que he probado
Eliotjse
22

Por lo que sé, no puedes hacer esto con string.Format ... tendrías que manejar esto tú mismo. Simplemente puede quitar todos los caracteres no numéricos y luego hacer algo como:

string.Format("({0}) {1}-{2}",
     phoneNumber.Substring(0, 3),
     phoneNumber.Substring(3, 3),
     phoneNumber.Substring(6));

Esto supone que los datos se han ingresado correctamente, que podría usar expresiones regulares para validar.

mattruma
fuente
44
Y asume un número de teléfono de América del Norte
Chris
19

Esto debería funcionar:

String.Format("{0:(###)###-####}", Convert.ToInt64("1112224444"));

O en su caso:

String.Format("{0:###-###-####}", Convert.ToInt64("1112224444"));
Vivek Shenoy
fuente
3
1 pequeño problema si estoy usando 01213456789 sus marcas (12) 345-6789 ... ¿alguna solución ...?
Sangram Nandkhile
55
Esta es la mejor solución. El cero inicial es discutible con respecto a los números de teléfono estadounidenses, ya que no hay códigos de área estadounidenses que comiencen con cero o uno.
JB
Pequeño problema si intenté 12345678 formatea (1) 234-5678 ... Pero lo que necesito es (123) 456-78. ¿Hay alguna solución para esto? Gracias
Kavitha P.
14

Si puede obtenerlo i["MyPhone"]como long, puede usar el long.ToString()método para formatearlo:

Convert.ToLong(i["MyPhone"]).ToString("###-###-####");

Vea la página de MSDN en cadenas de formato numérico .

Tenga cuidado de usar long en lugar de int: int podría desbordarse.

Joel Coehoorn
fuente
1
El problema con esto es si el número tiene más de 10 caracteres (es decir, incluye una extensión). Esto da como resultado una representación muy extraña donde 212-555-1212 x1234 aparece como2125551-212-1234.
Michael Blackburn
5
static string FormatPhoneNumber( string phoneNumber ) {

   if ( String.IsNullOrEmpty(phoneNumber) )
      return phoneNumber;

   Regex phoneParser = null;
   string format     = "";

   switch( phoneNumber.Length ) {

      case 5 :
         phoneParser = new Regex(@"(\d{3})(\d{2})");
         format      = "$1 $2";
       break;

      case 6 :
         phoneParser = new Regex(@"(\d{2})(\d{2})(\d{2})");
         format      = "$1 $2 $3";
       break;

      case 7 :
         phoneParser = new Regex(@"(\d{3})(\d{2})(\d{2})");
         format      = "$1 $2 $3";
       break;

      case 8 :
         phoneParser = new Regex(@"(\d{4})(\d{2})(\d{2})");
         format      = "$1 $2 $3";
       break;

      case 9 :
         phoneParser = new Regex(@"(\d{4})(\d{3})(\d{2})(\d{2})");
         format      = "$1 $2 $3 $4";
       break;

      case 10 :
         phoneParser = new Regex(@"(\d{3})(\d{3})(\d{2})(\d{2})");
         format      = "$1 $2 $3 $4";
       break;

      case 11 :
         phoneParser = new Regex(@"(\d{4})(\d{3})(\d{2})(\d{2})");
         format      = "$1 $2 $3 $4";
       break;

      default:
        return phoneNumber;

   }//switch

   return phoneParser.Replace( phoneNumber, format );

}//FormatPhoneNumber

    enter code here
guion bajo
fuente
entrada: 1234567890 salida:
123456
5

Si busca un número de teléfono (de EE. UU.) Para convertir en tiempo real. Sugiero usar esta extensión. Este método funciona perfectamente sin completar los números al revés. La String.Formatsolución parece funcionar al revés. Simplemente aplique esta extensión a su cadena.

public static string PhoneNumberFormatter(this string value)
{
    value = new Regex(@"\D").Replace(value, string.Empty);
    value = value.TrimStart('1');

    if (value.Length == 0)
        value = string.Empty;
    else if (value.Length < 3)
        value = string.Format("({0})", value.Substring(0, value.Length));
    else if (value.Length < 7)
        value = string.Format("({0}) {1}", value.Substring(0, 3), value.Substring(3, value.Length - 3));
    else if (value.Length < 11)
        value = string.Format("({0}) {1}-{2}", value.Substring(0, 3), value.Substring(3, 3), value.Substring(6));
    else if (value.Length > 10)
    {
        value = value.Remove(value.Length - 1, 1);
        value = string.Format("({0}) {1}-{2}", value.Substring(0, 3), value.Substring(3, 3), value.Substring(6));
    }
    return value;
}
James Copeland
fuente
Funciona perfecto para el movimiento hacia adelante. Pero cuando regresa, se atasca en el primer formato de (###).
Schwagmister
@Schwagmister Buena captura. Esto se ha corregido y he refactorizado el código a una extensión para uso general.
James Copeland el
4

También puedes probar esto:

  public string GetFormattedPhoneNumber(string phone)
        {
            if (phone != null && phone.Trim().Length == 10)
                return string.Format("({0}) {1}-{2}", phone.Substring(0, 3), phone.Substring(3, 3), phone.Substring(6, 4));
                return phone;
        }

Salida:

ingrese la descripción de la imagen aquí

atik sarker
fuente
1
Tenga en cuenta que los diferentes países tienen diferentes formatos y longitudes de números de teléfono y que las personas no podrán ingresarlos.
Neme
¿Cómo usaría esto con Html.DisplayFor (model => model.PhoneNumber)?
JustJohn
Usé este y descubrí cómo usarlo en la pantalla de Razor Page. Lo puse en un bloque @functions {} en la parte superior de la página. Luego me deshice del ayudante @ Html.DisplayFor y solo hice referencia a la función: ................. @GetFormattedPhoneNumber (Model.Courses_New.CurrentContactPhone) ¡Me alegro el día!
JustJohn
4

Es posible que te encuentres en la situación en la que tienes usuarios que intentan ingresar números de teléfono con todo tipo de separadores entre el código de área y el bloque de números principal (por ejemplo, espacios, guiones, puntos, etc.) Así que querrás pele la entrada de todos los caracteres que no son números para que pueda esterilizar la entrada con la que está trabajando. La forma más fácil de hacer esto es con una expresión RegEx.

string formattedPhoneNumber = new System.Text.RegularExpressions.Regex(@"\D")
    .Replace(originalPhoneNumber, string.Empty);

Entonces, la respuesta que ha enumerado debería funcionar en la mayoría de los casos.

Para responder lo que tiene sobre su problema de extensión, puede quitar cualquier cosa que sea más larga que la longitud esperada de diez (para un número de teléfono normal) y agregarlo al final usando

formattedPhoneNumber = Convert.ToInt64(formattedPhoneNumber)
     .ToString("###-###-#### " + new String('#', (value.Length - 10)));

Deberá hacer una verificación 'si' para determinar si la longitud de su entrada es mayor a 10 antes de hacer esto, si no, simplemente use:

formattedPhoneNumber = Convert.ToInt64(value).ToString("###-###-####");
Victor Johnson
fuente
3
Function FormatPhoneNumber(ByVal myNumber As String)
    Dim mynewNumber As String
    mynewNumber = ""
    myNumber = myNumber.Replace("(", "").Replace(")", "").Replace("-", "")
    If myNumber.Length < 10 Then
        mynewNumber = myNumber
    ElseIf myNumber.Length = 10 Then
        mynewNumber = "(" & myNumber.Substring(0, 3) & ") " &
                myNumber.Substring(3, 3) & "-" & myNumber.Substring(6, 3)
    ElseIf myNumber.Length > 10 Then
        mynewNumber = "(" & myNumber.Substring(0, 3) & ") " &
                myNumber.Substring(3, 3) & "-" & myNumber.Substring(6, 3) & " " &
                myNumber.Substring(10)
    End If
    Return mynewNumber
End Function
algo
fuente
Votado pero ... Esta es una respuesta de vb.net y la pregunta es c #
entrada: 1234567890 salida: (123) 456-789 ¡No funciona!
MC9000
3
        string phoneNum;
        string phoneFormat = "0#-###-###-####";
        phoneNum = Convert.ToInt64("011234567891").ToString(phoneFormat);
nirav gandhi
fuente
2

Prueba esto

string result;
if ( (!string.IsNullOrEmpty(phoneNumber)) && (phoneNumber.Length >= 10 ) )
    result = string.Format("{0:(###)###-"+new string('#',phoneNumber.Length-6)+"}",
    Convert.ToInt64(phoneNumber)
    );
else
    result = phoneNumber;
return result;

Salud.

Humberto Moreno
fuente
2

Use Match en Regex para dividir, luego envíe una cadena formateada con match.groups

Regex regex = new Regex(@"(?<first3chr>\d{3})(?<next3chr>\d{3})(?<next4chr>\d{4})");
Match match = regex.Match(phone);
if (match.Success) return "(" + match.Groups["first3chr"].ToString() + ")" + " " + 
  match.Groups["next3chr"].ToString() + "-" + match.Groups["next4chr"].ToString();
Sathyajith Bhat
fuente
2

Lo siguiente funcionará sin usar expresiones regulares

string primaryContactNumber = !string.IsNullOrEmpty(formData.Profile.Phone) ? String.Format("{0:###-###-####}", long.Parse(formData.Profile.Phone)) : "";

Si no usamos long.Parse, el string.format no funcionará.

Rama Krshna Ila
fuente
1
public string phoneformat(string phnumber)
{
String phone=phnumber;
string countrycode = phone.Substring(0, 3); 
string Areacode = phone.Substring(3, 3); 
string number = phone.Substring(6,phone.Length); 

phnumber="("+countrycode+")" +Areacode+"-" +number ;

return phnumber;
}

La salida será: 001-568-895623

Mak
fuente
1

Utilice el siguiente enlace para C # http://www.beansoftware.com/NET-Tutorials/format-string-phone-number.aspx

La forma más fácil de formatear es usar Regex.

private string FormatPhoneNumber(string phoneNum)
{
  string phoneFormat = "(###) ###-#### x####";

  Regex regexObj = new Regex(@"[^\d]");
  phoneNum = regexObj.Replace(phoneNum, "");
  if (phoneNum.Length > 0)
  {
    phoneNum = Convert.ToInt64(phoneNum).ToString(phoneFormat);
  }
  return phoneNum;
}

Pase su número de teléfono como cadena 2021231234 hasta 15 caracteres.

FormatPhoneNumber(string phoneNum)

Otro enfoque sería usar Substring

private string PhoneFormat(string phoneNum)
    {
      int max = 15, min = 10;
      string areaCode = phoneNum.Substring(0, 3);
      string mid = phoneNum.Substring(3, 3);
      string lastFour = phoneNum.Substring(6, 4);
      string extension = phoneNum.Substring(10, phoneNum.Length - min);
      if (phoneNum.Length == min)
      {
        return $"({areaCode}) {mid}-{lastFour}";
      }
      else if (phoneNum.Length > min && phoneNum.Length <= max)
      {
        return $"({areaCode}) {mid}-{lastFour} x{extension}";
      }
      return phoneNum;
    }
Mohammed Hossen
fuente
0

Para solucionar su problema de extensión, ¿qué tal si:

string formatString = "###-###-#### ####";
returnValue = Convert.ToInt64(phoneNumber)
                     .ToString(formatString.Substring(0,phoneNumber.Length+3))
                     .Trim();
Larry Smithmier
fuente
0

No para resucitar una vieja pregunta, pero pensé que podría ofrecer al menos un método un poco más fácil de usar, si es una configuración un poco más complicada.

Entonces, si creamos un nuevo formateador personalizado, podemos usar el formato más simple string.Formatsin tener que convertir nuestro número de teléfono along

Entonces, primero creemos el formateador personalizado:

using System;
using System.Globalization;
using System.Text;

namespace System
{
    /// <summary>
    ///     A formatter that will apply a format to a string of numeric values.
    /// </summary>
    /// <example>
    ///     The following example converts a string of numbers and inserts dashes between them.
    ///     <code>
    /// public class Example
    /// {
    ///      public static void Main()
    ///      {          
    ///          string stringValue = "123456789";
    ///  
    ///          Console.WriteLine(String.Format(new NumericStringFormatter(),
    ///                                          "{0} (formatted: {0:###-##-####})",stringValue));
    ///      }
    ///  }
    ///  //  The example displays the following output:
    ///  //      123456789 (formatted: 123-45-6789)
    ///  </code>
    /// </example>
    public class NumericStringFormatter : IFormatProvider, ICustomFormatter
    {
        /// <summary>
        ///     Converts the value of a specified object to an equivalent string representation using specified format and
        ///     culture-specific formatting information.
        /// </summary>
        /// <param name="format">A format string containing formatting specifications.</param>
        /// <param name="arg">An object to format.</param>
        /// <param name="formatProvider">An object that supplies format information about the current instance.</param>
        /// <returns>
        ///     The string representation of the value of <paramref name="arg" />, formatted as specified by
        ///     <paramref name="format" /> and <paramref name="formatProvider" />.
        /// </returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public string Format(string format, object arg, IFormatProvider formatProvider)
        {
            var strArg = arg as string;

            //  If the arg is not a string then determine if it can be handled by another formatter
            if (strArg == null)
            {
                try
                {
                    return HandleOtherFormats(format, arg);
                }
                catch (FormatException e)
                {
                    throw new FormatException(string.Format("The format of '{0}' is invalid.", format), e);
                }
            }

            // If the format is not set then determine if it can be handled by another formatter
            if (string.IsNullOrEmpty(format))
            {
                try
                {
                    return HandleOtherFormats(format, arg);
                }
                catch (FormatException e)
                {
                    throw new FormatException(string.Format("The format of '{0}' is invalid.", format), e);
                }
            }
            var sb = new StringBuilder();
            var i = 0;

            foreach (var c in format)
            {
                if (c == '#')
                {
                    if (i < strArg.Length)
                    {
                        sb.Append(strArg[i]);
                    }
                    i++;
                }
                else
                {
                    sb.Append(c);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        ///     Returns an object that provides formatting services for the specified type.
        /// </summary>
        /// <param name="formatType">An object that specifies the type of format object to return.</param>
        /// <returns>
        ///     An instance of the object specified by <paramref name="formatType" />, if the
        ///     <see cref="T:System.IFormatProvider" /> implementation can supply that type of object; otherwise, null.
        /// </returns>
        public object GetFormat(Type formatType)
        {
            // Determine whether custom formatting object is requested. 
            return formatType == typeof(ICustomFormatter) ? this : null;
        }

        private string HandleOtherFormats(string format, object arg)
        {
            if (arg is IFormattable)
                return ((IFormattable)arg).ToString(format, CultureInfo.CurrentCulture);
            else if (arg != null)
                return arg.ToString();
            else
                return string.Empty;
        }
    }
}

Entonces, si quieres usar esto, harías algo así:

String.Format(new NumericStringFormatter(),"{0:###-###-####}", i["MyPhone"].ToString());

Algunas otras cosas para pensar:

En este momento, si especificó un formateador más largo de lo que hizo una cadena para formatearlo, simplemente ignorará los signos # adicionales. Por ejemplo estoString.Format(new NumericStringFormatter(),"{0:###-###-####}", "12345"); daría como resultado 123-45, por lo que es posible que desee que tome algún tipo de posible carácter de relleno en el constructor.

Además, no proporcioné una forma de escapar de un signo #, por lo que si quisiera incluir eso en su cadena de salida, no podría hacerlo como está ahora.

La razón por la que prefiero este método sobre Regex es que a menudo tengo requisitos para permitir que los usuarios especifiquen el formato ellos mismos y es mucho más fácil para mí explicar cómo usar este formato que tratar de enseñarle a un usuario regex.

Además, el nombre de la clase es un poco inapropiado ya que en realidad funciona para formatear cualquier cadena siempre que desee mantenerla en el mismo orden y solo inyectar caracteres dentro de ella.

Kent Cooper
fuente
0

Puede probar {0: (000) 000 - ####} si su número objetivo comienza con 0.

Alice Guo
fuente
0

Aquí hay otra forma de hacerlo.

public string formatPhoneNumber(string _phoneNum)
{
    string phoneNum = _phoneNum;
    if (phoneNum == null)
        phoneNum = "";
    phoneNum = phoneNum.PadRight(10 - phoneNum.Length);
    phoneNum = phoneNum.Insert(0, "(").Insert(4,") ").Insert(9,"-");
    return phoneNum;
}
Neil Garcia
fuente