Reputation: 912
MySQL has two data types that are purpose built for storing date & time values - DATETIME
and TIMESTAMP
. Neither type stores timezone information, and both have different rules.
A DATETIME
column will store the exact date & time value provided in the insertion query. (No converstions and no affordances for time zone)
A TIMESTAMP
column will convert the date & time value provided at insertion from the timezone of the connection at insertion time to UTC. On retrieval it will convert the date & time value stored from UTC to the timezone of the retrieval connection.
The timezone of both connections can be explicitly or implicitly set according to these rules.
Now before I get to my question let's look at some of the nuances of handling dates & times when daylight savings is involved. Summarizing the answers on another Stack Overflow question as well as what I understand from the MySQL documentation regarding date/time:
DATETIME
column and explicitly specifying a value (ie/ 2009-11-01 01:30:00
), the value can be ambiguous. DATETIME
performs no conversation and simply stores this exact date/time. Say I'm in New York (which follows a daylight savings time). Both at insertion and retrieval I have no way of indicating/knowing if this value refers to 1:30AM at the with-daylight-savings moment (UTC-4) or 1:30AM at the without-daylight-savings moment (UTC-5).DATETIME
column along with NOW()
, NOW()
evaluates to the date & time value at the start of query execution (ie/ 2009-11-01 01:30:00
) and this value is inserted, with no converstions, into the DATETIME
field causing the same exact ambiguity as mentioned above.TIMESTAMP
column and explicitly specifying a value (ie/ 2009-11-01 01:30:00
), I again have the same problem as mentioned above. There's no way to specify and no way to know which 1:30am I'm referring to.Now, here's my question:
Given a MySQL connection that is set to a timezone that includes daylight savings (say America/New York
), can I be certain that inserting NOW()
into a TIMESTAMP
column will cause the correct UTC date & time value to be stored? UTC of course does not observe daylight savings, so the UTC time at the 1:30am New York timezone with-daylight-savings moment is different from the UTC time at the 1:30AM New York timezone without-daylight-savings moment.
More specifically: Is the UTC offset of the connection timezone at the start of query execution what is used to perform the to-UTC/from-UTC conversion when I insert/select from a TIMESTAMP
column? Going back to my example, at the 1:30am with-daylight-savings moment (America\New York
timezone) I'm at UTC-4 and at the 1:30am without-daylight-savings moment (America\New York
timezone) I'm at UTC-5 - so in both these moments, would a different value be stored in a TIMESTAMP
field when I explicitly insert 2009-11-01 01:30:00
or implicitly insert this same value by using NOW()
? Finally, if I'm within a single MySQL connection that spans both these moments, and I execute two queries (one in the first moment, and a separate one in the second moment), will both queries cause the correct (different) UTC value to be stored?
Upvotes: 7
Views: 3186
Reputation: 3414
I used this one Not sure if it will helpful or not. Please add the below text in your my.cnf
file.
[mysqld_safe]
timezone = UTC
Upvotes: 0
Reputation: 10044
As far as I know, you're best off with doing this from your code. If you really have to do it via DB, you could use UTC_TIMESTAMP()
which will always give you the current time based on UTC. Relying on your server timezone however is not a good idea in my opinion because the servers are bound to undergo changes as you grow/scale.
On the other hand, specifying the time from code will tend to be more important/accurate for you than letting it hit the DB. (Think latency, delayed inserts and what not).
Upvotes: 1
Reputation: 18855
You can test the time_zone change by using the SET time_zone
function :
mysql> create table demo (test timestamp);
mysql> SET time_zone='-06:00';
mysql> insert into demo VALUES(NOW());
mysql> SELECT * FROM demo;
+---------------------+
| test |
+---------------------+
| 2017-05-23 08:55:16 |
+---------------------+
mysql> SET time_zone='+02:00';
mysql> insert into demo VALUES(NOW());
mysql> SELECT * FROM demo;
+---------------------+
| test |
+---------------------+
| 2017-05-23 16:55:16 |
| 2017-05-23 16:55:32 |
+---------------------+
According to those results changing the timezone gives consistent results which prove that times are stored UTC (when using timestamp
).
Upvotes: 0
Reputation: 142453
You might want this for a server:
mysql> SHOW VARIABLES LIKE '%zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | UTC | -- Comes from OS
| time_zone | SYSTEM | -- Probably the 'right' setting
+------------------+--------+
With those settings, SELECT NOW()
will deliver UTC time, not local time.
For your personal computer, it is probably better to have system_time_zone
equal to something like Pacific Daylight Time
(or whatever), to reflect your current location.
No conversion happens when INSERTing
or SELECTing
a DATE
or DATETIME
. Think of it as being a picture of the clock.
For TIMESTAMP
, whatever you give it is converted to/from UTC. That is, the bits stored in the table are UTC, but you can't see that; you only see the converted date&time based on the two settings above.
I suggest that the best way to get the answer is to create a table with a DATETIME
and a TIMESTAMP
, set the two settings, then see what happens when storing. Then change the settings and do a SELECT
.
Upvotes: 3