前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GO语言程序中解决中文日期格式的解析问题

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

作者头像
用户1177503
发布2021-11-30 16:58:41
2.3K0
发布2021-11-30 16:58:41
举报
文章被收录于专栏:程序员的SOD蜜

最近做一个使用gin框架的GO语言项目,需要将前端传递过来的中文日期格式的字符串转换成GO语言的时间类型,遇到了`parsing time xx as xx: cannot parse xx as xx` 这样的错误,原来这是GO语言特殊的时间格式引起的,它默认不是使用系统的时间格式,使用的时候需要进行转换。下面做一个笔记记录解决方法。

代码语言:javascript
复制
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)
}

使用示例:

代码语言:javascript
复制
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,即:

代码语言:javascript
复制
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会报错:

代码语言:javascript
复制
invalid character '-' after top-level value

这个错误会在解析日期类型数据之前先报错。解决办法就是这种情况可以考虑 yyyyMMdd 这种日期格式,将本文的代码做相应修改:

代码语言:javascript
复制
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 这两种格式了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档