如何将HTML DateTime转换为Golang的Time对象

huangapple go评论97阅读模式
英文:

How to convert HTML DateTime to Golang Time object

问题

我是你的中文翻译助手,以下是翻译的内容:

我是golang的初学者。
我正在尝试从HTML的日期输入中获取输入。

<input type="date" id="birthDate" name="BirthDate" required placeholder="YYYY-MM-DD">

并将其提交到create方法中。

func (c *customerController) CreateCustomer(ctx *gin.Context) {
	var customer Customer
	if err := ctx.ShouldBindJSON(&customer); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if err := c.service.CreateCustomer(customer); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create customer"})
		return
	}

	ctx.Status(http.StatusOK)
}

Customer对象:

    type Customer struct {
	ID        uint      `gorm:"primarykey"`
	FirstName string    `gorm:"type:varchar(100);not null"`
	LastName  string    `gorm:"type:varchar(100);not null"`
	BirthDate time.Time `gorm:"not null"`
	Gender    string    `gorm:"type:varchar(6);not null"`
	Email     string    `gorm:"type:varchar(100);not null;unique"`
	Address   string    `gorm:"type:varchar(200)"`
}

当我尝试添加新的Customer时,我收到Http错误400,因为HTML的日期类型与golang的Time对象不匹配。
错误消息是{"error":"parsing time \"2014-05-05\" as \"2006-01-02T15:04:05Z07:00\": cannot parse \"\" as \"T\""}
我该如何解决这个问题?
提前感谢您的帮助。

英文:

I am beginner at golang.
I am trying to take input from HTML input type date

&lt;input type=&quot;date&quot; id=&quot;birthDate&quot; name=&quot;BirthDate&quot; required placeholder=&quot;YYYY-MM-DD&quot;&gt;

and post this create method

func (c *customerController) CreateCustomer(ctx *gin.Context) {
	var customer Customer
	if err := ctx.ShouldBindJSON(&amp;customer); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: err.Error()})
		return
	}

	if err := c.service.CreateCustomer(customer); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;Failed to create customer&quot;})
		return
	}

	ctx.Status(http.StatusOK)
}

Customer object:

    type Customer struct {
	ID        uint      `gorm:&quot;primarykey&quot;`
	FirstName string    `gorm:&quot;type:varchar(100);not null&quot;`
	LastName  string    `gorm:&quot;type:varchar(100);not null&quot;`
	BirthDate time.Time `gorm:&quot;not null&quot;`
	Gender    string    `gorm:&quot;type:varchar(6);not null&quot;`
	Email     string    `gorm:&quot;type:varchar(100);not null;unique&quot;`
	Address   string    `gorm:&quot;type:varchar(200)&quot;`
}

When I try to add new Customer I get Http Error 400 because HTML date type is not match to golang Time object.
And error body is {&quot;error&quot;:&quot;parsing time \&quot;2014-05-05\&quot; as \&quot;2006-01-02T15:04:05Z07:00\&quot;: cannot parse \&quot;\&quot; as \&quot;T\&quot;&quot;}
How can I solve this problem?
Thanks in advance

答案1

得分: 2

我得到了Http错误400,因为HTML日期类型与golang的Time对象不匹配。

请避免这样思考问题。

真正的问题是:

  1. 在客户端,解析的<input type="date">元素的值始终以yyyy-mm-dd的格式进行格式化(参见value of <input type="date">)。
  2. 在服务器端,ctx.ShouldBindJSON使用encoding/json包来解组请求,它使用(*Time).UnmarshalJSON将时间解组为time.Time对象。(*Time).UnmarshalJSON要求时间必须是RFC 3339格式的带引号的字符串(即2006-01-02T15:04:05Z07:00)(参见(*Time).UnmarshalJSON)。

格式为yyyy-mm-dd的值不满足2006-01-02T15:04:05Z07:00,所以失败了。

要解决这个问题,你可以在客户端将值转换为RFC 3339格式,或者在服务器端实现json.Unmarshaler接口以支持yyyy-mm-dd

有一个提案支持时间格式的结构标签,如果实现了这个提案,处理这种情况将变得容易。该提案还展示了目前的解决方法。

最后需要注意的是,在实际应用中,你应该定义BirthDate time.Time的含义。例如,假设一个用户在时区+07:00中表示他的出生日期是1990-05-21,并且该值以1990-05-20T17:00:00Z的形式存储到数据库中。稍后,另一个用户在时区-03:00中加载该用户的个人资料。你会在页面上显示什么?

英文:

> I get Http Error 400 because HTML date type is not match to golang Time object.

Please avoid thinking the issue like this.

The real issue is that:

  1. On the client side, the parsed value of an &lt;input type=&quot;date&quot;&gt; element is always formatted as yyyy-mm-dd (See value of &lt;input type=&quot;date&quot;&gt;).
  2. On the server side, ctx.ShouldBindJSON uses the encoding/json package to unmarshal the request, which uses (*Time).UnmarshalJSON to unmarshal a time into a time.Time object. (*Time).UnmarshalJSON requires that the time must be a quoted string in the RFC 3339 format (namely, 2006-01-02T15:04:05Z07:00) (See (*Time).UnmarshalJSON).

The value in the format yyyy-mm-dd does not satisfy 2006-01-02T15:04:05Z07:00, that's why it failed.

To address the issue, you can either transform the value into RFC 3339 format on the client side, or implement the json.Unmarshaler interface to support yyyy-mm-dd on the server side.

There is a proposal to support struct tag for time.Format, which if implemented, would make it easy to handle this case. The proposal also shows how to workaround the issue as of now.

The last note is, in a real world application, you should define what BirthDate time.Time means. For example, imaging a user in the time zone +07:00 said his birth date is 1990-05-21, and the value is stored to the database as 1990-05-20T17:00:00Z. Later another user loads this user's profile in time zone -03:00. What will you display on the page?

huangapple
  • 本文由 发表于 2023年5月21日 05:29:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76297424.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定