无法将float32值解组为字符串

时间:2014-04-27 17:54:15

标签: json floating-point go marshalling

我有一个JSON响应,它返回created字段的UNIX时间戳值:

"created_utc": 1395800038.0

---

// The type I use to marshal the response JSON.
// I can't use string because Golang complains the JSON is a float.
type Submission struct {
    CreatedUtc          float32         `json:"created_utc"`
}

我想将其转换为实际的Time对象:

const longForm = "Jan 2, 2006 at 3:04pm (MST)"
created_at, _ := time.Parse(longForm, string(created_utc))
  

./ main.go:57:无法将created_utc(类型为float32)转换为字符串


所以我有点卡在这里。我可以强制编组代码将时间戳转换为字符串,或者我可以将浮点值转换为time.Parse代码上的字符串 - 但是如果没有Golang抱怨我似乎无法做到。

3 个答案:

答案 0 :(得分:3)

您的代码存在一些问题:

将float32用于Unix时间戳

正如Nick Craig-Wood已经指出的那样,float32无法存储Unix时间戳而不会损失精度。虽然JSON标准不限制数字的精度,但Javascript将它们限制为IEEE 754 64位浮点值。

话虽这么说,将一个JSON数存储在float64变量中是一个好习惯,以避免失去精度,除非你确定数字适合int(无小数)或float32,或其他什么。

将float64转换为字符串以获取时间?

将float转换为字符串听起来像:

  

1395800038.0 => “1395800038.0”

我认为这不是你的意图,而是希望获得以下其中一项:

  1. var t time.Time = time.Unix(1395800038, 0)
  2. var s string = "Mar 26, 2014 at 2:13am (UTC)" // Or any other format
  3. 即使你的目标是获得字符串(2),你仍然需要创建time.Time变量(1)。所以它将分两步进行。

    <强>解决方案:

    package main
    
    import (
        "encoding/json"
        "fmt"
        "time"
    )
    
    var data = []byte(`{"created_utc": 1395800038.0}`)
    
    type Submission struct {
        CreatedUtc float64 `json:"created_utc"`
    }
    
    func main() {
        var sub Submission
        err := json.Unmarshal(data, &sub)
        if err != nil {
            panic(err)
        }
    
        // First step, convert float64 to a time.Time (after a quick conversion to int64 as well)
        dt := time.Unix(int64(sub.CreatedUtc), 0)
    
        // Second step, convert the timestamp to a string representation of your choice
        fmt.Println(dt.Format("2006-01-02 15:04:05"))
    }
    

    <强>结果:

    2014-03-26 02:13:58
    

    游乐场: http://play.golang.org/p/jNwzwc4dLg

答案 1 :(得分:2)

你应该使用int64来存储UNIX时间(浮点数没有意义)。

然后使用它将其转换为time.Time实例:

var x int64 = 1398621956

dt := time.Unix(x, 0) // setting nsec to 0
created_at := dt.Format("Jan 2, 2006 at 3:04pm (MST)")

fmt.Println(created_at)

如果你真的必须使用float float64(这会阻止解析问题)并使用它来转换为int64

var y float64 = 1398621956.0
x := int64(y)

答案 2 :(得分:2)

不要将unix时间戳存储在一个它不适合的float32中!

float32只有24位尾数 - 而当前的unix时间需要31位。

因此,如果你将一个unix时间存储在float32中,你的精确度会降低,例如

func main() {
    t := 1395800038.0
    v := float32(t)
    dv := float64(v) - t
    fmt.Printf("v = %f, difference is %f\n", v, dv)
}

打印

v = 1395800064.000000, difference is 26.000000

Playground

相关问题