GoFrame 數(shù)據(jù)庫(kù)ORM-時(shí)區(qū)處理

2022-04-02 13:47 更新

基本介紹

這個(gè)問(wèn)題由于大家問(wèn)得比較多,因此單獨(dú)開(kāi)了一個(gè)章節(jié)詳細(xì)介紹一下?ORM?中的時(shí)區(qū)處理是怎么一回事。我們這里以?MySQL?數(shù)據(jù)庫(kù)為基礎(chǔ)來(lái)介紹時(shí)區(qū)轉(zhuǎn)換的事情,本地時(shí)區(qū)我們?cè)O(shè)定為+8時(shí)區(qū),數(shù)據(jù)庫(kù)時(shí)區(qū)也是+8時(shí)區(qū)。

?MySQL?數(shù)據(jù)庫(kù)驅(qū)動(dòng)用得最多的是這個(gè)第三方包:https://github.com/go-sql-driver/mysql ,在這個(gè)第三方包中有這么一個(gè)參數(shù):


大概的意思是,當(dāng)你提交的時(shí)間參數(shù)為?time.Time?時(shí),該參數(shù)用來(lái)轉(zhuǎn)換參數(shù)時(shí)區(qū)的。當(dāng)你在連接數(shù)據(jù)庫(kù)時(shí),該參數(shù)傳遞?loc=Local?,那么該?driver?將會(huì)自動(dòng)將你提交的?time.Time?參數(shù)轉(zhuǎn)換為本地程序設(shè)置的時(shí)區(qū),沒(méi)有手動(dòng)設(shè)置時(shí),那么該時(shí)區(qū)為?UTC?時(shí)區(qū)。那么我們來(lái)看兩個(gè)例子。

轉(zhuǎn)換示例

示例1,設(shè)置loc=Local

配置文件

[database]
    link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local"

代碼示例

t1, _ := time.Parse("2006-01-02 15:04:05", "2020-10-27 10:00:00")
t2, _ := time.Parse("2006-01-02 15:04:05", "2020-10-27 11:00:00")
db.Model("user").Where("create_time>? and create_time<?", t1, t2).One()
// SELECT * FROM `user` WHERE create_time>'2020-10-27 18:00:00' AND create_time<'2020-10-27 19:00:00'

這里由于通過(guò)?time.Parse?創(chuàng)建的?time.Time?時(shí)間對(duì)象是?UTC?時(shí)區(qū),那么提交到數(shù)據(jù)庫(kù)執(zhí)行時(shí)將會(huì)被底層的?driver?修改為+8時(shí)區(qū)。

t1, _ := time.ParseInLocation("2006-01-02 15:04:05", "2020-10-27 10:00:00", time.Local)
t2, _ := time.ParseInLocation("2006-01-02 15:04:05", "2020-10-27 11:00:00", time.Local)
db.Model("user").Where("create_time>? and create_time<?", t1, t2).One()
// SELECT * FROM `user` WHERE create_time>'2020-10-27 10:00:00' AND create_time<'2020-10-27 11:00:00'

這里由于通過(guò)?time.ParseInLocation?創(chuàng)建的?time.Time?時(shí)間對(duì)象是+8時(shí)區(qū),和?loc=Local?的時(shí)區(qū)一致,那么提交到數(shù)據(jù)庫(kù)執(zhí)行時(shí)不會(huì)被底層的?driver?修改。

注意在寫(xiě)入數(shù)據(jù)中包含?time.Time?參數(shù)時(shí),也需要注意時(shí)區(qū)轉(zhuǎn)換的問(wèn)題。

示例2,不設(shè)置loc參數(shù)

配置文件

[database]
    link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"

代碼示例

t1, _ := time.Parse("2006-01-02 15:04:05", "2020-10-27 10:00:00")
t2, _ := time.Parse("2006-01-02 15:04:05", "2020-10-27 11:00:00")
db.Model("user").Where("create_time>? and create_time<?", t1, t2).One()
// SELECT * FROM `user` WHERE create_time>'2020-10-27 10:00:00' AND create_time<'2020-10-27 11:00:00'

這里由于通過(guò)?time.Parse?創(chuàng)建的?time.Time?時(shí)間對(duì)象是?UTC?時(shí)區(qū),那么提交到數(shù)據(jù)庫(kù)執(zhí)行時(shí)將不會(huì)被底層的?driver?修改。

t1, _ := time.ParseInLocation("2006-01-02 15:04:05", "2020-10-27 10:00:00", time.Local)
t2, _ := time.ParseInLocation("2006-01-02 15:04:05", "2020-10-27 11:00:00", time.Local)
db.Model("user").Where("create_time>? and create_time<?", t1, t2).One()
// SELECT * FROM `user` WHERE create_time>'2020-10-27 02:00:00' AND create_time<'2020-10-27 03:00:00'

這里由于通過(guò)?time.ParseInLocation?創(chuàng)建的?time.Time?時(shí)間對(duì)象是+8時(shí)區(qū),那么提交到數(shù)據(jù)庫(kù)執(zhí)行時(shí)會(huì)被底層的?driver?修改為UTC時(shí)區(qū)。

注意在寫(xiě)入數(shù)據(jù)中包含?time.Time?參數(shù)時(shí),也需要注意時(shí)區(qū)轉(zhuǎn)換的問(wèn)題。

改進(jìn)方案

也就是說(shuō),當(dāng)你使用?time.Time?對(duì)象作為時(shí)間參數(shù)時(shí),無(wú)論如何你都會(huì)需要注意時(shí)區(qū)自動(dòng)轉(zhuǎn)換的問(wèn)題。因此,為了避免這樣的心智負(fù)擔(dān),防止大家踩坑,在保留對(duì)?time.Time?參數(shù)支持的同時(shí),?ORM?增加了對(duì)?gtime.Time?類(lèi)型參數(shù)的支持,該類(lèi)型不會(huì)涉及到時(shí)區(qū)轉(zhuǎn)換困惑的問(wèn)題。例如:

t1 := gtime.New("2020-10-27 10:00:00")
t2 := gtime.New("2020-10-27 11:00:00")
db.Model("user").Where("create_time>? and create_time<?", t1, t2).One()
// SELECT * FROM `user` WHERE create_time>'2020-10-27 10:00:00' AND create_time<'2020-10-27 11:00:00'

即,你傳遞什么時(shí)間參數(shù),那么提交到數(shù)據(jù)庫(kù)執(zhí)行的也是同樣的時(shí)間參數(shù),不會(huì)執(zhí)行任何的時(shí)區(qū)轉(zhuǎn)換,免去了心智負(fù)擔(dān)。

這也是為什么?goframe?框架?cli?開(kāi)發(fā)工具自動(dòng)生成的?model?代碼文件中涉及到時(shí)間類(lèi)型的屬性均使用了?*gtime.Time?類(lèi)型而不是?time.Time?的緣故。

此外,還需要說(shuō)明的是,?goframe?框架的?ORM?默認(rèn)情況下沒(méi)有設(shè)置?loc?參數(shù),可以通過(guò)?Timezone?參數(shù)配置。


以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)