You've already forked VptPassiveAdapter
- 修改 config.yaml 中的 API 地址、存储配置及设备信息 - 新增 Viid 配置项支持新功能模块 - 在 go.mod 和 go.sum 中更新依赖包版本,引入新的第三方库 - 添加 model/custom_time.go 文件实现自定义时间类型的 JSON 序列化与反序列化 - 调整 DTO 结构体以适配新的配置项 - 升级 OTLP 导出器相关依赖并移除旧的标准输出导出器 - 引入 Gin 框架及相关中间件提升服务性能 - 更新 Protobuf 和 gRPC 相关依赖至最新版本 - 增加 zap 日志库和 lumberjack 日志轮转支持 - 添加 sonic、json-iterator 等高性能 JSON 处理库优化数据解析效率 - 引入 testify 断言库增强测试代码可读性 - 更新 sync 包版本提高并发安全性 - 添加 mock 工具支持单元测试模拟对象 - 引入 validator/v10 实现请求参数校验功能 - 更新 crypto、net、text 等标准库依赖确保安全性和兼容性 - 增加 mimetype 库用于文件类型识别 - 引入 quic-go 支持 HTTP/3 协议通信 - 添加 base64x
105 lines
2.4 KiB
Go
105 lines
2.4 KiB
Go
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()}
|
|
}
|