gorm中created_at 时间,go time时间,mysql数据库时间的一些问题总结
问题1 gorm中created_at 时间
在生成的时候发现数据库的时间慢了8个小时,后来发现是需要在连接数据库的时候加上参数&loc=local
func init(){driverName := viper.GetString("datasource.driverName")host := viper.GetString("datasource.host")port := viper.GetString("datasource.port")database := viper.GetString("datasource.database")username := viper.GetString("datasource.username")password := viper.GetString("datasource.password")charset := viper.GetString("datasource.charset")args := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=True&loc=Local", //loc=local不能忘记username,password,host,port,database,charset)db, err := gorm.Open(driverName, args)if err != nil {panic("failed to connect database err: " + err.Error())}db.AutoMigrate(&defs.Users{})db.AutoMigrate(&defs.Video_Info{})db.AutoMigrate(&ments{})db.AutoMigrate(&defs.Sessions{})dbConn=db}
问题2 go内置的time一些问题
使用time.Parse()
解析字符串生成的时间的时区是UTC,而你调用time.Now()
则是CST,这导致你数据库中查时间段的数据会出错,如下代码
func TestListComments(t *testing.T) {vid:="123"layout:="Jan 02 , 15:04:05"from,_:=time.Parse(layout,"Dec 14 , 20:18:15")//不加载时区fromUnix:=from.Unix()fmt.Println(from)fmt.Println(fromUnix)to:=time.Now()toUnix:=to.Unix()fmt.Println(to)fmt.Println(toUnix)comments, err := ListComments(vid, fromUnix, toUnix)if err!=nil{t.Errorf("Error of list comments:%v",err)}for _,val:=range comments{fmt.Printf("%#v",val)}}
输出有误
-12-14 20:18:15 +0000 UTC1639513095 //开始时间反而大于 结束时间,因为时区不对-12-14 21:22:25.3100649 +0800 CST m=+0.0324576011639488145
解析字符串并加载时区之后,时区一致
func TestListComments(t *testing.T) {vid:="123"layout:="Jan 02 , 15:04:05"// 加载时区loc, err := time.LoadLocation("Asia/Shanghai") //一定要这个否则会弄错的from,_:=time.ParseInLocation(layout,"Dec 14 , 20:18:15",loc)fromUnix:=from.Unix()fmt.Println(from)fmt.Println(fromUnix)to:=time.Now()toUnix:=to.Unix()fmt.Println(to)fmt.Println(toUnix)comments, err := ListComments(vid, fromUnix, toUnix)if err!=nil{t.Errorf("Error of list comments:%v",err)}for _,val:=range comments{fmt.Printf("%#v",val)}}
输出
-12-14 20:18:15 +0800 CST1639484295-12-14 21:20:16.129897 +0800 CST m=+0.0886331011639488016.....一些comment数据
问题3 mysql中的时间问题
我用gorm查询某个时间段的评论代码如下,可以看到我是以from和to 两个int64 类型,来作为查询条件,这是为了对应go中的unix时间戳也是int64
func ListComments(vid string ,from,to int64) ([]*mentWithName,error) {lock.RLock()defer lock.RUnlock()var res []*mentWithNamedbConn.Debug().Raw("select comments.id,users.username,comments.content FROM comments "+"INNER JOIN users on comments.author_id=users.id where comments.video_id=? AND comments.created_at > FROM_UNIXTIME(?) AND "+"comments.created_at <= FROM_UNIXTIME(?)", vid, from, to).Scan(&res)return res,nil}
但是他在Mysql内部执行的时候出了一些问题,什么问题呢,也是时区问题。
关键在于FROM_UNIXTIME(?)
这个函数,他这个函数是将unix时间戳转为正常时间,这个正常时间是和时区有关的,你相同的unix时间戳转为不同时区的正常时间,它是不一样的。
所导致的问题
这会导致一个什么问题,就是你在插入评论的时候,插入的created_at这个字段的值是你的时区时间,但是你在查找的时候,mysql调用FROM_UNIXTIME(?)
这个函数转化的时间又是另外时区的时间,那么你查询的时候就会出问题。
基础命令熟悉
在实验之前,先准备一下基础的命令
FROM_UNIXTIME(unix_timestamp,format)
返回表示 Unix 时间标记的一个字符串,根据format字符串格式化。format可以包含与DATE_FORMAT()函数列出的条目同样的修饰符。
SELECT FROM_UNIXTIME(1234567890, '%Y-%m-%d %H:%i:%S')
正常时间格式转换成unix时间戳
select unix_timestamp(current_date);
show variables like "%time_zone%";
查看时区
±-----------------±-------+
| Variable_name | Value |
±-----------------±-------+
| system_time_zone | CST |
| time_zone | SYSTEM |
±-----------------±-------+
2 rows in set (0.00 sec)
#time_zone说明mysql使用system的时区,system_time_zone说明system使用CST时区
修改时区
set global time_zone = '+8:00';
##修改mysql全局时区为北京时间,即我们所在的东8区
set time_zone = '+8:00';
##临时修改,只用于当前会话
flush privileges;
#立即生效
然后当你设置不同的时区的时候,把unix时间戳转为正常时间就会不一样
情况1 当时区为+8.00
system_time_zone
time_zone
+08:00
执行
select from_unixtime(1639484295,'%Y-%m-%d %H:%i:%S')
得到
-12-14 20:18:15
情况2 当时区为+0.00
system_time_zone
time_zone
+00:00
执行
select from_unixtime(1639484295,'%Y-%m-%d %H:%i:%S')
得到
-12-14 12:18:15
差了8个小时
因此即然时间不对,那么你去查找某一时间段的内容,当然也会找不出。
所以在使用这三个内容的时候需要注意时间问题