Go 时间的格式化
解决方案⌗
实现 MarshalJSON 接口⌗
type Log struct {
Id int64 `json:"id"`
UserId string `json:"user_id"`
Operation string `json:"operation"`
Result string `json:"result"`
CreatedAt time.Time `json:"created_at"`
}
func (log *Log) MarshalJSON() ([]byte, error) {
type Alias Log
return json.Marshal(&struct {
Alias
CreatedAt string `json:"created_at"`
}{
Alias: Alias(*log),
CreatedAt: log.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
这种方式比较简单,但是如果你有很多 struct 都包含时间,那么需要为每个 struct 实现 MarshalJSON,比较麻烦。并且在反向序列化时也存在 created_at 为 null 则反序列化失败的问题。
至于为什么时间格式是 2006-01-02 15:04:05,可以参考 time 这个包的 fromat.go 中定义的常量。
自已定一个 Time 数据类型⌗
package utils
import (
"time"
)
type (
Time time.Time
)
const DefaultTimeFormat = "2006-01-02 15:04:05"
func (t *Time) UnmarshalJSON(data []byte) error {
now, err := time.ParseInLocation(`"`+DefaultTimeFormat+`"`, string(data), time.Local)
*t = Time(now)
return err
}
func (t *Time) MarshalJSON() ([]byte, error) {
if time.Time(*t).IsZero() {
return []byte("null"), nil
}
b := make([]byte, 0, len(DefaultTimeFormat)+2)
b = append(b, '"')
b = time.Time(*t).AppendFormat(b, DefaultTimeFormat)
b = append(b, '"')
return b, nil
}
func (t Time) String() string {
return time.Time(t).Format(DefaultTimeFormat)
}
func (t *Time) IsZero() bool {
return time.Time(*t).Second() == 0 && time.Time(*t).Nanosecond() == 0
}
定义好时间的类型后,在其他的 struct 中使用该类型作为时间的类型。
Node struct {
Id string `json:"id"`
Name string `json:"name"`
CreatedAt utils.Time `json:"created_at"`
UpdatedAt utils.Time `json:"updated_at"`
}
这样当 Node 在序列化和反序列化时会自动调用自定义 utils.Time
的 MarshalJSON
和 UnmarshalJSON
方法。
注意:在
MarshalJSON
方法中,如果你的 utils.Time 为空,那么将其转换为 null,而不是 0001-01-01 00:00:00 +0000 UTC。
如果你有更好的方案,请告诉我,谢谢!
I hope this is helpful, Happy hacking…