GO语言程序中解决中文日期格式的解析问题

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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)
}
使⽤⽰例:
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 这两种格式了。

相关文档
最新文档