Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse currency / float string to float type based on locale in go

I am puzzled how to parse a "float-string" to a float, based on knowing the i18n-locale but not making presumptions about the string.

Example: Germans, like me, write "1.234,87" when Americans write "1,234.87". In my project I do know what locale I do expect, but I do not want to "hard code" what presumptions I have about how that local writes that stuff.

I would hate to do regexp/stringreplacements.

Is there a generic way to say something like

myFloat := ParseFloatByLocale("1.234,76", "DE-DE")
// myFloat => 1234.76

strconvdoesn't seem to have this functionality, neither does x/text/language

Grateful for any hints!

like image 209
huehnerhose Avatar asked Jul 13 '17 11:07

huehnerhose


People also ask

How to convert string to float in Go?

String to floatUse the strconv. ParseFloat function to parse a string as a floating-point number with the precision specified by bitSize : 32 for float32 , or 64 for float64 . When bitSize is 32, the result still has type float64 , but it will be convertible to float32 without changing its value.

How to convert float 64 to string golang?

In order to convert Float value into string type in Golang, you can use the following methods. You can use the strconv package's FormatFloat() function to convert the float into an string value. FormatFloat converts the floating-point number f to a string, according to the format fmt and precision prec.

What is float parse?

The parseFloat() method in Float Class is a built in method in Java that returns a new float initialized to the value represented by the specified String, as done by the valueOf method of class Float. Syntax: public static float parseFloat(String s)


1 Answers

Your best bet is the use the standard library's strconv. You can make your own wrappers and locale stuff. Eventually I'd add more error checking and turn this into it's own package, but here is an idea. If you haven't found a package yet there is a good chance you will have to write your own. For a more general solution, you'd have to think about every possible input.. normalize that per locale and enforce those rules when others are using your tools... That would be a more complex solution given the number of if statements and pieces of logic.. The good part is that you know the type of input strconv.ParseFloat expects.. So all you really have to do is take the user input and transform it to the programmatic standard http://floating-point-gui.de/formats/fp/. Given numbers are mostly universal, with the exception of commas and decimal points, there shouldn't be many use cases. You might even be able to generalize further and say there are two main formats.. https://www.quora.com/Why-do-some-countries-use-a-period-and-others-use-a-comma-to-separate-large-numbers, which is largely broken down to Europe et al and British/American, where German uses the standard almost all of Europe does. Under that assumption there isn't really much to do as the use cases comes down to 2.

package main

import (
    "fmt"
    "log"
    "strconv"
    "strings"
)

func normalizeGerman(old string) string {
    s := strings.Replace(old, ",", ".", -1)
    return strings.Replace(s, ".", "", 1)
}
func normalizeAmerican(old string) string {
    return strings.Replace(old, ",", "", -1)
}

var locale map[string]func(string) string

func init() {
    locale = make(map[string]func(string) string)
    locale["DE-DE"] = normalizeGerman
    locale["US"] = normalizeAmerican
}

func main() {
    var f, f2 float64
    var err error
    // german
    if val, ok := locale["DE-DE"]; ok {
        f, err = strconv.ParseFloat(val("1.234,87"), 64)
        if err != nil {
            log.Fatal("german fail", err)
        }
    }
    //american
    if val, ok := locale["US"]; ok {
        f2, err = strconv.ParseFloat(val("1,234.87"), 64)
        if err != nil {
            log.Fatal("american fail", err)
        }
    }

    fmt.Println(f, f2)

}
like image 141
reticentroot Avatar answered Oct 17 '22 01:10

reticentroot