package model import ( "database/sql/driver" "encoding/json" "fmt" "time" ) // CustomTime 自定义时间类型,用于JSON序列化为YYYY-MM-DD HH:mm:ss格式 type CustomTime struct { time.Time } // MarshalJSON 自定义JSON序列化 func (ct CustomTime) MarshalJSON() ([]byte, error) { if ct.Time.IsZero() { return json.Marshal("") } return json.Marshal(ct.Time.Format("2006-01-02 15:04:05")) } // UnmarshalJSON 自定义JSON反序列化 // 支持格式: // 1. 数字时间戳:10位秒级(1732435200)或13位毫秒级(1732435200000) // 2. 字符串格式:秒级(2024-11-24 12:00:00)或毫秒级(2024-11-24 12:00:00.000) // 3. 空字符串:转换为零值时间 func (ct *CustomTime) UnmarshalJSON(data []byte) error { // 1. 尝试解析为数字时间戳 var timestamp int64 if err := json.Unmarshal(data, ×tamp); err == nil { if timestamp == 0 { ct.Time = time.Time{} return nil } // 根据位数判断精度:13位为毫秒级,10位为秒级 if timestamp > 9999999999 { ct.Time = time.UnixMilli(timestamp) } else { ct.Time = time.Unix(timestamp, 0) } return nil } // 2. 解析字符串格式 var str string if err := json.Unmarshal(data, &str); err != nil { return err } if str == "" { ct.Time = time.Time{} return nil } // 3. 使用本地时区解析时间,避免时区问题 // 尝试多种格式(按精度从高到低) formats := []string{ "2006-01-02 15:04:05.000", // 毫秒格式 "2006-01-02 15:04:05", // 秒格式(现有) } var lastErr error for _, format := range formats { t, err := time.ParseInLocation(format, str, time.Local) if err == nil { ct.Time = t return nil } lastErr = err } return lastErr } // Value 实现driver.Valuer接口,用于写入数据库 func (ct CustomTime) Value() (driver.Value, error) { if ct.Time.IsZero() { return nil, nil } return ct.Time, nil } // Scan 实现sql.Scanner接口,用于从数据库读取 func (ct *CustomTime) Scan(value interface{}) error { if value == nil { ct.Time = time.Time{} return nil } if t, ok := value.(time.Time); ok { ct.Time = t return nil } return fmt.Errorf("无法扫描 %T 到 CustomTime", value) } // NewCustomTime 创建一个新的 CustomTime 实例 func NewCustomTime(t time.Time) CustomTime { return CustomTime{Time: t} } // NowCustomTime 返回当前时间的 CustomTime 实例 func NowCustomTime() CustomTime { return CustomTime{Time: time.Now()} }