z3nth10n
z3nth10n

Reputation: 2451

Detect IFormatProvider or CultureInfo from String using VB.NET

Well, for avoiding Format Exceptions in a Convert.ToDecimal, ToSingle, and ToDouble, I use a Foreach with an array of CultureInfo class, but, is there a method for detecting which are the "possible cultures" from a string? (I say possible cultures because some culture shares their format.)

An example: If I use "1,080.47" I want to return en-US, and if I use "1.080,47" I want to return fr-FR, es-ES, etc.

What do you recommend?

Upvotes: 2

Views: 1482

Answers (2)

Just to be clear, and I'll quote MSDN

*In the .NET Framework 4 and previous versions, by default, the culture of all threads is set to the Windows system culture*

However, there's a distinction between input and output. I'll start with the trivial part.

Output

This is the easy one. We're in control. If the user wants a , as a decimal separator , so shall be done.

decimalValue.ToString(123.456, CultureInfo.GetCultureInfo("nb-NO"))

Output:

123,456

Input

This is the tricky part. I'm a Norwegian (as I guess you've figured out), and yes, we use the comma (,) as a decimal separator. Does this mean that all my fellows will input , instead of .? No. So applies to dates. Some users input dd-MM-yyyy "instead" of dd.MM.yyyy. Welcome to the UXD. However (and this might not be true for others), I'm yet to see a user trying to input a thousand separator when working with floating numbers.


Conclusion

My best advice is to use the default Culture Info as the output, and as implied, format the user input if not valid.

Note

FYI, the Culture Info reveals many a useful properties. Here's a few related to my anwwer:

  • CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator
  • CultureInfo.CurrentCulture.DateTimeFormat.DateSeparator

Upvotes: 0

ElektroStudios
ElektroStudios

Reputation: 20464

The same numeric formatting can pertains to various cultures, so maybe I'm wrong but I'll imagine that the best you could do is match the valid cultures for an specific format and then use your own logic to decide, something like this which is only an example for Single:

Public Function MatchCultures(ByVal str As String) as list(of string)

    Dim ValidCultures As New List(Of String)

    Dim CultureNames As IEnumerable(Of String) =
        From cultureInfo In cultureInfo.GetCultures(CultureTypes.AllCultures)
        Select cultureInfo.Name

    For Each CultureName As String In CultureNames

        Try

            Convert.ToSingle(str, New CultureInfo(CultureName))
            ValidCultures.Add(CultureName)

        Catch ex As FormatException
            ' Do nothing

        End Try

    Next

    Return ValidCultures

End Function

Also you could speed-up the procedure if you want to limit the CultureNames to a specific range lets say { "en-Us", "fr", "es", etc... } 'cause the list of culture-names is too big: http://msdn.microsoft.com/es-es/goglobal/bb896001.aspx

Anyways I think that you're approaching the problem into a bad solution, you should use the "TryParse" helper methods from datatypes like:

If Single.TryParse("1.000", New Single) Then...

Upvotes: 2

Related Questions