无法将float32值解组为字符串

I have a JSON response that returns a UNIX timestamp value for the created field:

"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"`
}

I want to convert this to an actual Time object:

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

./main.go:57: cannot convert created_utc (type float32) to type string


So I'm sort of stuck here. Either I can force the marshal code to convert the timestamp to a string, or I can convert the float value to a string on the time.Parse code - but I can't seem to do either without Golang complaining.

You should use int64 to store the UNIX time (float doesn't make sense).

Then use this to convert it to a time.Time instance:

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)

If you really have to use float use float64 (this will prevent the parsing issue) and use this to convert to int64:

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

Don't store a unix timestamp in a float32 it doesn't fit!

A float32 has only 24 bits of mantissa - whereas a current unix time needs 31 bits.

So if you do store a unix time in a float32 you'll get reduced precision, eg

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

Which prints

v = 1395800064.000000, difference is 26.000000

(Playground)

You need to check your other question's answer here....

Anyway, that's a unix timestamp (in javascript +(new Date())), you can use time.Unix to convert it to time.Time :

Play link

func main() {
    t := 1395800038.0
    fmt.Println(time.Unix(int64(t), 0))
}
//output : 2014-03-26 02:13:58 +0000 UTC

There are a few things wrong with your code:

Using float32 for a Unix timestamp

As Nick Craig-Wood already pointed out, a float32 cannot store a Unix timestamp without loss of precision. And while the JSON standard doesn't restrict the precision of a number, Javascript restricts them to IEEE 754 64-bit floating point values.

That being said, it is a good practice to store JSON numbers in float64 variables to avoid loosing precision, unless you are certain the number fits well in an int (no decimals) or float32, or whatever.

Converting float64 to string to get Time?

Converting float to string sounds like:

1395800038.0 => "1395800038.0"

I will assume that is not your intent, but rather that wish to get one of the following:

  1. var t time.Time = time.Unix(1395800038, 0)
  2. var s string = "Mar 26, 2014 at 2:13am (UTC)" // Or any other format

And even if your aim is to get to the string (2), you still would need to create the time.Time variable (1). So it will happen in two steps.

Solution:

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

Result:

2014-03-26 02:13:58

Playground: http://play.golang.org/p/jNwzwc4dLg