I am beginner at golang. I am trying to take input from HTML input type date
<input type="date" id="birthDate" name="BirthDate" required placeholder="YYYY-MM-DD">
and post this create method
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 object:
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)"`
}
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 {"error":"parsing time \"2014-05-05\" as \"2006-01-02T15:04:05Z07:00\": cannot parse \"\" as \"T\""}
How can I solve this problem?
Thanks in advance
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:
<input type="date">
element is always formatted as yyyy-mm-dd
(See value of <input type="date">
).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?