我回来了!最近开始了在腾讯广告的实习生活,也算是完成了本科一定要经历一次开发实习的心愿。
第一周熟悉环境,熟悉代码,做了一些零零散散的小需求。这周终于开始负责一些比较独立的需求了。每天都要经历接任务->coding->merge request->code review->approve->merged的过程,感觉压力还是挺大的。自己以前写代码感觉比较像是野蛮生长,功能实现了就完事了。但是在公司写代码,每一行都要小心翼翼,很怕被喷或者出糗。还有一点感受就是把细节处理好其实是很难的事情。再小的需求也有很多细节需要去注意。所以在博客里开个坑,记录一下实习期间遇到的一些问题和感受~
Gorm读取timeStamp类型
gorm是一个go的orm框架。在使用他读取timeStamp的时候,可以直接使用time.Time
1 | type DagRun struct { |
但是有一点要注意,在定义dateSource的时候一定要记得开启parseTime=True.
1 | dbsource = "root:@tcp(127.0.0.1:3306)/yourSchema?charset=utf8&parseTime=True" |
另外要注意的点是gorm在读取空的(NULL)timeStamp的时候,会加载为time.Time的zero value,也就是
1 | 0001-01-01 00:00:00 +0000 UTC |
可以用date.IsZero()来判断date是不是NULL
+8小时谜题
有个很有意思的现象,数据库中的时间戳读取到go程序里就会自动+8个小时。我一开始以为是bug,花了好多时间去debug。后来才恍然大悟,这是因为mysql数据库的时区和电脑时区是不一样的。
mysql创建的时候默认的时区是UTC,也就是零时区。我们所在的东八区(CST)比UTC时间快8个小时。所以说时间戳读取到程序里面之后其实是转换成了东八区(CST)的。同时,从程序中把时间戳写入数据库又会重新转换成UTC时区。
令人迷惑的time.Parse和time.Format
提到了时区,就不得不继续说一下time.Parse和time.Format方法。
time.Parse方法可以把一个字符串转换为时间戳
1 | time.Parse("2006-01-02 15:04:05", str) |
time.Format方法用来格式输出时间
1 | time.Now().Format("2006-01-02 15:04:05") |
注意time.Parse默认时区是UTC,而time.Format默认时区是当地时间(time.Local)
指定时区Parse
1 | localTime, err := time.ParseInLocation("2006-01-02 15:04:05", "2017-12-03 22:01:02", time.Local) |
指定时区Format
1 | time.Now().In(time.UTC).Format("2006-01-02 15:04:05") |
关于go-mysql-driver的一个bug
当数据库的时区和程序时区不统一时,使用go-mysql-driver读取timestamp会出现一个很有趣的bug。
比如我们读取2020-04-14 07:46:10.778901这样一个时间,在数据库中时区是UTC。当我们读到程序中时,你会发现这个时间变成了2020-04-14 15:46:10.778901。乍一看没有什么问题,就是我们前面提到的时区转换。但是当你格式化输出一下这个时间,你会发现他的完整版是2020-04-14 15:46:10.778901 +0000 UTC。也就是说,虽然时间换算了,但是时区还是数据库default的时区。
总结
说了这么多,最重要的经验就是一定要统一数据库时区和程序时区呀!!!不然会出现很多棘手的麻烦。
可以参照这篇文章解决 https://studygolang.com/articles/17313