Отметки времени по умолчанию для разных часовых поясов в разных таблицах mysql - PullRequest
0 голосов
/ 24 марта 2020

Версия сервера & 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
}

What I смотрите, когда выбираете запросы

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 является текущим временем UT C.

Но я ожидаю, что оба времени одинаковы (я имею в виду либо UT C или BST).

Хочу знать:

  • Причина, по которой два раза различаются по регионам.
  • Любое решение, чтобы оба раза находятся в одном регионе

1 Ответ

1 голос
/ 01 апреля 2020

В таблице t1, CreatedAt установлено Gorm в местном часовом поясе, поскольку вы используете loc=Local.

Ссылка: https://github.com/jinzhu/gorm/blob/master/callback_create.go#L32

А в таблице t2, initiated_at не установлено Gorm, установлено Mysql, поскольку вы используете значение по умолчанию как CURRENT_TIMESTAMP в MySql.

Решение:

Вы можете изменить Gorm часовой пояс на UT C, используя loc=UTC в соединении.

или

Вы можете установить местный часовой пояс как Mysql часовой пояс. Обратите внимание, что задается местоположение для значений времени. Значения времени, но не изменяются настройки time_zone MySQL. Для этого см. Системную переменную time_zone, которая также может быть установлена ​​как параметр DSN.

Ref: https://github.com/go-sql-driver/mysql#loc

...