GO语言程序中解决中文日期格式的解析问题
最近做一个使用gin框架的GO语言项目,需要将前端传递过来的中文日期格式的字符串转换成GO语言的时间类型,遇到了`parsing time xx as xx: cannot parse xx as xx` 这样的错误,原来这是GO语言特殊的时间格式引起的,它默认不是使用系统的时间格式,使用的时候需要进行转换。下面做一个笔记记录解决方法。
package util
import (
"fmt"
"time"
)
const (
DateFormat = "2006-01-02"
TimeFormat = "2006-01-02 15:04:05"
)
//add by dengtaihua 2021-08-15
//DateTime 中文格式处理,例如 "2021-08-15"
type Date time.Time
func (d Date) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, time.Time(d).Format(DateFormat))), nil
}
func (d *Date) UnmarshalJSON(b []byte) error {
now, err := time.ParseInLocation(`"`+DateFormat+`"`, string(b), time.Local)
if err != nil {
return fmt.Errorf("can not convert %v to date,must like format:yyyy-MM-dd,simple example : %v", string(b), DateFormat)
}
*d = Date(now)
return nil
}
func (d Date) Value() (driver.Value, error) {
var zeroTime time.Time
if time.Time(d).UnixNano() == zeroTime.UnixNano() {
return nil, nil
}
return time.Time(d), nil
}
func (d *Date) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*d = Date(value)
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
func (d Date) String() string {
return time.Time(d).Format(DateFormat)
}
//add by dengtaihua 2021-08-15
//DateTime 中文格式处理,例如 "2021-08-15 10:21:00"
type DateTime time.Time
func (t DateTime) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, time.Time(t).Format(TimeFormat))), nil
}
func (t *DateTime) UnmarshalJSON(b []byte) error {
now, err := time.ParseInLocation(`"`+TimeFormat+`"`, string(b), time.Local)
if err != nil {
return fmt.Errorf("can not convert %v to date,must like format:yyyy-MM-dd HH:mm:ss,simple example : %v", string(b), TimeFormat)
}
*t = DateTime(now)
return nil
}
func (t DateTime) Value() (driver.Value, error) {
var zeroTime time.Time
if time.Time(t).UnixNano() == zeroTime.UnixNano() {
return nil, nil
}
return time.Time(t), nil
}
func (t *DateTime) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*t = DateTime(value)
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
func (t DateTime) String() string {
return time.Time(t).Format(TimeFormat)
}
使用示例:
1 2 3 4 5 6 7 8 9 | type UpdateLeaveParam struct { Id uint `json: "id" ` // 请假记录ID ContactId uint `json: "contactId" ` // 宝宝请假的联系人 OperatorId uint `json: "operatorId" ` // 请假操作人 Device string `json: "device" ` // 请假操作使用的设备:PC/PAD/手机 LeaveDate util.Date `json: "date" ` // 请假时间 LeaveType int `json: "leaveType" ` // 请假类型:病假/事假 Reason string `json: "reason" ` // 请假原因 } |
上面的请假时间字段用的就是本文定义的 Date类型。但是这样用还有一个问题,上面这种结构体的定义中字段的注解使用了json格式,表示从HTTP请求的Body中解析json格式的数据,但是如果需要在GET请求中使用,需要把上面的 json替换成 form,即:
type UpdateLeaveParam struct { Id uint `form:"id"` // 请假记录ID ContactId uint `form:"contactId"` // 宝宝请假的联系人 OperatorId uint `form:"operatorId"` // 请假操作人 Device string `form:"device"` // 请假操作使用的设备:PC/PAD/手机 LeaveDate util.Date `form:"date"` // 请假时间 LeaveType int `form:"leaveType"` // 请假类型:病假/事假 Reason string `form:"reason"` // 请假原因 }
前端传参给date像这样:xxx?date=2021-09-01&id=1
GIN会报错:
invalid character '-' after top-level value
这个错误会在解析日期类型数据之前先报错。解决办法就是这种情况可以考虑 yyyyMMdd 这种日期格式,将本文的代码做相应修改:
const ( DateFormat = "2006-01-02" DateFormat2 = "20060102" TimeFormat = "2006-01-02 15:04:05" ) //其它代码略 func (d *Date) UnmarshalJSON(b []byte) error { now, err := time.ParseInLocation(`"`+DateFormat+`"`, string(b), time.Local) if err != nil { now2, err2 := time.Parse(DateFormat2, string(b)) if err2 != nil { return fmt.Errorf("can not convert %v to date,must like format:yyyy-MM-dd,simple example : %v", string(b), DateFormat) }else{ now= now2 } } *d = Date(now) return nil }
之后,我们的日期格式就兼容 yyyy-MM-dd 和 yyyyMMdd 这两种格式了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2016-09-19 Vue.js 入门指南之“前传”(含sublime text 3 配置)