Golang中如何配置GORM以特定格式在SQLite中存储日期
Golang中如何配置GORM以特定格式在SQLite中存储日期 我有这个表:
type Table struct {
Date time.Time `gorm:"column:date;type:datetime;default:current_timestamp;not null"`
}
但它是以这种格式存储的:
2023-10-25 23:36:29.4928236-05:00
我该如何让 gorm 以这种方式存储它?
10-25-2023 23:36:29.4928236-05:00
我以为GORM会通过自定义数据类型为我处理这个问题。
更多关于Golang中如何配置GORM以特定格式在SQLite中存储日期的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
是的,我也这么认为……
那么,这意味着如果我想以我偏好的格式存储数据,就必须使用文本类型而不是日期时间类型,对吗?
Sqlite 始终将日期存储为“YYYY-MM-DD HH:MM:SS”格式。因此,我认为问题在于如何以您想要的特定格式显示日期时间,您可以使用 time.Format 来应用您想要的模式。
func main() {
fmt.Println("hello world")
}
日期并非以字符串形式存储,那只是默认的显示格式。在后端,你应该始终使用 ISO8601 完整格式,而仅在前端根据不同的区域设置来显示日期或时间戳。
相信我,你绝对不想在后端以那种混乱的传统美国格式来存储日期。
默认格式可以自然排序,并且各个字段的含义是明确无歧义的。
在Golang中使用GORM配置SQLite以特定格式存储日期,可以通过自定义数据类型和序列化/反序列化逻辑实现。以下是实现方案:
import (
"database/sql/driver"
"fmt"
"time"
)
// CustomTime 自定义时间类型
type CustomTime struct {
time.Time
}
// 自定义格式
const customTimeFormat = "01-02-2006 15:04:05.9999999-07:00"
// Value 实现 driver.Valuer 接口,用于存储到数据库
func (ct CustomTime) Value() (driver.Value, error) {
if ct.IsZero() {
return nil, nil
}
return ct.Time.Format(customTimeFormat), nil
}
// Scan 实现 sql.Scanner 接口,用于从数据库读取
func (ct *CustomTime) Scan(value interface{}) error {
if value == nil {
ct.Time = time.Time{}
return nil
}
switch v := value.(type) {
case []byte:
return ct.parseTime(string(v))
case string:
return ct.parseTime(v)
case time.Time:
ct.Time = v
return nil
default:
return fmt.Errorf("无法扫描类型 %T 到 CustomTime", value)
}
}
// parseTime 解析时间字符串
func (ct *CustomTime) parseTime(str string) error {
t, err := time.Parse(customTimeFormat, str)
if err != nil {
// 尝试其他格式作为后备
t, err = time.Parse(time.RFC3339Nano, str)
if err != nil {
return err
}
}
ct.Time = t
return nil
}
// 在模型中使用自定义类型
type Table struct {
Date CustomTime `gorm:"column:date;type:text;default:(strftime('%m-%d-%Y %H:%M:%f', 'now', 'localtime'));not null"`
}
// 如果需要JSON序列化,可以添加MarshalJSON/UnmarshalJSON方法
func (ct CustomTime) MarshalJSON() ([]byte, error) {
if ct.IsZero() {
return []byte("null"), nil
}
return []byte(fmt.Sprintf(`"%s"`, ct.Time.Format(customTimeFormat))), nil
}
func (ct *CustomTime) UnmarshalJSON(data []byte) error {
str := string(data)
if str == "null" || str == `""` {
ct.Time = time.Time{}
return nil
}
// 移除JSON引号
if len(str) >= 2 && str[0] == '"' && str[len(str)-1] == '"' {
str = str[1 : len(str)-1]
}
return ct.parseTime(str)
}
// 使用示例
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic(err)
}
// 自动迁移
db.AutoMigrate(&Table{})
// 创建记录
now := CustomTime{Time: time.Now()}
table := Table{Date: now}
db.Create(&table)
// 查询记录
var result Table
db.First(&result)
fmt.Printf("存储的时间: %s\n", result.Date.Time.Format(customTimeFormat))
}
对于SQLite的默认值,可以使用SQLite的strftime函数:
type Table struct {
Date CustomTime `gorm:"column:date;type:text;default:(strftime('%m-%d-%Y %H:%M:%f', 'now', 'localtime'));not null"`
}
如果需要处理时区,可以这样调整:
const customTimeFormatWithTZ = "01-02-2006 15:04:05.9999999-07:00"
// 或者在解析时指定时区
func (ct *CustomTime) parseTime(str string) error {
loc, _ := time.LoadLocation("Local")
t, err := time.ParseInLocation(customTimeFormat, str, loc)
if err != nil {
t, err = time.Parse(time.RFC3339Nano, str)
if err != nil {
return err
}
}
ct.Time = t
return nil
}
这个实现确保了日期以"MM-DD-YYYY HH:MM:SS.FFFFFFF±HH:MM"格式在SQLite中存储和读取。


