Cómo convertir string a double con la información cultural apropiada

Tengo dos campos nvarchar en una base de datos para almacenar DataType y DefaultValue, y tengo un DataType Double y un valor como 65.89875 en formato inglés.

Ahora quiero que el usuario vea el valor según el formato de idioma del navegador seleccionado (65.89875 en inglés debe mostrarse como 65.89875 en alemán). Ahora bien, si el usuario edita desde el formato alemán hasta 65,89875, que es equivalente a 65,89875 en inglés, y las otras vistas de usuario desde un navegador en inglés, se obtiene como 6589875.

Esto sucede porque en la base de datos se almacenó como 65,89875 en la columna nvarchar y cuando se convierte usando cultura inglesa se convierte en 6589875 ya que considera , como un separador que es un operador decimal para el alemán.

¿Cómo hago que esto funcione para todos los navegadores?

Necesita definir una configuración regional única que usará para los datos almacenados en la base de datos, la cultura invariante está ahí exactamente para este propósito.

Cuando visualiza convertir al tipo nativo y luego formatea para la cultura del usuario.

Ej. Para mostrar:

 string fromDb = "123.56"; string display = double.Parse(fromDb, CultureInfo.InvariantCulture).ToString(userCulture); 

Almacenar:

 string fromUser = "132,56"; double value; // Probably want to use a more specific NumberStyles selection here. if (!double.TryParse(fromUser, userCulture, NumberStyles.Any, out value)) { // Error... } string forDB = value.ToString(CultureInfo.InvariantCulture); 

PD. Es casi innecesario decir que usar una columna con un tipo de datos que coincida con los datos sería incluso mejor (pero a veces se aplica el legado).

Recibí ayuda de MSDN, pero esta es mi respuesta:

 double number; string localStringNumber; string doubleNumericValueasString = "65.89875"; System.Globalization.NumberStyles style = System.Globalization.NumberStyles.AllowDecimalPoint; if (double.TryParse(doubleNumericValueasString, style, System.Globalization.CultureInfo.InvariantCulture, out number)) Console.WriteLine("Converted '{0}' to {1}.", doubleNumericValueasString, number); else Console.WriteLine("Unable to convert '{0}'.", doubleNumericValueasString); localStringNumber =number.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("de-DE")); 

Puede convertir el valor que el usuario proporciona en un doble y almacenarlo de nuevo como nvarchar, con la ayuda de FormatProviders . CultureInfo es un FormatProvider típico. Suponiendo que conoces la cultura que estás operando,

 System.Globalization.CultureInfo EnglishCulture = new System.Globalization.CultureInfo("en-EN"); System.Globalization.CultureInfo GermanCulture = new System.Globalization.CultureInfo("de-de"); 

será suficiente para hacer la transformación necesaria, como;

 double val; if(double.TryParse("65,89875", System.Globalization.NumberStyles.Float, GermanCulture, out val)) { string valInGermanFormat = val.ToString(GermanCulture); string valInEnglishFormat = val.ToString(EnglishCulture); } if(double.TryParse("65.89875", System.Globalization.NumberStyles.Float, EnglishCulture, out val)) { string valInGermanFormat = val.ToString(GermanCulture); string valInEnglishFormat = val.ToString(EnglishCulture); } 

Puede cambiar su cultura de interfaz de usuario a cualquier cosa que desee, pero debe cambiar el separador de números de esta manera:

 CultureInfo info = new CultureInfo("fa-IR"); info.NumberFormat.NumberDecimalSeparator = "."; Thread.CurrentThread.CurrentCulture = info; Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; 

Con esto, sus cadenas se convierten así: “12.49” en vez de “12.49” o “12/49”

Tengo esta función en mi toolbelt desde hace años (todos los nombres de funciones y variables son complicados y mezclan español e inglés, lo siento).

Permite al usuario usar , y . para separar los decimales y tratará de hacer lo mejor si se usan ambos símbolos.

  Public Shared Function TryCDec(ByVal texto As String, Optional ByVal DefaultValue As Decimal = 0) As Decimal If String.IsNullOrEmpty(texto) Then Return DefaultValue End If Dim CurAsTexto As String = texto.Trim.Replace("$", "").Replace(" ", "") ''// You can probably use a more modern way to find out the ''// System current locale, this function was done long time ago Dim SepDecimal As String, SepMiles As String If CDbl("3,24") = 324 Then SepDecimal = "." SepMiles = "," Else SepDecimal = "," SepMiles = "." End If If InStr(CurAsTexto, SepDecimal) > 0 Then If InStr(CurAsTexto, SepMiles) > 0 Then ''//both symbols was used find out what was correct If InStr(CurAsTexto, SepDecimal) > InStr(CurAsTexto, SepMiles) Then ''// The usage was correct, but get rid of thousand separator CurAsTexto = Replace(CurAsTexto, SepMiles, "") Else ''// The usage was incorrect, but get rid of decimal separator and then replace it CurAsTexto = Replace(CurAsTexto, SepDecimal, "") CurAsTexto = Replace(CurAsTexto, SepMiles, SepDecimal) End If End If Else CurAsTexto = Replace(CurAsTexto, SepMiles, SepDecimal) End If ''// At last we try to tryParse, just in case Dim retval As Decimal = DefaultValue Decimal.TryParse(CurAsTexto, retval) Return retval End Function