如何在Go语言中将时间转换为UTC后再作为JSON进行封送?

bqujaahr  于 2022-12-15  发布在  Go
关注(0)|答案(2)|浏览(140)

我尝试定义一个Time结构体来实现Marshaler接口,这样当它被封送到JSON时,它就以YYYY-mm-ddTHH:MM:SSZ表示,也就是说,时间被转换成UTC并舍入到最接近的秒。

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "time"
)

type Time struct {
    time.Time
}

func (t *Time) MarshalJSON() ([]byte, error) {
    return []byte(t.Time.UTC().Round(time.Second).Format(time.RFC3339)), nil
}

func main() {
    tm := time.Now()
    // tm := time.Now().UTC().Round(time.Second)

    tmJSON, err := json.Marshal(tm)
    if err != nil {
        log.Fatalf("marshal time: %v", err)
    }

    fmt.Println(string(tmJSON))
}

但是,当我运行这个函数时,它会打印

> go run main.go
"2022-12-07T16:32:51.494597-08:00"

相反,如果传入time.Now().UTC().Round(time.Second)作为要封送的输入(即使用上面代码片段中注解掉的行),则会得到所需的输出:

> go run main.go
"2022-12-08T00:41:10Z"

我的问题是:为什么我不能在MarshalJSON方法本身中执行到UTC的转换并舍入到最近的秒?

6qftjkof

6qftjkof1#

你想干什么?
我试着运行你的MarshalJSON函数,它按预期工作
以下是我尝试做的:

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "time"
)

type Time struct {
    time.Time
}

func (t *Time) MarshalJSON() ([]byte, error) {
    return []byte(t.Time.UTC().Round(time.Second).Format(time.RFC3339)), nil
}

func main() {
    // tm := time.Now().UTC()
    tm := time.Now().UTC().Round(time.Second)

    tmJSON, err := json.Marshal(tm)
    if err != nil {
        log.Fatalf("marshal time: %v", err)
    }

    fmt.Println(string(tmJSON))

    marshal_time := Time{time.Now().UTC()}
    byt_arr, _ := marshal_time.MarshalJSON()
    fmt.Println(string(byt_arr))
}

我得到了以下输出:

"2022-12-08T04:41:59Z"
2022-12-08T04:41:59Z

第一行是前面的输出,第二行是MarshalJSON函数的输出。

f87krz0w

f87krz0w2#

您可以使用AppendFormat将时间字符串转换为缓冲区。
同样在您的问题中,您没有初始化用于编组的Time结构。
这是一个可能的解决办法

package main

import (
    "encoding/json"
    "errors"
    "fmt"
    "log"
    "time"
)

type Time struct {
    time.Time
}

func (t *Time) MarshalJSON() ([]byte, error) {
    if y := t.Year(); y < 0 || y >= 10000 {
        return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
    }

    b := make([]byte, 0, len(time.RFC3339)+2)
    b = append(b, '"')
    b = t.UTC().Round(time.Second).AppendFormat(b, time.RFC3339)
    b = append(b, '"')
    return b, nil
}

func main() {
    now := time.Now()
    mt := &Time{now}
    bytArr, err := json.Marshal(mt)
    if err != nil {
        log.Fatalf("marshal time: %v", err)
    }

    fmt.Println(string(bytArr))
}

相关问题