CURRENT_TIME Неверная отметка времени при вставке строки в MySQL, я использую AWS RDS - PullRequest
0 голосов
/ 27 декабря 2018

edit: это была проблема с библиотекой mysql, которую я использовал node-mysql2

Я использую AWS RDS для размещения базы данных MySQL.

В моей базе данных есть столбец сследующее определение

createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP

Когда я вставил строку в 16:43 EST, я получил следующее значение для этого столбца

2018-12-27T02:43:32.000Z

Когда я пытаюсь преобразовать это значение в EST, я получаю

12/26/2018, 9:43:32 PM

, что неверно.

Я делаю что-то неправильно или есть что-то, что мне нужнонастройка

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Я думал, что этот тест был интересным, и хотя он не отвечает на ваш вопрос, он выводит библиотеку узлов из уравнения, и я подумал, что это интересно.

CREATE DATABASE IF NOT EXISTS test;
USE test;

CREATE TEMPORARY TABLE t (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  created DATETIME DEFAULT CURRENT_TIMESTAMP,
  tz varchar(32)
);

select "datetime";

SET time_zone = "CST6CDT";
insert into t (tz) values (@@SESSION.time_zone);

SET time_zone = "EST5EDT";
insert into t (tz) values (@@SESSION.time_zone);

SET time_zone = "UTC";
insert into t (tz) values (@@SESSION.time_zone);

SET time_zone = "CST6CDT";
select *, @@SESSION.time_zone FROM t;

SET time_zone = "EST5EDT";
select *, @@SESSION.time_zone FROM t;

SET time_zone = "UTC";
select *, @@SESSION.time_zone FROM t;

DROP TEMPORARY TABLE t;

select "timestamp";

CREATE TEMPORARY TABLE t (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  tz varchar(32)
);

SET time_zone = "CST6CDT";
insert into t (tz) values (@@SESSION.time_zone);

SET time_zone = "EST5EDT";
insert into t (tz) values (@@SESSION.time_zone);

SET time_zone = "UTC";
insert into t (tz) values (@@SESSION.time_zone);

SET time_zone = "CST6CDT";
select *, @@SESSION.time_zone FROM t;

SET time_zone = "EST5EDT";
select *, @@SESSION.time_zone FROM t;

SET time_zone = "UTC";
select *, @@SESSION.time_zone FROM t;

Здесь я создаю временную таблицу со столбцом DEFAULT CURRENT_TIMESTAMP.Я установил переменные сеанса для каждого из CST, EST и UTC, чтобы протестировать несколько разных локальных часовых поясов, а затем вставил часовой пояс сеанса, чтобы отследить, какой часовой пояс создал какое значение.Затем я снова выбираю их с каждым из часовых поясов, заданным в качестве часового пояса сеанса, чтобы показать, как взаимодействуют часовой пояс сеанса вставки и часовой пояс выбранного сеанса.

Затем я снова все делаюточно так же, как и раньше, но вместо DATETIME я создаю столбец с полем TIMESTAMP во второй раз.

Я запускаю его в Docker-контейнере только для тестирования, с которого я начинаю:

docker run --rm -d -e MYSQL_ALLOW_EMPTY_PASSWORD=true --name mysql mysql

Но запускать его с любого клиента mysql, который может связаться с сервером, должно быть довольно легко;вот мой docker exec вызов:

