In my PHP.ini file I set the TimeZone like so...
'America/New_York'
so when i ran a simple php Date() function
echo date("Y-m-d H:i:s");
I get the Correct dateTime according to 'MY' system time as that's what i am comparing against and want to store in my MySQL db as well. (as reported from PHP).
Now the problem is, i exported a MySQL db to PDF format, just to see what it looked like, and the time was 1 hour back, ex.. it was (10:00 a.m.) here and the PDF footer said (9:00 a.m.)
So.. i got to thinking.. my PHP script will INSERT into the db the correct dateTime that i need.. But i have alot of dateTime comparing going on for accounts,
I know if i run any MySQL Queries in phpMyAdmin then i will get the wrong dateTime.
i have tried running in (phpMyAdmin SQL Query)
SET time_zone = 'America/New_York';
-and-
SET time_zone = '-05:00';
But when I run the query
SELECT ##global.time_zone, ##session.time_zone;
I get back SYSTEM and SYSTEM.
(I should also mention i am on shared hosting)
If I use the MySQL NOW() function in my query, the time entered into the db will be calculated by MySQL, according to it's own timezone.
like this..
mysql_query("INSERT INTO table (id, value, time_created)
VALUES ('{$id}', '{$value}', NOW())");
I understand that I will have to do all of my INSERTING and comparing in PHP to keep the times right.. but with the above, it will insert the wrong time.
so this is my dilemma...
But will this affect anything that i am not foreseeing? I just feel like somehow this will affect my times.
So how can I get around this or get MySQL on the SAME timezone? and make sure that ALL my date/times are right, not the 1 hour behind..
Two queries ran successively through PhpMyAdmin will be executed in two separate sessions (connections) therefore SELECT ##session.time_zone alone will always return "SYSTEM".
I doubt you can (and I hope you cannot) change the global time zone on a shared server, so always expect "SYSTEM" for SELECT ##global.time_zone. On the other hand you should be able to change your session's time zone.
Try running these two queries in one execution, it should show the new time zone :
SET time_zone = '-05:00'; SELECT ##session.time_zone; -- same session
NOW() returns time in the current session time zone, so time zone does matter. However I would rather store times in GMT time zone, but I suppose that's more a matter of taste.
Depending on what you may do and what you may not do (on your shared hosting) you could choose to either use the following statement as the start of all your queries: "set time_zone='-05:00';", for example: "set time_zone='-05:00'; select foo from bar;" or (maybe the most reliable option): only use timestamps in your tables and queries and create DateTime objects in PHP based on the timestamp you received.
Related
I am working on a project based on PHP i have an issue that i purchased a hosting whose server is of another country and i am in Pakistan when i enter data in database table from PHPMyAdmin in enters the date of that country which is 11 hours behind us that's why my insert queries and update queries not working Php time zone is set but server time zone is not set.
php_value date.timezone 'Asia/Karachi';
i use this is my htaccess file Also use
date.timezone = "Asia/Karachi"
in php ini file
(To long for comment)
If you write a website with user specific timezones, then managing timezones at database site is a bit complicated. I prefer this solution:
Try to store all timestamp as bigint values in unix time.
Converting time to string only at user interface.
Examples
For Database storing I use:
UPDATE table SET start_time = UNIX_TIMESTAMP();
Results are either retrieved as native integers or converted to UTC/GMT time:
SELECT unix_time, UNIX_TIMESTAMP(db_date)
You can test it with:
SELECT UNIX_TIMESTAMP(), UNIX_TIMESTAMP(now());
In PHP, you can now simply do fast time calculations by adding and substracting. It printing a time at the user interface, set the timezone (maybe evaluated by a database query) and use date() or strftime(), or any date+time class.
You should set your MySQL timezone when you open the connexion to the database server in PHP.
You can see some example here: Set timezone in PHP and MySQL
You could also do it like this (works with MariaDB, never tested on MySQL):
$db->exec("SET time_zone='Asia/Karachi';");
That way you don't have to update your database configuration and you can update the set depending on a variable.
I'm trying to add datetime for check record changes. I'm using datetime datatype in table.
`date_added` datetime DEFAULT '0000-00-00 00:00:00',
I use following php built-in function using for datetime column in the query
date("Y-m-d H:i:s");
Problem is that this function date("Y-m-d H:i:s"); giving me two different date and time when i check in same time on server.
Localhost Result
date("Y-m-d H:i:s"); == 2016-07-12 13:10:04
Server Result
date("Y-m-d H:i:s"); == 2016-07-12 05:08:07
So when i use TimeAgo function on date_added column it is giving me wrong time, I mean the server time. For example I add a record then function will return me Record Added 8 Hours Ago so its totally wrong. I would like to know how can i add real time of an event into database that i can show using TimeAgo() function.
Is there any way to do that without change the server timezone, because if I change the timezone then it will be showing correct time only for those who are in the same region but what will be get others? I think they will face same issue.
I wanted to develop something like Facebook DateTime Functionality.
Can any one guide me how can I achieve this kind functionality? I would like to appreciate. Thank You
Instead of fiddling with timezones, why not just do
ALTER TABLE `your_table`
CHANGE `date_added` `date_added`
TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
This will change your column from a DATE column to a TIMESTAMP column, converting all the dates to their respective UTC timestamps in the process.
When a new row is inserted, it will use the current timestamp as a value. Timestamps are always in UTC, so you don't have to change the timezone on your MySql server, nor supply the date when inserting a new row.
If you cannot or want not change your columns, you can also just select the timestamp via
SELECT UNIX_TIMESTAMP('date_added') FROM your_table;
For your TimeAgo, you can then just do
$now = new DateTime;
$dateAdded = new DateTime("#$yourTimestampFromDb");
$dateAdded->setTimezone($now->getTimezone());
$timeSinceAdded = $dateAdded->diff($now);
When you supply a timestamp to DateTime, it will always use UTC regardless of your default server timezone set. Consequently, you have to either convert $dateAdded to the default timezone (as shown above) or convert $timeSinceAdded to UTC.
To change the dateTime to the currently visiting user's timezone, you either
need to have this information in your database, e.g. because you are asking registered users to supply this information
or you determine it at runtime, usually by doing a GeoIP lookup on the visiting user's IP or by sending the DateTime Offset from the user's browser.
In any case, you then just change both DateTimes to that timezone. This is easily done via setTimezone().
The $timeSinceAdded will then be a DateInterval object, which you can use like this
echo $timeSinceAdded->format('%a total days');
Please refer to the links for further details, for instance on the available format modifiers.
If you're accessing the same database server from clients with different timezone settings, you could also insert and check the date/time fields in sql:
INSERT INTO my_table SET date_added = NOW();
and then also check with something like
SELECT * FROM my_table WHERE TIMESTAMPDIFF(SECOND, date_added, NOW()) > 3600;
to select rows that are older than 1 hour.
Your question is a bit ambiguous but i'll try to explain a workaround that i think should fix this issues.
If you allow other users to add or update your database then, you should be having some information about them, like which city/continent they are coming from. You might also have telephone contacts and more about them.
If it is true that you possess such information about your users in your database then use that information to detect and load their timezone when they log into your system.
You can have a table with all the timezones or create an array that will hold all the known timezones so that when you call
date_default_timezone_set('continent/city')
function you can dynamically change the parameters to suit the current users timezone and later use that to affect date added field.
Problem
TimeAgo/nicetime function uses strtotime() to convert your datetime field value to unix timestamp. You receive a number of seconds since January 1 1970 00:00:00 UTC until the date you passed as a string. Then time() function returns the number of seconds until now, and nicetime compares the difference. The problem is in strtotime, when we send to it the text like "2016-07-12 05:08:07", it has no idea what time zone that is in and how it should be converted to UTC, so it uses the best guess, often incorrect.
Quick Solution
Specify the time zone of your date that you pass into nicetime() function. Instead of doing this:
$date = '2016-07-04 17:45'; // get from database
print nicedate($date);
try this:
$date = '2016-07-04 17:45';
print nicedate($date . ' America/Denver');
// mind the gap --------^
That should fix it.
Before one blindly goes ahead and starts comparing times, or performing date / time calculations on values retrieved from a database, it is essential that we understand the individual database's configuration settings to ensure our calculations are correct.
It should be noted that the MySQL timezone variable's default setting is SYSTEM at MySQL startup. The SYSTEM value is obtained from the the operating system's GLOBAL time_zone environment variable.
MySQL's default timezone variable can be initialised to a different value at start-up by providing the following command line option:
--default-time-zone=timezone
Alternatively, if you are supplying the value in an options file, you should use the following syntax to set the variable:
--default-time-zone='timezone'
If you are a MySQL SUPER user, you can set the SYSTEM time_zone variable at runtime from the MYSQL> prompt using the following syntax:
SET GLOBAL time_zone=timezone;
MySQL also supports individual SESSION timezone values which defaults to the GLOBAL time_zone environment variable value. To change the session timezone value during a SESSION, use the following syntax:
SET time_zone=timezone;
In order to interrogate the existing MYSQL timezone setting values, you can execute the following SQL to obtain these values:
SELECT ##global.time_zone, ##session.time_zone;
It should be noted also that:
The current session time zone setting affects display and storage of time values that are zone-sensitive. This includes the values displayed by functions such as NOW() or CURTIME(), and values stored in and retrieved from TIMESTAMP columns. Values for TIMESTAMP columns are converted from the current time zone to UTC for storage, and from UTC to the current client time zone for retrieval.
To obtain values in UTC time, use the UTC_DATE(), UTC_TIME() or UTC_TIMESTAMP() functions instead. To convert to another time zone, pass the value of the appropriate UTC function return to convert_tz(), which requires the zoneinfo tables to be generated (see below).
In your circumstances, if you DO NOT want to / CAN NOT change the SERVER time_zone value, you will have to explicitly set the individual SESSION timezone values for each client connection which will enable you to draw a line in the sand and have a known base from which you can convert and display a facebook user's post time into a viewer's local timezone.
To explicitly set the session timezone when connecting, issue the following command:
SET SESSION time_zone = '+10:00';
When you explicitly set the SESSION time_zone, and store a TIMESTAMP value, the server converts it from the client's time_zone to UTC and stores the UTC value (Internally the server stores a TIMESTAMP value). When you select data from the database, the opposite conversion takes place and provides the client with a UTC time in the client's timezone.
On the topic of data types and time zone's, in PHP you are better off using the DatTimeZone class if you would like to improve the accuracy of your date and time values by facilitating daylight saving aware dates and times.
As noted earlier, if your database is MySQL, you can load / generate the zoneinfo tables with the following command:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
* where root is the username to be substituted.
Performing the generation of the zoneinfo tables allows you to use the convert_tz() function which accurately converts dates and times from one time zone to another, like so:
select DATE_FORMAT(convert_tz(now(), 'UTC', 'Australia/Perth'), '%e/%c/%Y %H:%i') AS PERTH_TIME;
PERTH_TIME;
+-----------------+
| PERTH_TIME |
+-----------------+
| 19/7/2016 19:42 |
+-----------------+
Additionally, you can generate an array of UTC time zones programmatically by calling the static function listIdentifiers() in the PHP DateTimeZone class.
May the force be with you.
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.
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)
Our production platform technologies are these: PHP, MS SQL Sever, and IIS.
PHP is set to the timezone 'Pacific/Auckland' which is current +12:00 GMT/UTC.
When we retrieve dates from SQL Server, they are consistently 12 hours 'behind' what they should be, ie. SQL Server is storing and serving them as GMT dates, even though the time zone on the server itself is Pacific/Auckland too.
Is there a hidden sp function some where you can use to set the timezone? If this is not timezone related, please enlighten me!
Can you open up sql server management studio and type "select getdate()" to make sure it is sql server that is wrong?
Are you using getdate() or another sql function to get the date?
If your statement is both accurate and general, then you should be able to reproduce this simply by inserting a row into a table with a datetime column like this:
CREATE TABLE OffBy12 (
IsThisOff datetime not null
)
GO
INSERT INTO OffBy12 (IsThisOff) VALUES ('2009-06-28')
SELECT IsThisOff
FROM OffBy12
If you're right, then the time portion of the date will not be 00:00.
If you're not correct, then this must be something more complex. In that case, you may want to say how the data are getting into SQL Server.