mysql different server, same content, different count - mysql

I have 2 servers, live and beta, and have 2 identical databases between live and beta, but the count() return different number
LIVE:
mysql> SELECT COUNT(*) FROM `tbl_application_user` WHERE created >= '2014-06-01 00:00:01' and created < '2014-07-01 23:59:59';
+----------+
| COUNT(*) |
+----------+
| 3432 |
+----------+
1 row in set (0.02 sec)
BETA (ubuntu, mysql):
mysql> SELECT COUNT(*) FROM `tbl_application_user` WHERE created >= '2014-06-01 00:00:01' and created < '2014-07-01 23:59:59';
+----------+
| COUNT(*) |
+----------+
| 3444 |
+----------+
1 row in set (0.00 sec)
And when I try local mysql on my laptop (Windows 8.1, mysql), it returns the same number as the live.
mysql> SELECT COUNT(*) FROM `tbl_application_user` WHERE created >= '2014-06-01
00:00:01' and created < '2014-07-01 23:59:59';
+----------+
| COUNT(*) |
+----------+
| 3432 |
+----------+
1 row in set (0.03 sec)
mysql>
What causes the BETA server to return different number?
Thanks,

The time zone on the BETA server is probably different from the other machines. Although times and dates are stored as UTC, they will be interpreted in the connection's time zone when used literally, as in the WHERE part of your query.
For your reference: 11.3.1 The DATE, DATETIME, and TIMESTAMP Types
MySQL converts TIMESTAMP values from the current time zone to UTC for
storage, and back from UTC to the current time zone for retrieval.
(This does not occur for other types such as DATETIME.) By default,
the current time zone for each connection is the server's time. The
time zone can be set on a per-connection basis. As long as the time
zone setting remains constant, you get back the same value you store.
If you store a TIMESTAMP value, and then change the time zone and
retrieve the value, the retrieved value is different from the value
you stored. This occurs because the same time zone was not used for
conversion in both directions. The current time zone is available as
the value of the time_zone system variable. For more information, see
Section 10.6, “MySQL Server Time Zone Support”.

maybe the created field is deferent in your twoo databases.
if you are using triggers for created field and replication this issue is normally casue of the time delay in replication

Related

How to test database record with different time zone?

Now I am developing a rails project.
My database is MySQL.
I check my MySQL's timezone:
mysql> SELECT ##global.time_zone, ##session.time_zone;
+--------------------+---------------------+
| ##global.time_zone | ##session.time_zone |
+--------------------+---------------------+
| SYSTEM | SYSTEM |
+--------------------+---------------------+
And the SYSTEM timezone is:
mysql> SELECT EXTRACT(HOUR FROM (TIMEDIFF(NOW(), UTC_TIMESTAMP))) AS `timezone`;
+----------+
| timezone |
+----------+
| 9 |
+----------+
Also, my linux system's timezone is:
$ date +'%:z %Z'
+09:00 JST
Now, when I insert a record to database, the created_at value will be utc time. For example:
# Now is 14:25:59
Product.create(name: 'Best')
# select created_at from products;
# 5:25:59
So if I test the feature with rspec in my spec source, I should get that data from database and plus 9 to equal the current system time. Is it good?
Why the data been saved as a utc time with active_record? If use this configuration, is there a way to test the database record in a right way?
The (maybe) best approach is to save all at UTC-Time. So Then you can use the Time.in_time_zone to get the time inside a specified zone.
My 20:00 PM is UTC 13:00 and maybe your 06:00 AM - but in the database its just the same time - UTC.
If it then comes to Rendering you use the rails helper for timing and always give the created_at.in_time_zone.
If it comes to rendering you just throw out the UTC timestamp and let JavaScript to the rest, formatting the timestamp to the users local time.

Better way to safely insert UTC time value into mySQL TIMESTAMP variable?

My application wants to insert a timestamp value into a TIMESTAMP variable in a mySQL database. The timestamp value is a UTC time in the usual "YYYY-MM-DD HH:MM:SS" format. The problem is that my SQL server is set to use SYSTEM time (SELECT ##global.time_zone says SYSTEM), and the system timezone is Europe/London (the server is running Ubuntu 14.04), so mySQL does a daylight-saving conversion and stores the value one hour off from what it ought to be. (I guess if I was in another timezone e.g. CST then I'd have an unwanted timezone offset as well as the daylight saving hour).
To get mySQL to do The Right Thing it appears that I need to covert the UTC timestamp into system time before I insert it so that mySQL can convert it from system time to UTC time before it stores it internally. This bit of code has the desired effect:-
mysql> select timestamp("2015-05-06 12:34:56")+CURRENT_TIMESTAMP-UTC_TIMESTAMP;
+------------------------------------------------------------------+
| timestamp("2015-05-06 12:34:56")+CURRENT_TIMESTAMP-UTC_TIMESTAMP |
+------------------------------------------------------------------+
| 20150506133456.000000 |
+------------------------------------------------------------------+
I'm going to run with this for now, but it seems like a bit of a palaver, so is there a better way?
[edit] Another round of RTFM'ing gave me this idea...
mysql> select CONVERT_TZ("2015-05-06 12:34:56", "+00:00", "SYSTEM");
+-------------------------------------------------------+
| CONVERT_TZ("2015-05-06 12:34:56", "+00:00", "SYSTEM") |
+-------------------------------------------------------+
| 2015-05-06 13:34:56 |
+-------------------------------------------------------+
That looks a lot cleaner. Any better ideas?
You can probably use the CONVERT_TZ function which uses the specified timezone to parse the date instead of system timezone:
SELECT CONVERT_TZ('2015-05-06 12:34:56','+00:00','SYSTEM') AS `Local Time`,
UNIX_TIMESTAMP(CONVERT_TZ('2015-05-06 12:34:56', '+00:00', 'SYSTEM')) AS `UNIX Timestamp`;
+---------------------+----------------+
| Local Time | UNIX Timestamp |
+---------------------+----------------+
| 2015-05-06 17:34:56 | 1430915696 |
+---------------------+----------------+
The local time value will differ depending on which system the query is run. However, the UNIX timestamp value will be same.
You can then insert the local time value in the timestamp column; MySQL will store the value after conversion.

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.

How do I get the current time zone of 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