I thought this test was interesting, and though it doesn't answer your question, it does take the node library out of the equation.
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;
Here I create a temporary table with a DEFAULT CURRENT_TIMESTAMP
column. I set the session variables to each of CST, EST, and UTC to test some different local time zones, then insert the session time zone to track which time zone created which value. I then select them out again with each of the timezones set as my session time zone to show how the time zone of the insert session and the time zone of the select session interact.
Then I do the whole thing again, exactly as before, but instead of DATETIME I create the column with TIMESTAMP field the second time.
I run it in a docker container just for testing, which I start up with:
docker run --rm -d -e MYSQL_ALLOW_EMPTY_PASSWORD=true --name mysql mysql
But it should be pretty easy to run from any mysql client that can reach a server; here's my docker exec
invocation:
$ 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 |
+----+---------------------+---------+---------------------+
As you can see, DATETIME is always stored in the session's local time. It's not obvious to me how to know whether to convert this to a different time zone, as the time zone is apparently stored as UTC internally but obviously doesn't get corrected for the SELECT sesson's time zone.
The time stamp, on the other hand, behaves differently. In these cases the timestamp, when selected, is correctly converted to the session time of the SELECT. I would think this would typically be the behavior a database client would expect ( I set a session time zone, so show me the dates in that session timezone ).
In short, if you want to store local time, use datetime. If you want to store "absolute time", use timestamp. Not sure if that's a good rule but based on my test it seems like a good approach.
Of course, as you pointed out, the client does still have to set the time zone they wish to use. Setting everything to use the same time zone kind of obviates the whole issue :)