在Golang中完全解析时间戳

时间:2016-06-13 05:18:53

标签: json postgresql datetime go unmarshalling

我正在尝试创建一个简单的工具来解析文件中的JSON格式的行,并对数据库执行INSERT操作。

我有一个看起来像这样的结构:

type DataBlob struct {
  ....
  Datetime time.Time `json:"datetime, string"`
  ....
}

解析看起来像这样的代码:

scanner := bufio.NewScanner(file)
// Loop through all lines in the file
for scanner.Scan() {
    var t DataBlob

    // Decode the line, parse the JSON
    dec := json.NewDecoder(strings.NewReader(scanner.Text()))
    if err := dec.Decode(&t);
    err != nil {
        panic(err)
    }

    // Perform the database operation
    executionString: = "INSERT INTO observations (datetime) VALUES ($1)"
    _, err := db.Exec(executionString, t.Datetime)
    if err != nil {
        panic(err)
    }
}

我的JSON文件包含行,每行包含datetime值,如下所示:

{ "datetime": 1465793854 }

datetime被格式化为Unix时间戳时,Marshaller会抱怨:

panic: parsing time "1465793854" as ""2006-01-02T15:04:05Z07:00"": cannot parse "1465793854" as """

在生成JSON(也用Golang编写)的脚本中,我尝试简单地打印Time.time类型的String表示,产生以下内容:

{ "datetime": "2016-06-13 00:23:34 -0400 EDT" }

当我去解析时Marshaller抱怨的是:

panic: parsing time ""2016-06-13 00:23:34 -0400 EDT"" as ""2006-01-02T15:04:05Z07:00"": cannot parse " 00:23:34 -0400 EDT"" as "T"

如果我也将此时间戳(看起来非常标准)视为字符串并避免编组问题,Postgres在尝试执行插入时会抱怨:

panic: pq: invalid input syntax for type timestamp: "2016-06-13 00:23:34 -0400 EDT"

这在许多级别上令人沮丧,但主要是因为如果我序列化Time.time类型,我认为在该过程的另一方仍应理解它。

如何解析此时间戳以执行数据库插入?为冗长的问题道歉并感谢您的帮助!

2 个答案:

答案 0 :(得分:7)

JSON解析time.Time expects日期字符串为RFC 3339格式。

因此,在生成JSON的golang程序中,不要只打印time.Time值,而是使用Format以RFC 3339格式打印它。

t.Format(time.RFC3339)
  

如果我序列化Time.time类型,我认为它应该仍然是   在过程的另一方理解

如果您使用Marshaller interface进行序列化,它确实会以RFC 3339格式输出日期。因此,该过程的另一方将理解它。所以你也可以这样做。

d := DataBlob{Datetime: t}
enc := json.NewEncoder(fileWriter)
enc.Encode(d)

答案 1 :(得分:0)

作为参考,如果您需要使用时间类型进行自定义解组,则需要使用 UnmarshallJSON 方法创建自己的类型。带时间戳的示例

type Timestamp struct {
    time.Time
}

// UnmarshalJSON decodes an int64 timestamp into a time.Time object
func (p *Timestamp) UnmarshalJSON(bytes []byte) error {
    // 1. Decode the bytes into an int64
    var raw int64
    err := json.Unmarshal(bytes, &raw)

    if err != nil {
        fmt.Printf("error decoding timestamp: %s\n", err)
        return err
    }

    // 2 - Parse the unix timestamp
    *&p.Time = time.Unix(raw, 0)
    return nil
}

然后使用结构中的类型:

type DataBlob struct {
  ....
  Datetime Timestamp `json:"datetime"`
  ....
}