6

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

Ayaz Ali Shah
  • 3,453
  • 9
  • 36
  • 68

5 Answers5

10

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

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.

Community
  • 1
  • 1
Gordon
  • 312,688
  • 75
  • 539
  • 559
1

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.

1

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.

ocnet
  • 51
  • 5
0

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.

Matt G
  • 1,332
  • 2
  • 13
  • 25
0

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.

Serge Uvarov
  • 113
  • 9