MySQL Query "How long ago" + 6hours - php

With the help of a friend, I got a webpage going that tracks different stats and saves it in an SQL database.
One of the information that returns, is when the latest score was submitted to the database. It works fine, but the webhost is in a different timezone and I am unable to change that timezone.
So therefore I was thinking about changing our query to one which returns how long ago the score was added.
Current code:
$statement = $adapter->query("
select name,
SUM(score_1) as score_1,
SUM(score_2) as score_2,
SUM(score_3) as score_3,
(SUM(score_1)+SUM(score_2)+SUM(score_3)) as total,
DATE_FORMAT(MAX(creation_time), '%d %b %H:%i') as creation_time
from score_entry
WHERE DATE(creation_time) = CURDATE()
group by name ORDER BY total DESC");
It grabs the information stored in the past day (from 00:00 this day), and I'm not sure if that is also affected by the incorrect timezone.
After a lot of searching around, I can't seem to find the solution to my exact problem.
I have tried to set the timezone in MySQL, but it's a shared host by Namecheap, they don't allow it.

Take a look at the time zone documentation.
Using the SET time_zone = timezone; command you will be able to set the time zone on a per-connection basis.
In addition, storing dates in a TIMESTAMP column makes MySQL convert the time to UTC and then it converts it back to the current time zone when you access it. Thus it makes storing and retrieving time zone agnostic.

Set the time zone in your PHP script using the posted solution. It's also possible to send it the datetime to use in your query using PHP's date function.

Related

MySQL delete older then * hours

I want to use the following code to SELECT data older then 1 minute.
SELECT * FROM `auth_temp` WHERE date > (NOW() - INTERVAL 1 MINUTE)
But it didn't work. Then I checked some other topics and one person talked about the server time, I just asked my host and he said the server time is: 15:30
When at my place and the logs in MySQL it is 21:30, aka 6 hours later.
Anyone how I should asjust my code to that?
Thank you all!
You are hitting a timezone issue. Most servers run on UTC. If you have a TIMESTAMP as the field type, MySQL will convert the time from server time to UTC and back. You can adjust what MySQL considers server time using SET time_zone = timezone; (Docs). If you actually care about timezones it is advisable to just use UTC and convert in your application.
Your current SQL statement will only select data newer than 1 minute. Change it to:
SELECT * FROM auth_temp WHERE date < (NOW() - INTERVAL 1 MINUTE)
This will select data that is older than one minute. If you are using NOW() for setting the date column when you are inserting the row then that small fix should do it even if the time zones are different between your application and database layer. If you are setting the date column from your application layer you will have syncing issues if the time zone is set differently than the database layer.
It sounds like the MySQL server is either running in a different time zone or running on Universal Time (UTC) which is common. Running MySQL on UTC time is a good way to deal with users in multiple time zones. In your code, you should be able to synchronize the time zones in use on the database and application layers if it's set to UTC time easily. If it's set to a different time zone, it should be possible as well but not recommended.

How to deal with time zone in MySQL?

I have a script which has to do a "Google Analytics" like task.
Basically display visitor statistics for a user.
I want to generate a report in the time zone of the user who is requesting it.
So far I have written a code with this:
SET time_zone = timezone;
What it does it sets the time zone per each MySQL connection. If a user retrieves data with timestamp the timestamp is converted to the timezone of the connection. I am storing the UTC in the timestamp.
So everything seems to work. But some people are saying that this is a wrong approach. Because multiple user can't connect to the database with different time_zone setting.
But the MySQL doc says:
Per-connection time zones. Each client that connects has its own time
zone setting, given by the session time_zone variable. Initially, the
session variable takes its value from the global time_zone variable,
but the client can change its own time zone with this statement
However they keep insisting that you should not do anything with time zone in MySQL at all. You should do it all in your (for example) PHP code.
Here a similar question with this answer.
But how can I do it in the PHP code? I mean I know how to convert a time with a time zone in PHP but it's not like I am retrieving a single row.
I am retrieving thousands of rows and GROUP them by the date in the timestamp field:
SELECT ...
FROM logs
WHERE
user_id = :user_id
AND timestamp >= CURDATE()
GROUP BY DATE(timestamp)
It is very important that MySQL is using the index of timestamp because I have millions of. Does the index work even though I am using a function on the timestamp GROUP BY DATE(timestamp)? If not how else could I accomplish this?
So how should I do this all? I would be really thankful for some advice.
Now User converts all timestamps to his tz and uses timestamp(*user) >= CURDATE(*user).
I think the other way is to
convert timestamp(user) to timestamp(server)
and use
timestamp(*server) >= CURDATE(*server)
example
dates =(5,6,7)
(convert to my tz) dates-2 = (3,4,5)
(check constrain directly with this array )biggerThan3 result=(4,5)
2nd way
(convert constraint to ts server) biggerThan3 -> biggerThan(3+2)5
(check constraint with server array) dates =(5,6,7) result=(6,7)
result can be converted to (4,5)

How to Ensure the Correct Sorting on the Base of Date and Time in MySQL

I am in a great confusion now. I have a comments table in mysql database. in comments table there is a field comment_posted_time (type DATETIME), I sort all the comments like this
$query = "SELECT * FROM comments ORDER BY comment_posted_time DESC";
Now, This can produce wrong results. I give you an example. Suppose there are two users sitting in front of computer, one in India and the other in America. Suppose India's Time is 10 hours forward from America. first the user from India posts a comment and its current local time is stored in comment_posted_time (type DATETIME). After 1 hour the user from America posts a comment and its current local time is stored in comment_posted_time (type DATETIME) as well. Now, in database the later posted comment from American User will not be counted the most current comment and sorting will not be correct.
How to handle this situation?
There is no difference where are your users, your php and mysql are in one server, so you must not have a problem with times, You can show times for each user by his timezone converting it by php, but don't change mysql default timezone for each user. Design your comments table and set on comment_posted_time default value NOW(), and don't use this field in your insert queries. So all records in that field will saved in same timezone.
How are getting the date for comment_posted_time? Typically this would be the current date on the MySQL server. If you're getting the datetime from the client machine (which I would NOT recommend), you could get the UTC date/time and then convert it back to the local time when you display it.
To store the current time from the MySQL server, you can do something like:
update comments set comment_posted_time = NOW() where id=...
This will not differ based on the client...
You can convert the date to its UNIX_TIMESTAMP and then sort by that.
$query = "SELECT * FROM comments ORDER BY UNIX_TIMESTAMP(comment_posted_time) DESC";
You can read more about UNIX_TIMESTAMP() documentation.
Edit:
You should not be storing the comment_posted_time relative to different timezones. All of the times should be relative to one timezone, like GMT, or the machine running php.
So if you're facing the problem, that your users are in different timezones you should ALWAYS calculate timepoints to one given timezone bofore persisting it (usually you take the main servers timezone, or UTC per default). With this approach you can do both: order by timepoint and show users the timepoint calculated to their timezone.

query database for results within a certain time using the user's timezone

How can I query a set of results that belong to a specific time period according to the user's time.
For example: "select * from table where datestamp like ".date("Y-m-d",strtotime("-1 day"))."%"
would give me results within the past 24 hours based on the server time. How can I do this query to be based on the user's time rather than the server's time?
You can do this in 3 steps:
1. Detect the client timezone
This is difficult: Different browsers use different acronyms and conventions for representing names of timezones. You should use an existing implementation, like jsTimezoneDetect.
2. Pass the timezone information to PHP
If you need to use timezone dependent PHP functions (like date() in your exemple), you can set the timezone with:
date_default_timezone_set($TZ);
Where $TZ is the variable where you stored the timezone from the client request.
3. Pass the timezone information to MySQL
If you need to use timezone dependent MySQL functions, you can set the timezone for the current MySQL session with:
mysql_query("SET time_zone = $TZ");
In order to find out how to get your web client timezone, please read this question
Ask your user which timezone he's in, then subtract/add the offset to your server's time.
"The last 24 hours" are the same all over the world though, so I'd rather change the query to encompass the last 24 hours, not the same day:
SELECT * FROM `table`
WHERE `datestamp` BETWEEN DATE_SUB(NOW(), INTERVAL 1 DAY) AND NOW()

How to get UNIX_TIMESTAMP to not offset a datetime field when in different time zones?

I have built a small forum where users can post messages. My server is in the United States, but the userbase for the forum is in Taiwan (+15hrs).
When someone posts to the form, I store the time in my mySQL database in the format YYYY-MM-DD HH:MM:SS. When I look in the database, the time displays the proper time (the time that the person in Taiwan posted it).
However, when I use UNIX_TIMESTAMP to get the date out of the database, the time is altered.
Example:
I post something to the forum. The datetime on my wrist watch is 2009-10-2 11:24am (Taiwan Time)
I look in the database and it says the datetime is 2009-10-2 11:24am (same time as my wrist watch. good!)
Then when I use UNIX_TIMESTAMP to display the date on my website, it shows as 2009-10-03 4:22 pm (bad! it applied an offset)
Is there a way I can get UNIX_TIMESTAMP to stop converting the time (applying an offset) when I query the date from the database?
Extra Info:
I'm using PHP
I have set the timezone in my PHP to Taiwan (date.timezone = Asia/Taipei)
If a user is in another timezone than Taiwan, I want it to convert the time to Taipei time. The site is nearly 100% Taiwan used so I just want Taiwan time to show all the time even if they're in another timezone.
I display the date in lots of areas around the site in different date() formats.
Basically everything works great except that when I use UNIX_TIMESTAMP to query the data out, it applies an offset to the time.
Thanks!
MySQL writes dates "as-is", also reads them so, but UNIX_TIMESTAMP treats any input dates as in your local timezone and converts them to UTC/GMT timestamps meaning it will apply your local timezone offset, now if you process your timestamps returned from mysql via eg. php date() it will again apply your local timezone offset(note there is also gmtime() which does not do that), which will produce unwanted results.
But you can get by with this following trick which will subtract your session timezone before UNIX_TIMESTAMP() applies it, so you will get the exact number regardless of the server/local timezone if you want the exact same date in db as if it were a GMT time.
mysql> SELECT UNIX_TIMESTAMP(CONVERT_TZ("2013-05-27","GMT",##session.time_zone));
+--------------------------------------------------------------------+
| UNIX_TIMESTAMP(CONVERT_TZ("2013-05-27","GMT",##session.time_zone)) |
+--------------------------------------------------------------------+
| 1369612800 |
+--------------------------------------------------------------------+
1 row in set (0.00 sec)
Another solution would be to set the servers or session timezone to 0(GMT), so there will be no real conversions taking place.
MySQL takes system's default timezone setting unless told otherwise, it explains the problems you are having; take a look at MySQL's time zone reference manual for more details. Based on my past experience I've come to a conclusion UTC is the best choice for storing date and time; when displaying it to the user, they are converted to user's timezone.
If possible, change all date and time entries in the DB to UTC, configure timezone in PHP usingdate_default_timezone_set()and make sure to convert it properly when rendering it to the user and when storing it in the database as well. If storing UTC values is not an option, you may simply convert them by following time zone reference guide the same way as with UTC.
What you need to do is grab raw date and time from the database and then use PHP's DateTime to convert it. Take a look at DateTimeZone as well.
The best that I have found to this problem is using this:
SELECT UNIX_TIMESTAMP(CONVERT_TZ(<<>>,'+15:00','+00:00')) +TIMESTAMPDIFF(second,utc_timestamp(), now())
Example: I want to get the timestamp of 31-may-2012 at 23:59:59, Local time.
SELECT UNIX_TIMESTAMP(CONVERT_TZ('2012-05-31 23:59:59','+15:00','+00:00')) +TIMESTAMPDIFF(second,utc_timestamp(), now())
This way I get the timestamp GMT-0, corresponding to the localtime.
I have found a possible solution which is to just retrieve the date from the database without converting it to Unix time, and then just using strtotime(); to convert it to Unix time. Basically instead of converting using sql, i'm converting using php. The only things I don't like about it are: strtotime() < I'm not sure how reliable this function is, and I have to go and change about 100 places where i'm using UNIX_TIMESTAMP (doh!)
Are there any other ways?

Categories