英文:
Golang gorm time data type conversion
问题
情况:
我正在使用一个 postgres 数据库,并且有以下的结构:
type Building struct {
ID int `json:"id,omitempty"`
Name string `gorm:"size:255" json:"name,omitempty"`
Lon string `gorm:"size:64" json:"lon,omitempty"`
Lat string `gorm:"size:64" json:"lat,omitempty"`
StartTime time.Time `gorm:"type:time" json:"start_time,omitempty"`
EndTime time.Time `gorm:"type:time" json:"end_time,omitempty"`
}
问题:
然而,当我尝试将这个结构体插入数据库时,出现了以下错误:
将时间“10:00:00”解析为“2006-01-02T15:04:05Z07:00”时出错:无法将“0:00”解析为“2006”。
可能是因为它没有将 StartTime
和 EndTime
字段识别为 Time 类型,而是使用了 Timestamp 类型。我该如何指定这些字段的类型为 Time?
附加信息:
以下代码片段展示了我创建 Building
的代码:
if err = db.Create(&building).Error; err != nil {
return database.InsertResult{}, err
}
Building 表的 SQL 代码如下:
DROP TABLE IF EXISTS building CASCADE;
CREATE TABLE building(
id SERIAL,
name VARCHAR(255) NOT NULL ,
lon VARCHAR(31) NOT NULL ,
lat VARCHAR(31) NOT NULL ,
start_time TIME NOT NULL ,
end_time TIME NOT NULL ,
PRIMARY KEY (id)
);
英文:
Situation:
I'm using a postgres database and have the following struct:
type Building struct {
ID int `json:"id,omitempty"`
Name string `gorm:"size:255" json:"name,omitempty"`
Lon string `gorm:"size:64" json:"lon,omitempty"`
Lat string `gorm:"size:64" json:"lat,omitempty"`
StartTime time.Time `gorm:"type:time" json:"start_time,omitempty"`
EndTime time.Time `gorm:"type:time" json:"end_time,omitempty"`
}
Problem:
However, when I try to insert this struct into the database, the following error occurs:
> parsing time ""10:00:00"" as ""2006-01-02T15:04:05Z07:00"": cannot
> parse "0:00"" as "2006""}.
Probably, it doesn't recognize the StartTime
and EndTime
fields as Time type and uses Timestamp instead. How can I specify that these fields are of the type Time?
Additional information
The following code snippet shows my Building
creation:
if err = db.Create(&building).Error; err != nil {
return database.InsertResult{}, err
}
The SQL code of the Building table is as follows:
DROP TABLE IF EXISTS building CASCADE;
CREATE TABLE building(
id SERIAL,
name VARCHAR(255) NOT NULL ,
lon VARCHAR(31) NOT NULL ,
lat VARCHAR(31) NOT NULL ,
start_time TIME NOT NULL ,
end_time TIME NOT NULL ,
PRIMARY KEY (id)
);
答案1
得分: 7
gorm不直接支持TIME类型,但你可以创建自己的类型,并实现sql.Scanner
和driver.Valuer
接口,以便能够从数据库中获取和存储时间值。
以下是一个示例实现,它重用/别名了time.Time
,但不使用日期、月份和年份数据:
const MyTimeFormat = "15:04:05"
type MyTime time.Time
func NewMyTime(hour, min, sec int) MyTime {
t := time.Date(0, time.January, 1, hour, min, sec, 0, time.UTC)
return MyTime(t)
}
func (t *MyTime) Scan(value interface{}) error {
switch v := value.(type) {
case []byte:
return t.UnmarshalText(string(v))
case string:
return t.UnmarshalText(v)
case time.Time:
*t = MyTime(v)
case nil:
*t = MyTime{}
default:
return fmt.Errorf("cannot sql.Scan() MyTime from: %#v", v)
}
return nil
}
func (t MyTime) Value() (driver.Value, error) {
return driver.Value(time.Time(t).Format(MyTimeFormat)), nil
}
func (t *MyTime) UnmarshalText(value string) error {
dd, err := time.Parse(MyTimeFormat, value)
if err != nil {
return err
}
*t = MyTime(dd)
return nil
}
func (MyTime) GormDataType() string {
return "TIME"
}
你可以像这样使用它:
type Building struct {
ID int `json:"id,omitempty"`
Name string `gorm:"size:255" json:"name,omitempty"`
Lon string `gorm:"size:64" json:"lon,omitempty"`
Lat string `gorm:"size:64" json:"lat,omitempty"`
StartTime MyTime `json:"start_time,omitempty"`
EndTime MyTime `json:"end_time,omitempty"`
}
b := Building{
Name: "test",
StartTime: NewMyTime(10, 23, 59),
}
为了正确支持JSON,你需要为json.Marshaler
/json.Unmarshaler
添加实现,这留给读者作为练习。
英文:
While gorm does not support the TIME type directly, you can always create your own type that implements the sql.Scanner
and driver.Valuer
interfaces to be able to put in and take out time values from the database.
Here's an example implementation which reuses/aliases time.Time
, but doesn't use the day, month, year data:
const MyTimeFormat = "15:04:05"
type MyTime time.Time
func NewMyTime(hour, min, sec int) MyTime {
t := time.Date(0, time.January, 1, hour, min, sec, 0, time.UTC)
return MyTime(t)
}
func (t *MyTime) Scan(value interface{}) error {
switch v := value.(type) {
case []byte:
return t.UnmarshalText(string(v))
case string:
return t.UnmarshalText(v)
case time.Time:
*t = MyTime(v)
case nil:
*t = MyTime{}
default:
return fmt.Errorf("cannot sql.Scan() MyTime from: %#v", v)
}
return nil
}
func (t MyTime) Value() (driver.Value, error) {
return driver.Value(time.Time(t).Format(MyTimeFormat)), nil
}
func (t *MyTime) UnmarshalText(value string) error {
dd, err := time.Parse(MyTimeFormat, value)
if err != nil {
return err
}
*t = MyTime(dd)
return nil
}
func (MyTime) GormDataType() string {
return "TIME"
}
You can use it like:
type Building struct {
ID int `json:"id,omitempty"`
Name string `gorm:"size:255" json:"name,omitempty"`
Lon string `gorm:"size:64" json:"lon,omitempty"`
Lat string `gorm:"size:64" json:"lat,omitempty"`
StartTime MyTime `json:"start_time,omitempty"`
EndTime MyTime `json:"end_time,omitempty"`
}
b := Building{
Name: "test",
StartTime: NewMyTime(10, 23, 59),
}
For proper JSON support you'll need to add implementations for json.Marshaler
/json.Unmarshaler
, which is left as an exercise for the reader 😉
答案2
得分: 0
如在“在使用GORM和Postgresql时如何在数据库中节省时间?”中提到:
目前,GORM不支持除了
timestamp with time zone
之外的任何日期/时间类型。
因此,您可能需要将时间解析为日期:
time.Parse("2006-01-02 3:04PM", "1970-01-01 9:00PM")
英文:
As mentioned in "How to save time in the database in Go when using GORM and Postgresql?"
> Currently, there's no support in GORM for any Date/Time types except timestamp with time zone
.
So you might need to parse a time as a date:
time.Parse("2006-01-02 3:04PM", "1970-01-01 9:00PM")
答案3
得分: 0
我遇到了相同的错误。看起来数据库中的列类型与 Gorm 模型不匹配。
可能是数据库中的列类型是文本类型,你可能之前设置了这个类型,然后在 Gorm 模型中更改了列类型。
英文:
I am have come across the same error. It seems like there is a mismatch between type of the column in the database and the Gorm Model
Probably the type of the column in the database is text which you might have set earlier and then changed the column type in gorm model.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论