zoukankan      html  css  js  c++  java
  • 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() ([]byteerror) {
        return []byte(fmt.Sprintf(`"%s"`, time.Time(d).Format(DateFormat))), nil
    }

    func (d *Date) UnmarshalJSON(b []byteerror {
        nowerr := 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 nilnil
        }
        return time.Time(d), nil
    }

    func (d *Date) Scan(v interface{}) error {
        valueok := 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() ([]byteerror) {
        return []byte(fmt.Sprintf(`"%s"`, time.Time(t).Format(TimeFormat))), nil
    }

    func (t *DateTime) UnmarshalJSON(b []byteerror {
        nowerr := 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 nilnil
        }
        return time.Time(t), nil
    }

    func (t *DateTime) Scan(v interface{}) error {
        valueok := 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 这两种格式了。

  • 相关阅读:
    Visual Studio 2013各个版本密钥(亲测可用)
    Duilib bkimage 属性
    VC++ 文件夹的打开
    孙鑫- VC++在对话框程序中让对话框捕获WM_KEYDOWN消息
    OpenCV窗口置顶的方法
    OpenCV设置感兴趣区域(roi)
    Ubuntu 12,04安装ROS Hydro
    VC获取任务栏窗口及其子窗口句柄
    关于调用静态链接库LIB,提示重定义或库冲突的错误
    DuiLib如何禁用双击标题栏窗口最大化
  • 原文地址:https://www.cnblogs.com/bluedoctor/p/15311758.html
Copyright © 2011-2022 走看看