2010-04-06 11 views
30

J'ai deux champs nvarchar dans une base de données pour stocker DataType et DefaultValue, et j'ai un double DataType et une valeur 65.89875 en format anglais.Comment convertir une chaîne en double avec un cultureinfo approprié

Maintenant je veux que l'utilisateur voit la valeur selon le format de langue de navigateur choisi (65.89875 en anglais devrait être affiché comme 65.89875 en allemand). Maintenant, si l'utilisateur édite du format allemand à 65,89875 qui est 65,89875 équivalent en anglais, et les autres vues de l'utilisateur à partir d'un navigateur anglais, il s'agit de 6589875.

Cela se produit parce que dans la base de données, il était stocké 65,89875 dans la colonne nvarchar et lorsqu'il est converti en utilisant la culture anglaise, il devient 6589875 car il considère , comme un séparateur qui est un opérateur décimal pour l'allemand.

Comment puis-je obtenir ce travail pour tous les navigateurs?

+0

Pourquoi es-tu st oring nombres comme texte pour commencer? Si vous pouvez éventuellement changer le schéma, je vous suggère fortement de le faire. –

Répondre

1

Vous pouvez convertir la valeur fournie par l'utilisateur en double et la mémoriser de nouveau en tant que nvarchar, à l'aide de FormatProviders. CultureInfo est un FormatProvider typique. En supposant que vous connaissez la culture que vous exploitez,

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

suffisent à faire la transformation neccesary, comme;

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); 
} 
+1

"de-de" est le nom de l'allemand en Allemagne. – Richard

+0

@Richard, je l'ai cherché mais je n'ai pas trouvé, merci. – tafa

54

Vous devez définir une seule locale que vous utiliserez pour les données stockées dans la base de données, la culture invariante est là exactement dans ce but.

Lorsque vous affichez la conversion au type natif, puis formatez pour la culture de l'utilisateur.

E.g. à afficher:

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

pour stocker:

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); 

PS. Il va presque sans dire que l'utilisation d'une colonne avec un type de données correspondant aux données serait encore meilleure (mais parfois l'héritage s'applique).

0

J'ai cette fonction dans ma toolbelt depuis des années (tous les noms de fonctions et de variables sont désordonnés et mélangent l'espagnol et l'anglais, désolé pour cela).

Il permet à l'utilisateur d'utiliser , et . pour séparer les décimales et essaiera de faire de son mieux si les deux symboles sont utilisés.

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 
1

Vous pouvez modifier votre culture d'interface utilisateur pour tout ce que vous voulez, mais vous devez changer le séparateur de numéro comme celui-ci:

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

Avec cela, vos chaînes convertit comme ceci: « 12,49 » au lieu de " 12,49" ou "12/49"

1

j'ai pris un peu d'aide de MSDN, mais voici ma réponse:

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"));