默认时间戳在不同的mysql表中具有不同的时区

问题描述 投票:0回答:1

服务器版本和gorm软件包:

❯ docker exec -it mysql mysqld --version
mysqld  Ver 5.7.29 for Linux on x86_64 (MySQL Community Server (GPL))

❯ docker exec -it mysql mysql --version
mysql  Ver 14.14 Distrib 5.7.29, for Linux (x86_64) using  EditLine wrapper
import "github.com/jinzhu/gorm"

两个表:

mysql> desc t1;
+------------+-------------------+------+-----+-------------------+----------------+
| Field      | Type              | Null | Key | Default           | Extra          |
+------------+-------------------+------+-----+-------------------+----------------+
| ...        |                   |      |     |                   |                |
| created_at | timestamp         | YES  |     | CURRENT_TIMESTAMP |                |
+------------+-------------------+------+-----+-------------------+----------------+

mysql> desc t2;
+----------------+------------------+------+-----+-------------------+----------------+
| Field          | Type             | Null | Key | Default           | Extra          |
+----------------+------------------+------+-----+-------------------+----------------+
| ...            | ...              | ...  | ... | ...               | ...            |
| initiated_at   | timestamp        | YES  |     | CURRENT_TIMESTAMP |                |
+----------------+------------------+------+-----+-------------------+----------------+

gorm模型在定义stuct{}时如下:

// t1
type T1 struct {
    ID uint `gorm:"primary_key"`
    // others are here
    // ...

    CreatedAt  time.Time `gorm:"timestamp;default:CURRENT_TIMESTAMP" json:"created_at" form:"created_at" query:"created_at" sql:"DEFAULT:current_timestamp"`
}

// t2 ...
type T2 struct {
    ID uint `gorm:"primary_key"`
    // others are here
    // ...
    InitiatedAt  time.Time `gorm:"timestamp;default:CURRENT_TIMESTAMP" json:"initiated_at" form:"initiated_at" query:"initiated_at" sql:"DEFAULT:current_timestamp"`
}

插入未初始化的时间戳

dbSource := fmt.Sprintf(
    "%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local",
    cnf.Username,
    cnf.Password,
    cnf.Host,
    cnf.Port,
    cnf.DBName,
)

db, err := gorm.Open("mysql", dbSource)
if err != nil {
    logrus.Warn("Got error when connect database:", err)
    return err
}

t1 := T1{} // created_at is not set
t2 := T2{} // initiated_at is not set

tx := db.Begin()
defer func() {
    if r := recover(); r != nil {
        logrus.Error("Rolling back")
        tx.Rollback()
    }
}()
// If failed to begin transaction
if err := tx.Error; err != nil {
    return err
}

if err := db.Create(&t1).Error; err != nil {
    logrus.Warn(err)
    // rollback the transaction in case of error
    tx.Rollback()
    return derror.ErrorBadRequest
}
if err := db.Create(&t2).Error; err != nil {
    logrus.Warn(err)
    // rollback the transaction in case of error
    tx.Rollback()
    return derror.ErrorBadRequest
}

// Or commit the transaction
if err := tx.Commit().Error; err != nil {
    logrus.Warn(err)
    // rollback the transaction in case of error
    tx.Rollback()
    return derror.ErrorBadRequest
}

我看到的,何时选择查询

mysql> select * from t1;
+-----+---------------------+
| ... | created_at          |
+-----+---------------------+
| ... | 2020-03-24 02:38:26 |
+-----+---------------------+

mysql> select * from t2;
+-----+---------------------+
| ... | initiated_at        |
+-----+---------------------+
| ... | 2020-03-23 20:38:26 |
+-----+---------------------+

期望:

注意,我在asia/dhaka(+ 06:00)区域。 created_at表的t1时间是我所在地区的BST当前时间。另一方面,initiated_at表的t2的时间是UTC当前时间。

但是我希望两个时间都相同(我指的是UTC或BST)。

想知道:

  • 两次位于不同区域的原因。
  • 任何解决方案,使两个时间都在同一地区
mysql go gorm
1个回答
0
投票

在表t1中,因为使用CreatedAt,所以在本地时区中由Gorm设置了loc=Local

参考:https://github.com/jinzhu/gorm/blob/master/callback_create.go#L32

并且在表t2中,initiated_at未由Gorm设置,而由Mysql设置,因为您将默认值用作CURRENT_TIMESTAMP中的MySql

解决方案:

您可以在连接中使用Gormloc=UTC时区更改为UTC。

您可以将本地时区设置为Mysql时区。请注意,它设置时间的位置。时间值,但不会更改MySQL的time_zone设置。有关此信息,请参见time_zone系统变量,也可以将其设置为DSN参数。

© www.soinside.com 2019 - 2024. All rights reserved.