Is there any posibilities to change the default Bind timestamp format in gin-gionic?

2k Views Asked by At

I have a question in Go especially with gin-gionic and gorm.

Let's say I have model like this

// Classroom struct.
type Classroom struct {
    gorm.Model
    Name      string    `json:"name"`
    Code      string    `json:"code"`
    StartedAt time.Time `json:"started_at"`
}

I want to create data of Classroom Model with this JSON

{
  "name": "Math",
  "code": "math-mr-robie",
  "started_at": "2020-10-10 10:00:00"
}

But when I bind the JSON data, I got this following error

parsing time ""2020-10-10 10:00:00"" as ""2006-01-02T15:04:05Z07:00"": cannot parse " 10:00:00"" as "T"

I know that error appear because of the format that I sent was not the exact format of time.Time?

Is it possible to set default format of time.Time?

How to do that?

Because I've try to add .Format in after time.Time but error occurs.

// Classroom struct.
type Classroom struct {
    gorm.Model
    Name         string `json:"name"`
    Code         string `json:"code"`
    StartedAt    time.Time.Format("2006-01-02 15:04:05") `json:"started_at"`
}
2

There are 2 best solutions below

2
On BEST ANSWER

I resolve this issue by creating new struct JSONData that contain time inside it.

// JSONData struct.
type JSONData struct {
  Time time.Time
}

After I red Customize Data Types in Gorm and see some examples here then I add some methods


// Scan JSONDate.
func (j *JSONDate) Scan(value interface{}) (err error) {
    nullTime := &sql.NullTime{}
    err = nullTime.Scan(value)
    *j = JSONDate{nullTime.Time}
    return
}

// Value JSONDate.
func (j JSONDate) Value() (driver.Value, error) {
    y, m, d := time.Time(j.Time).Date()
    return time.Date(y, m, d, 0, 0, 0, 0, time.Time(j.Time).Location()), nil
}

// GormDataType gorm common data type
func (j JSONDate) GormDataType() string {
    return "timestamp"
}

For the gin things. Another resource @Eklavya given. So I add another methods.


// UnmarshalJSON JSONDate.
func (j *JSONDate) UnmarshalJSON(b []byte) error {
    s := strings.Trim(string(b), "\"")
    t, err := time.Parse(helpers.YMDHIS, s)
    if err != nil {
        return err
    }
    *j = JSONDate{
        Time: t,
    }
    return nil
}

// MarshalJSON JSONDate.
func (j JSONDate) MarshalJSON() ([]byte, error) {
    return []byte("\"" + j.Time.Format(helpers.YMDHIS) + "\""), nil
}

// Format method.
func (j JSONDate) Format(s string) string {
    t := time.Time(j.Time)
    return t.Format(helpers.YMDHIS)
}

And it's works!

0
On

I came across this question with the same issue and found that if you are looking for a specific time format like the ISOStrings sent from the browser you can have something like this;

type Classroom struct {
    gorm.Model
    Name      string    `json:"name"`
    Code      string    `json:"code"`
    StartedAt time.Time `json:"started_at" time_format:"RFC3339"`
}

With the time_format I did not need to define marshal functions to handle the formatting. However, if you need to do a completely custom format for your date and time then I believe you will need to define these functions.