$ docker exec -i mysql mysql -t  < t.sql
+----------+
| datetime |
+----------+
| datetime |
+----------+
+----+---------------------+---------+---------------------+
| id | created             | tz      | @@SESSION.time_zone |
+----+---------------------+---------+---------------------+
|  1 | 2018-12-27 11:07:05 | CST6CDT | CST6CDT             |
|  2 | 2018-12-27 12:07:05 | EST5EDT | CST6CDT             |
|  3 | 2018-12-27 17:07:05 | UTC     | CST6CDT             |
+----+---------------------+---------+---------------------+
+----+---------------------+---------+---------------------+
| id | created             | tz      | @@SESSION.time_zone |
+----+---------------------+---------+---------------------+
|  1 | 2018-12-27 11:07:05 | CST6CDT | EST5EDT             |
|  2 | 2018-12-27 12:07:05 | EST5EDT | EST5EDT             |
|  3 | 2018-12-27 17:07:05 | UTC     | EST5EDT             |
+----+---------------------+---------+---------------------+
+----+---------------------+---------+---------------------+
| id | created             | tz      | @@SESSION.time_zone |
+----+---------------------+---------+---------------------+
|  1 | 2018-12-27 11:07:05 | CST6CDT | UTC                 |
|  2 | 2018-12-27 12:07:05 | EST5EDT | UTC                 |
|  3 | 2018-12-27 17:07:05 | UTC     | UTC                 |
+----+---------------------+---------+---------------------+
+-----------+
| timestamp |
+-----------+
| timestamp |
+-----------+
+----+---------------------+---------+---------------------+
| id | created             | tz      | @@SESSION.time_zone |
+----+---------------------+---------+---------------------+
|  1 | 2018-12-27 11:07:05 | CST6CDT | CST6CDT             |
|  2 | 2018-12-27 11:07:05 | EST5EDT | CST6CDT             |
|  3 | 2018-12-27 11:07:05 | UTC     | CST6CDT             |
+----+---------------------+---------+---------------------+
+----+---------------------+---------+---------------------+
| id | created             | tz      | @@SESSION.time_zone |
+----+---------------------+---------+---------------------+
|  1 | 2018-12-27 12:07:05 | CST6CDT | EST5EDT             |
|  2 | 2018-12-27 12:07:05 | EST5EDT | EST5EDT             |
|  3 | 2018-12-27 12:07:05 | UTC     | EST5EDT             |
+----+---------------------+---------+---------------------+
+----+---------------------+---------+---------------------+
| id | created             | tz      | @@SESSION.time_zone |
+----+---------------------+---------+---------------------+
|  1 | 2018-12-27 17:07:05 | CST6CDT | UTC                 |
|  2 | 2018-12-27 17:07:05 | EST5EDT | UTC                 |
|  3 | 2018-12-27 17:07:05 | UTC     | UTC                 |
+----+---------------------+---------+---------------------+

Как видите, DATETIME всегда сохраняется по местному времени сеанса.Для меня не очевидно, как узнать, следует ли преобразовать это в другой часовой пояс, поскольку часовой пояс, очевидно, хранится как UTC внутри, но, очевидно, не корректируется для часового пояса SELECT.

Времяштамп, с другой стороны, ведет себя по-другому.В этих случаях отметка времени, если она выбрана, корректно преобразуется во время сеанса SELECT.Я бы подумал, что, как правило, такое поведение будет ожидать клиент базы данных (я установил часовой пояс сеанса, поэтому покажу мне даты в этом часовом поясе сеанса).

Короче говоря, если вы хотите сохранить местное время, используйте datetime.Если вы хотите сохранить «абсолютное время», используйте отметку времени.Не уверен, что это хорошее правило, но на основании моего теста это кажется хорошим подходом.

Конечно, как вы указали, клиент все еще должен установить часовой пояс, который он хочет использовать.Настройка всего для использования одного и того же часового пояса устраняет всю проблему:)

0 голосов
/ 27 декабря 2018

Это не было проблемой с AWS или MySQL

Я выяснил, в чем проблема, узел-mysql2 решил преобразовать метку времени.Я не понимаю, какое преобразование это делало или почему.

Настройка, которую я использовал, чтобы исправить это была

let options = {
    ...,
    timezone: 'UTC', // Interpret all received timestamps as UTC. Otherwise local timezone is assumed.
    dateStrings: [
        'DATE', // DATE's are returned as strings (otherwise they would be interpreted as YYYY-MM-DD 00:00:00+00:00)
        'DATETIME' // DATETIME's return as strings (otherwise they would interpreted as YYYY-MM-DD HH:mm:ss+00:00)
    ]
}
...