How do I get the current time zone of MySQL? - mysql

Anyone knows if there is such a function in MySQL?
UPDATE
This doesn't output any valid info:
mysql> SELECT ##global.time_zone, ##session.time_zone;
+--------------------+---------------------+
| ##global.time_zone | ##session.time_zone |
+--------------------+---------------------+
| SYSTEM | SYSTEM |
+--------------------+---------------------+
Or maybe MySQL itself can't know exactly the time_zone used,that's fine, we can involve PHP here, as long as I can get valid info not like SYSTEM...

From the manual (section 9.6):
The current values of the global and client-specific time zones can be retrieved like this:
mysql> SELECT ##global.time_zone, ##session.time_zone;
Edit The above returns SYSTEM if MySQL is set to use the system's timezone, which is less than helpful. Since you're using PHP, if the answer from MySQL is SYSTEM, you can then ask the system what timezone it's using via date_default_timezone_get. (Of course, as VolkerK pointed out, PHP may be running on a different server, but as assumptions go, assuming the web server and the DB server it's talking to are set to [if not actually in] the same timezone isn't a huge leap.) But beware that (as with MySQL), you can set the timezone that PHP uses (date_default_timezone_set), which means it may report a different value than the OS is using. If you're in control of the PHP code, you should know whether you're doing that and be okay.
But the whole question of what timezone the MySQL server is using may be a tangent, because asking the server what timezone it's in tells you absolutely nothing about the data in the database. Read on for details:
Further discussion:
If you're in control of the server, of course you can ensure that the timezone is a known quantity. If you're not in control of the server, you can set the timezone used by your connection like this:
set time_zone = '+00:00';
That sets the timezone to GMT, so that any further operations (like now()) will use GMT.
Note, though, that time and date values are not stored with timezone information in MySQL:
mysql> create table foo (tstamp datetime) Engine=MyISAM;
Query OK, 0 rows affected (0.06 sec)
mysql> insert into foo (tstamp) values (now());
Query OK, 1 row affected (0.00 sec)
mysql> set time_zone = '+01:00';
Query OK, 0 rows affected (0.00 sec)
mysql> select tstamp from foo;
+---------------------+
| tstamp |
+---------------------+
| 2010-05-29 08:31:59 |
+---------------------+
1 row in set (0.00 sec)
mysql> set time_zone = '+02:00';
Query OK, 0 rows affected (0.00 sec)
mysql> select tstamp from foo;
+---------------------+
| tstamp |
+---------------------+
| 2010-05-29 08:31:59 | <== Note, no change!
+---------------------+
1 row in set (0.00 sec)
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2010-05-29 10:32:32 |
+---------------------+
1 row in set (0.00 sec)
mysql> set time_zone = '+00:00';
Query OK, 0 rows affected (0.00 sec)
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2010-05-29 08:32:38 | <== Note, it changed!
+---------------------+
1 row in set (0.00 sec)
So knowing the timezone of the server is only important in terms of functions that get the time right now, such as now(), unix_timestamp(), etc.; it doesn't tell you anything about what timezone the dates in the database data are using. You might choose to assume they were written using the server's timezone, but that assumption may well be flawed. To know the timezone of any dates or times stored in the data, you have to ensure that they're stored with timezone information or (as I do) ensure they're always in GMT.
Why is assuming the data was written using the server's timezone flawed? Well, for one thing, the data may have been written using a connection that set a different timezone. The database may have been moved from one server to another, where the servers were in different timezones (I ran into that when I inherited a database that had moved from Texas to California). But even if the data is written on the server, with its current time zone, it's still ambiguous. Last year, in the United States, Daylight Savings Time was turned off at 2:00 a.m. on November 1st. Suppose my server is in California using the Pacific timezone and I have the value 2009-11-01 01:30:00 in the database. When was it? Was that 1:30 a.m. November 1st PDT, or 1:30 a.m. November 1st PST (an hour later)? You have absolutely no way of knowing. Moral: Always store dates/times in GMT (which doesn't do DST) and convert to the desired timezone as/when necessary.

The query below returns the timezone of the current session.
select timediff(now(),convert_tz(now(),##session.time_zone,'+00:00'));

Simply
SELECT ##system_time_zone;
Returns PST (or whatever is relevant to your system).
If you're trying to determine the session timezone you can use this query:
SELECT IF(##session.time_zone = 'SYSTEM', ##system_time_zone, ##session.time_zone);
Which will return the session timezone if it differs from the system timezone.

As Jakub Vrána (The creator or Adminer and NotORM) mentions in the comments, to select the current timezone offset in TIME use:
SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);
It will return: 02:00:00 if your timezone is +2:00 for that date
I made a cheatsheet here: Should MySQL have its timezone set to UTC?

To get Current timezone of the mysql you can do following things:
SELECT ##system_time_zone; # from this you can get the system timezone
SELECT IF(##session.time_zone = 'SYSTEM', ##system_time_zone, ##session.time_zone) # This will give you time zone if system timezone is different from global timezone
Now if you want to change the mysql timezone then:
SET GLOBAL time_zone = '+00:00'; # this will set mysql timezone in UTC
SET ##session.time_zone = "+00:00"; # by this you can chnage the timezone only for your particular session

If you need the GMT difference as an integer:
SELECT EXTRACT(HOUR FROM (TIMEDIFF(NOW(), UTC_TIMESTAMP))) AS `timezone`

To anyone come to find timezone of mysql db.
With this query you can get current timezone :
mysql> SELECT ##system_time_zone as tz;
+-------+
| tz |
+-------+
| CET |
+-------+

The command mention in the description returns "SYSTEM" which indicated it takes the timezone of the server. Which is not useful for our query.
Following query will help to understand the timezone
SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP) as GMT_TIME_DIFF;
Above query will give you the time interval with respect to Coordinated Universal Time(UTC). So you can easily analyze the timezone. if the database time zone is IST the output will be 5:30
UTC_TIMESTAMP
In MySQL, the UTC_TIMESTAMP returns the current UTC date and time as a value in 'YYYY-MM-DD HH:MM:SS' or YYYYMMDDHHMMSS.uuuuuu format depending on the usage of the function i.e. in a string or numeric context.
NOW()
NOW() function. MySQL NOW() returns the value of current date and time in 'YYYY-MM-DD HH:MM:SS' format or YYYYMMDDHHMMSS.uuuuuu format depending on the context (numeric or string) of the function. CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, LOCALTIMESTAMP() are synonyms of NOW().

Check out MySQL Server Time Zone Support and the system_time_zone system variable. Does that help?

My PHP framework uses
SET LOCAL time_zone='Whatever'
on after connect, where 'Whatever' == date_default_timezone_get()
Not my solution, but this ensures SYSTEM timezone of MySQL server is always the same as PHP's one
So, yes, PHP is strongly envolved and can affect it

To get the current time according to your timezone, you can use the following (in my case its '+5:30')
select DATE_FORMAT(convert_tz(now(),##session.time_zone,'+05:30') ,'%Y-%m-%d')

You can try the following:
select sec_to_time(TIME_TO_SEC( curtime()) + 48000);
Here you can specify your time difference as seconds

Use LPAD(TIME_FORMAT(TIMEDIFF(NOW(), UTC_TIMESTAMP),’%H:%i’),6,’+') to get a value in MySQL's timezone format that you can conveniently use with CONVERT_TZ(). Note that the timezone offset you get is only valid at the moment in time where the expression is evaluated since the offset may change over time if you have daylight savings time. Yet the expression is useful together with NOW() to store the offset with the local time, which disambiguates what NOW() yields. (In DST timezones, NOW() jumps back one hour once a year, thus has some duplicate values for distinct points in time).

You just need to restart mysqld after altering timezone of System..
The Global time zone of MySQL takes timezone of System. When you change any such attribute of system, you just need a restart of Mysqld.

Insert a dummy record into one of your databases that has a timestamp
Select that record and get value of timestamp.
Delete that record. Gets for sure the timezone that the server is using to write data and ignores PHP timezones.

It may be
select timediff(current_time(),utc_time())
You won't get the timezone value directly this way.
##global.time_zone cannot be used as it is a variable, and it returns the value 'SYSTEM'.
If you need to use your query in a session with a changed timezone by using session SET TIME_ZONE =, then you will get that with ##session.time_zone. If you query ##global.time_zone, then you get 'SYSTEM'.
If you try datediff, date_sub, or timediff with now() and utc_time(), then you'll probably run into conversion issues.
But the things suggested above will probably work at least with some server versions. My version is 5.5.43-37 and is a hosted solution.

It is not a direct answer to this question but this blog post provides valuable information on the subject:
https://danuka-praneeth.medium.com/guide-to-time-zones-conversion-between-zones-and-storing-in-mysql-da4fc4350cd9.
Quote from the blog post:
In MySQL5+, TIMESTAMP values are converted from the session time zone
to UTC for storage, and from UTC to the session time zone for
retrieval. But DATETIME does not do any conversion.

Based on Timos answer.
Atleast on older version of mysql if your current timezone is lower than UTC then his solution returns NULL.
SELECT
IF(NOW() >= UTC_TIMESTAMP,
CONCAT('+', SUBSTRING_INDEX(TIMEDIFF(NOW(), UTC_TIMESTAMP), ':', 2)),
CONCAT('-', SUBSTRING_INDEX(TIMEDIFF(UTC_TIMESTAMP, NOW()), ':', 2))
) AS offset;
this returns (based on your timezone)
+02:00
-01:00

Try using the following code:
//ASP CLASSIC
Set dbdate = Server.CreateObject("ADODB.Recordset")
dbdate.ActiveConnection = MM_connection
dbdate.Source = "SELECT NOW() AS currentserverdate "
dbdate.Open()
currentdate = dbdate.Fields("currentserverdate").Value
response.Write("Server Time is "&currentdate)
dbdate.Close()
Set dbdate = Nothing

Related

When using NOW() in MySQL can I be certain that the correct UTC value will be stored in a TIMESTAMP column?

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:
When using a 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).
When using a 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.
When using a 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?
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.
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).
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).
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

Should MySQL have its timezone set to UTC?

Follow up question of
https://serverfault.com/questions/191331/should-servers-have-their-timezone-set-to-gmt-utc
Should the MySQL timezone be set to UTC or should it be set to be the same timezone as the server or PHP is set? (If it is not UTC)
What are the pros and cons?
It seems that it does not matter what timezone is on the server as long as you have the time set right for the current timezone, know the timezone of the datetime columns that you store, and are aware of the issues with daylight savings time.
On the other hand if you have control of the timezones of the servers you work with then you can have everything set to UTC internally and never worry about timezones and DST, at least when it comes to storing internal time.
Here are some notes I collected of how to work with timezones as a form of cheatsheet for myself and others which might influence what timezone the person will choose for his/her server and how he/she will store date and time.
MySQL Timezone Cheatsheet
Notes:
Changing the timezone will not change the stored datetime or
timestamp, but it will select a different datetime from
timestamp columns
Warning! UTC has leap seconds, these look like '2012-06-30 23:59:60' and can
be added randomly, with 6 months prior notice, due to the slowing of
the earths rotation
GMT confuses seconds, which is why UTC was invented.
Warning! different regional timezones might produce the same datetime value due
to daylight savings time
The timestamp column only supports dates 1970-01-01 00:00:01 to 2038-01-19 03:14:07 UTC, due to a limitation.
Internally a MySQL timestamp column is stored as UTC but
when selecting a date MySQL will automatically convert it to the
current session timezone.
When storing a date in a timestamp, MySQL will assume that the date
is in the current session timezone and convert it to UTC for
storage.
MySQL can store partial dates in datetime columns, these look like
"2013-00-00 04:00:00"
MySQL stores "0000-00-00 00:00:00" if you set a datetime column as
NULL, unless you specifically set the column to allow null when you
create it.
Read this
To select a timestamp column in UTC format
no matter what timezone the current MySQL session is in:
SELECT
CONVERT_TZ(`timestamp_field`, ##session.time_zone, '+00:00') AS `utc_datetime`
FROM `table_name`
You can also set the sever or global or current session timezone to UTC and then select the timestamp like so:
SELECT `timestamp_field` FROM `table_name`
To select the current datetime in UTC:
SELECT UTC_TIMESTAMP();
SELECT UTC_TIMESTAMP;
SELECT CONVERT_TZ(NOW(), ##session.time_zone, '+00:00');
Example result: 2015-03-24 17:02:41
To select the current datetime in the session timezone
SELECT NOW();
SELECT CURRENT_TIMESTAMP;
SELECT CURRENT_TIMESTAMP();
To select the timezone that was set when the server launched
SELECT ##system_time_zone;
Returns "MSK" or "+04:00" for Moscow time for example, there is (or was) a MySQL bug where if set to a numerical offset it would not adjust the Daylight savings time
To get the current timezone
SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);
It will return 02:00:00 if your timezone is +2:00.
To get the current UNIX timestamp (in seconds):
SELECT UNIX_TIMESTAMP(NOW());
SELECT UNIX_TIMESTAMP();
To get the timestamp column as a UNIX timestamp
SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`
To get a UTC datetime column as a UNIX timestamp
SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', ##session.time_zone)) FROM `table_name`
Get a current timezone datetime from a positive UNIX timestamp integer
SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`
Get a UTC datetime from a UNIX timestamp
SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), ##session.time_zone, '+00:00')
FROM `table_name`
Get a current timezone datetime from a negative UNIX timestamp integer
SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND)
There are 3 places where the timezone might be set in MySQL:
Note: A timezone can be set in 2 formats:
an offset from UTC: '+00:00', '+10:00' or '-6:00'
as a named time zone: 'Europe/Helsinki', 'US/Eastern', or 'MET'
Named time zones can be used only if the time zone information tables
in the mysql database have been created and populated.
in the file "my.cnf"
default_time_zone='+00:00'
or
timezone='UTC'
##global.time_zone variable
To see what value they are set to
SELECT ##global.time_zone;
To set a value for it use either one:
SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';
SET ##global.time_zone='+00:00';
##session.time_zone variable
SELECT ##session.time_zone;
To set it use either one:
SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00";
SET ##session.time_zone = "+00:00";
both "##global.time_zone variable" and "##session.time_zone variable" might return "SYSTEM" which means that they use the timezone set in "my.cnf".
For timezone names to work (even for default-time-zone) you must setup your timezone information tables need to be populated: http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html
Note: you can not do this as it will return NULL:
SELECT
CONVERT_TZ(`timestamp_field`, TIMEDIFF(NOW(), UTC_TIMESTAMP), '+00:00') AS `utc_datetime`
FROM `table_name`
Setup mysql timezone tables
For CONVERT_TZ to work, you need the timezone tables to be populated
SELECT * FROM mysql.`time_zone` ;
SELECT * FROM mysql.`time_zone_leap_second` ;
SELECT * FROM mysql.`time_zone_name` ;
SELECT * FROM mysql.`time_zone_transition` ;
SELECT * FROM mysql.`time_zone_transition_type` ;
If they are empty, then fill them up by running this command
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
if this command gives you the error "data too long for column 'abbreviation' at row 1", then it might be caused by a NULL character being appended at the end of the timezone abbreviation
the fix being to run this
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
(if the above gives error "data too long for column 'abbreviation' at row 1")
mysql_tzinfo_to_sql /usr/share/zoneinfo > /tmp/zut.sql
echo "SET SESSION SQL_MODE = '';" > /tmp/mysql_tzinfo_to.sql
cat /tmp/zut.sql >> /tmp/mysql_tzinfo_to.sql
mysql --defaults-file=/etc/mysql/my.cnf --user=verifiedscratch -p mysql < /tmp/mysql_tzinfo_to.sql
(make sure your servers dst rules are up to date zdump -v Europe/Moscow | grep 2011 https://chrisjean.com/updating-daylight-saving-time-on-linux/)
See the full DST (Daylight Saving Time) transition history for every timezone
SELECT
tzn.Name AS tz_name,
tztt.Abbreviation AS tz_abbr,
tztt.Is_DST AS is_dst,
tztt.`Offset` AS `offset`,
DATE_ADD('1970-01-01 00:00:00',INTERVAL tzt.Transition_time SECOND) AS transition_date
FROM mysql.`time_zone_transition` tzt
INNER JOIN mysql.`time_zone_transition_type` tztt USING(Time_zone_id, Transition_type_id)
INNER JOIN mysql.`time_zone_name` tzn USING(Time_zone_id)
-- WHERE tzn.Name LIKE 'Europe/Moscow' -- Moscow has weird DST changes
ORDER BY tzt.Transition_time ASC
CONVERT_TZ also applies any necessary DST changes based on the rules in the above tables and the date that you use.
Note:
According to the docs, the value you set for time_zone does not change, if you set it as "+01:00" for example, then the time_zone will be set as an offset from UTC, which does not follow DST, so it will stay the same all year round.
Only the named timezones will change time during daylight savings time.
Abbreviations like CET will always be a winter time and CEST will be summer time while +01:00 will always be UTC time + 1 hour and both won't change with DST.
The system timezone will be the timezone of the host machine where mysql is installed (unless mysql fails to determine it)
You can read more about working with DST here
When not to use UTC by the legendary Jon Skeet: https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/
(For example a scheduled event in the future that represents a time, not an instant in time)
related questions:
How do I set the time zone of MySQL?
MySql - SELECT TimeStamp Column in UTC format
How to get Unix timestamp in MySQL from UTC time?
Converting Server MySQL TimeStamp To UTC
https://dba.stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
How do I get the current time zone of MySQL?
MySQL datetime fields and daylight savings time -- how do I reference the "extra" hour?
Converting negative values from FROM_UNIXTIME
Sources:
https://bugs.mysql.com/bug.php?id=68861
http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html
http://dev.mysql.com/doc/refman/5.1/en/datetime.html
http://en.wikipedia.org/wiki/Coordinated_Universal_Time
http://shafiqissani.wordpress.com/2010/09/30/how-to-get-the-current-epoch-time-unix-timestamp/
https://web.ivy.net/~carton/rant/MySQL-timezones.txt
PHP and MySQL have their own default timezone configurations. You should synchronize time between your data base and web application, otherwise you could run some issues.
Read this tutorial: How To Synchronize Your PHP and MySQL Timezones
This is a working example:
jdbc:mysql://localhost:3306/database?useUnicode=yes&characterEncoding=UTF-8&serverTimezone=Europe/Moscow
The pros and cons are pretty much identical.It depends on whether you want this or not.
Be careful, if MySQL timezone differs from your system time (for instance PHP), comparing the time or printing to the user will involve some tinkering.
How about making your app agnostic of the server's timezone?
Owing to any of these possible scenarios:
You might not have control over the web/database server's timezone settings
You might mess up and set the settings incorrectly
There are so many settings as described in the other answers, and so many things to keep track of, that you might miss something
An update on the server, or a software reset, or another admin, might unknowing reset the servers' timezone to the default - thus breaking your application
All of the above scenarios give rise to breaking of your application's time calculations. Thus it appears that the better approach is to make your application work independent of the server's timezone.
The idea is simply to always create dates in UTC before storing them into the database, and always re-create them from the stored values in UTC as well. This way, the time calculations won't ever be incorrect, because they're always in UTC. This can be achieved by explicity stating the DateTimeZone parameter when creating a PHP DateTime object.
On the other hand, the client side functionality can be configured to convert all dates/times received from the server to the client's timezone. Libraries like moment.js make this super easy to do.
For example, when storing a date in the database, instead of using the NOW() function of MySQL, create the timestamp string in UTC as follows:
// Storing dates
$date = new DateTime('now', new DateTimeZone('UTC'));
$sql = 'insert into table_name (date_column) values ("' . $date . '")';
// Retreiving dates
$sql = 'select date_column from table_name where condition';
$dateInUTC = new DateTime($date_string_from_db, new DateTimeZone('UTC'));
You can set the default timezone in PHP for all dates created, thus eliminating the need to initialize the DateTimeZone class every time you want to create a date.
Check Timezone
SELECT ##system_time_zone as System_tz ,##global.time_zone as MYSQL_timeZone, NOW() as timenow_bymysql;
SET GLOBAL time_zone = '+05:30';
OR
change system time zone then restart MariaDB/MYSQL
and check again timezone

MySql unix_time() function with only date argument

Ok, so the following works fine
mysql> SELECT UNIX_TIMESTAMP('2007-11-30 10:30:19');
But if I give only a date argument, like in:
mysql> SELECT UNIX_TIMESTAMP('2007-11-30');
Then somehow I am getting the timestamp equivalent to 2007-11-30 18:30 GMT. Can I somehow reset it to give timestamp for the beginning of that particular day? Like UNIX_TIMESTAMP('2007-11-30'); should give the timestamp equivalent of UNIX_TIMESTAMP('2007-11-30 00:00:00'); I need to filter out some records from a table based an event that happend after a certain date.
Thanks
[EDIT]: I don't know how but this seems to be working as expected now. Screenshots: 2007-11:30 00:00:00 2007-11:30 18:30:00 2007-11:30
I have checked it But i am getting same timestamp for '2007-11-30 00:00:00' and '2007-11-30'
mysql> SELECT UNIX_TIMESTAMP('2007-11-30 00:00:00');
+---------------------------------------+
| UNIX_TIMESTAMP('2007-11-30 00:00:00') |
+---------------------------------------+
| 1196361000 |
+---------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT UNIX_TIMESTAMP('2007-11-30');
+------------------------------+
| UNIX_TIMESTAMP('2007-11-30') |
+------------------------------+
| 1196361000 |
+------------------------------+
Can you run these queries on your machine and check timestamp values.
I also checked, for me as well it is giving for 00:00:00. On further investigation, I came across this Here:
The server interprets date as a value in the current time zone and
converts it to an internal value in UTC. Clients can set their time
zone as described in Section 10.6, “MySQL Server Time Zone Support”.
On further searching, it became apparent that there is a variable system_time_zone, that is set when server starts using server machine's timezone. See here also
For each client connecting, they can set their own timezone as
mysql> SET time_zone = timezone;
So finally, you need to check your system_time_zone, set it to proper value.
I hope it will work well then....
Found a way to make sure, that the UNIX_TIMESTAMP function returns the correct timestamp irrespective of anything interfering with the timezone etc
>> SELECT UNIX_TIMESTAMP(CONCAT(t.DATE,' 00:00:00')) FROM db.table_name t
That is, to append the 00:00:00 manually in the query string.

Hibernate and MySQL: UTC datetime

We have a MySQL database where UTC timestamps are persisted into a DATETIME column.
I am retrieving these times via Hibernate (into a Date property, with TemporalType.TIMESTAMP) and wish to display them to the user unchanged.
The issue I am seeing is that when Hibernate reads the column value, it assigns a timezone (seconds from epoch) value to the object's Date property. However, it is storing this value as per the local time zone.
mysql> create table datetest(mydate datetime);
Query OK, 0 rows affected (0.13 sec)
mysql> insert into datetest values('2012-07-25 16:00:00');
Query OK, 1 row affected (0.00 sec)
mysql> select mydate from datetest;
+---------------------+
| mydate |
+---------------------+
| 2012-07-25 16:00:00 |
+---------------------+
1 row in set (0.00 sec)
Loading the "datetest" object within Hibernate and viewing the "mydate" value shows the value as:
2012-05-24T15:00:00.000+0100
I am in the UK, so +0100 (GMT+DST) is the local timezone. This matches the UNIX_TIMESTAMP() result:
mysql> select unix_timestamp(mydate) from datetest;
+------------------------+
| unix_timestamp(mydate) |
+------------------------+
| 1343228400 |
+------------------------+
1 row in set (0.00 sec)
I presume that when Hibernate loads the record it uses UNIX_TIMESTAMP() to populate the Date property of the object. The documentation for UNIX_TIMESTAMP() states:
The server interprets date as a value in the current time zone and
converts it to an internal value in UTC
I do not have control to change the server's time zone globally, and there are many other timezone related columns in our database which should not change. So how can I tell Hibernate that only some column values are UTC and ensure it does not apply any timezone 'formatting' to them ?
Within the MySQL command line client I can change the local timezone using
SET TIME_ZONE='+0:00'
And this allows UNIX_TIMESTAMP() to return a UTC value, but I cannot work out how to tell Hibernate to send this value before running the Criteria/Projection that extracts the information from the database..
A Java Timestamp doesn't have any time zone. The time zone you see is your local time zone, which is displayed by the method which transforms the Timestamp instance into a readable String (and that you've not told us in your question). And for your convenience, this method seems to use your local time zone, in order for you to be able to easily compare the time it displays with the time displayed by your wall clock.
If you want to format the Timestamp instance in another way, using another time zone, use SimpleDateFormat.

Mysql: Convert DB from local time to UTC

I need to convert an existing (datetime fields) db from local time ut UTC.
The values are stored ad datetimes on a server with time zone CET (+1) (with summertime +2). When selecting data I use UNIX_TIMESTAMP(), which magically compensates for everything, ie, time zone shift and dst (if i've read the docs right).
I'm moving the db to a new server with UTC as system time.
Simply subtracting -1 H won't work, as summer time is +2.
Any ideas for a clever way to do this? (using sql or some script lang)
First you need to make sure the mysql.time_zone_name table is populated. If it's empty, you can follow the instructions on this page to populate it:
http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html
It's typically as simple as running a command like this in the shell:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
Once that table is populated you can use the CONVERT_TZ() function to update the existing values in the DB:
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_convert-tz
Here are two examples to show how it converts datetimes from CET to UTC in winter vs summer:
mysql> SELECT CONVERT_TZ('2010-01-22 12:00:00','CET','UTC');
+-----------------------------------------------+
| CONVERT_TZ('2010-01-22 12:00:00','CET','UTC') |
+-----------------------------------------------+
| 2010-01-22 11:00:00 |
+-----------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT CONVERT_TZ('2010-07-22 12:00:00','CET','UTC');
+-----------------------------------------------+
| CONVERT_TZ('2010-07-22 12:00:00','CET','UTC') |
+-----------------------------------------------+
| 2010-07-22 10:00:00 |
+-----------------------------------------------+
1 row in set (0.00 sec)
It should be noted that the conversion for dates from one timezone to another or to UTC can only be done reliably if the dates are in the past.
Timezone definitions change. They are a human definition of how to deviate from the "sun clock", and those definitions can and do change constantly. So the only valid conversion is for dates in the past, because that will not change anymore.
Any date in the future cannot reliably be converted, because the conversion can only take into account the currently known timezone definition.
Simple example: Let's create a meeting appointment next year in Berlin, Germany. We agree today that we want to meet at 12:00 on July 1st, 2014 at Alexanderplatz. That date would be translated to 10:00 UTC on that day.
Now if some government decides to opt out of daylight saving time in 2014, you'd have a problem deciding whether you should show up at 12:00 local time, or at 11:00 local time, because the conversion back from UTC will result in a different local time.
If you had saved the original date of "2014-07-01 12:00 Europe/Berlin", you will be there at that exact time at noon, like everyone else.
In the original server, you can use one of the following expressions inside an UPDATE query:
CONVERT_TZ(your_datetime_field,'SYSTEM','UTC')
CONVERT_TZ(your_datetime_field,##global.time_zone,'UTC')
Alternatively, in the destination server, if you know the time zone of the original server (for example 'Europe/Berlin') you can use one of the following expressions:
CONVERT_TZ(your_datetime_field,'Europe/Berlin','UTC')
CONVERT_TZ(your_datetime_field,'Europe/Berlin',##global.time_zone)