Files
assetx/webapp-back/models/nulltime.go

68 lines
1.4 KiB
Go
Raw Normal View History

package models
import (
"database/sql/driver"
"encoding/json"
"strings"
"time"
)
// NullTime wraps *time.Time with custom JSON and GORM handling:
// - JSON marshal: nil → "1970-01-01T00:00:00Z", non-nil → RFC3339
// - JSON unmarshal: null / "" / "1970-01-01..." → nil (stored as NULL in DB)
// - GORM Scan/Value: nil ↔ NULL column
type NullTime struct {
Time *time.Time
}
func (nt NullTime) MarshalJSON() ([]byte, error) {
if nt.Time == nil {
return []byte(`"1970-01-01T00:00:00Z"`), nil
}
return json.Marshal(nt.Time.Format(time.RFC3339))
}
func (nt *NullTime) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
nt.Time = nil
return nil
}
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
if s == "" || strings.HasPrefix(s, "1970-01-01") {
nt.Time = nil
return nil
}
t, err := time.Parse(time.RFC3339, s)
if err != nil {
return err
}
nt.Time = &t
return nil
}
// Value implements driver.Valuer so GORM writes NULL for nil.
func (nt NullTime) Value() (driver.Value, error) {
if nt.Time == nil {
return nil, nil
}
return *nt.Time, nil
}
// Scan implements sql.Scanner so GORM reads NULL as nil.
func (nt *NullTime) Scan(value interface{}) error {
if value == nil {
nt.Time = nil
return nil
}
t, ok := value.(time.Time)
if !ok {
nt.Time = nil
return nil
}
nt.Time = &t
return nil
}