Search code examples
jsongogo-gormgo-gin

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


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"`
}

Solution

  • 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!