PHP calculating time difference, result 1 hour wrong - php

I want to calculate difference of two times and print it in pretty way. I know the difference will never exceed 24 hours, so I tried the following
$time = 7200; //time difference in seconds
date("H:i:s", $time); // should print 02:00
The result is unexpected, it prints 03:00 instead.
What am I doing wrong?

Why not the DateTime::diff??
Here, check PHP.net for DateTime class
Grabbed from php.net datetime diff page:
$datetime1 = new DateTime('2009-10-11');
$datetime2 = new DateTime('2009-10-13');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%R%a days');
//Outputs +2 days

The PHP date() function is meant for formatting absolute time stamps (as in "Friday, 20 July 2012, 15:02 UTC"), not for time differences (as in "3 hours and 5 minutes ago").
In some cases, it is possible to trick date() into producing something that looks like a correctly formatted time difference by setting your time zone to UTC and relying on the fact that the Unix epoch happens to fall on midnight in UTC. However, even then, this will only work for positive time differences of less than 24 hours.
Instead, the correct solution is to use a function designed for formatting time differences, or write one yourself. Here's a simple function to do so:
function format_time_difference ( $delta ) {
$sign = ( $delta < 0 ? "-" : "" );
$delta = abs( $delta );
return sprintf( "%s%02d:%02d:%02d", $sign, $delta / 3600,
($delta / 60) % 60, $delta % 60 );
}
Of course, you can extend this function to e.g. include days in the output if you like.

You should never use date to compute time difference. Firstly it is ugly hack. It was not intended for that purpose. And secondly, it works reliably only when timezone set to UTC.
Now, why it does not work:
PHP function date takes two arguments, format and timestamp, the latter is defined as number of seconds from 1st January 1970 00:00 UTC called unix epoch. So if you call date("H:i", 3600) and your timezone is set to UTC, it will return "01:00", cause it represents time one hour after unix epoch and the epoch was at the midnight.
The problem is, unix epoch was at the midnight only in UTC, not in the other timezones. And this is the source of the incorrect result.

Related

PHP get 00:00:00 of a unix timestamp

If I got a unix time which is e.g
1407050129
How do I get the 12:00AM of that unix day in unix timestamp , means the first minute of the day of that unix time.
Example if i want get today first minute
$today_first_min = strtotime("00:00:00");
Try this:
$that_day = "1407050129";
$that_day_first_min = strtotime(date('Y-m-d', $that_day) . ' midnight');
See demo
An alternate method to arrive at the same result... Unix time is a count of seconds since 1970-01-01 00:00:00 UTC, so each whole day is a multiple of (60*60*24) seconds.
Using this fact you can use the modulus operator (%) to calculate and then remove the remainder (ie. the seconds, hours and minutes) from the day, and get back to the first hours!
date_default_timezone_set('UTC');
$that_date = 1407050129;
$first_hour = $that_date - ($that_date % (60*60*24));
print date('Y-m-d H:i:s', strval($first_hour));
// 2014-08-03 00:00:00

php giving wrong answer when using time zone Australia/Sydney

I am developing an website to run in Australia.
so i have set the time zone as follows.
date_default_timezone_set('Australia/Sydney');
I need to calculate number of days between two dates.
I found a strange behavior in the month of October.
$now = strtotime('2013-10-06'); // or your date as well
$your_date = strtotime('2013-10-01');
$datediff = $now - $your_date;
echo floor($datediff/(60*60*24));//gives output 5, this is right
$now = strtotime('2013-10-07'); // or your date as well
$your_date = strtotime('2013-10-01');
$datediff = $now - $your_date;
echo floor($datediff/(60*60*24));//gives output 5, this is wrong, but it should be 6 here
after 2013-10-07 it always give one day less in answer.
Its fine with other timezones. May be its due to daylight saving. But whats the solution for this.
Please help.
Thanks
Why it says 5, and why this is technically correct
In Sydney, DST begins at 2013-10-06 02:00:00 - so you lose an hour in dates straddling that.
When you call strtime, it will interpret the time as a Sydney time, but return a Unix timestamp. If you converted the second set of timestamps to UTC, you'd get a range from 2013-09-30 14:00:00 to 2013-10-06 13:00:00, which isn't quite 6 days, so gets rounded down to 5.
How to get the time difference ignoring DST transitions
Try using DateTime objects instead, e.g.
$tz=new DateTimeZone('Australia/Sydney');
$start=new DateTime('2013-10-01', $tz);
$end=new DateTime('2013-10-07', $tz);
$diff=$end->diff($start);
//displays 6
echo "difference in days is ".$diff->d."\n";
Why does DateTime::diff work differently?
You might ask "why does that work?" - after all, there really isn't 6 days between those times, it's 5 days and 23 hours.
The reason is that DateTime::diff actually corrects for DST transitions. I had to read the source to figure that out - the correction happens inside the internal timelib_diff function. This correction happens if all the following are true
each DateTime uses the same timezone
the timezone must be geographic id and not an abbreviation like GMT
each DateTime must have different DST offsets (i.e. one in DST and one not)
To illustrate this point, here's what happens if we use two times just a few hours either side of the switch to DST
$tz=new DateTimeZone('Australia/Sydney');
$start=new DateTime('2013-10-06 00:00:00', $tz);
$end=new DateTime('2013-10-06 04:00:00', $tz);
//diff will correct for the DST transition
$diffApparent=$end->diff($start);
//but timestamps represent the reality
$diffActual=($end->getTimestamp() - $start->getTimestamp()) / 3600;
echo "Apparent difference is {$diffApparent->h} hours\n";
echo "Actual difference is {$diffActual} hours\n";
This outputs
Apparent difference is 4 hours
Actual difference is 3 hours

Timestamp intervals processed by date() don't calculate correctly

I have two unix timestamps in my database that I am subtracting to get a time interval in seconds:
$interval = $array["time2"] - $array["time1"]; // When echoed, $interval = 3
However, when I run this $interval through date(), like so:
echo date("g\h i\m", $interval);
these 3 seconds all of a sudden echo to:
7h00m
Does anyone have any idea why date() might be taking these three seconds and stretching them out into a 7 hour interval somehow?
The second argument to date() is a timestamp (seconds since midnight, Jan 1, 1970 GMT). Your interval is probably equating to 7am in your timezone relative to this date.

PHP: Compare file timestamp with system time

I am new to PHP and am writing a PHP script that contains a module which reads the file timestamp out of a file and then compare with system time to see whether the file is older than 5 minutes or not and I am wondering how that can be achieved. I am currently using
$timeStamp = strftime('%c', filectime($this->localPath));
$timeStamp2 = filectime($this->localPath);
The two $timeStamp and $timeStamp2 are different, the 1st one is more human readable
$timeStamp Mon Jun 20 15:17:01 2011
$timeStamp2 1308608221
What does $timeStamp2 mean?
And again, how to see if the file is more than 5 minutes old?
That is Unix timestamp actually (seconds since 1st jan 1970 or EPOCH)
You can use time() function to get current time in same Unix format.
And then subtract both time values to check whether difference is > 300 (5 min) or not.
$timeStamp2 is a UNIX timestamp (the number of seconds passed since 01/01/1970).
You can get the same thing from $timeStamp1 by doing
$timeStamp1 = strtotime($timeStamp1)
and then compare the two values
Answering your question "What does $timeStamp2 mean?"
1308608221 is the number of seconds that have passed since midnight January 1,1970.

Removing an hour from PHP (FROM_UNIXTIME)

Could you please advice how to remove an hour from unixtime.
I have a unixtime and i need to remove an extra hour before converting to normal time. Could you please advice how to do this?
Also, is Unixtime affected by the GMT time changes?
Unix timestamps are measured in seconds, there are 3600 seconds in an hour (60 minutes, each with 60 seconds = 60*60 = 3600), so just subtract:
$timestamp = time();
$timestamp_less_one_hour = $timestamp - 3600;
You can also use strtotime to accomplish the same:
$timestamp_less_one_hour = strtotime('-1 hour', $timestamp);
Or if $timestamp is simply "now" you can call strtotime without the second parameter:
$timestamp_less_one_hour = strtotime('-1 hour'); // time() - 1 hour
So you seem to be looking for GMT time instead, the trouble is GMT can include Daylight Savings Time (DST), and the "GMT" date functions in PHP actually return UTC time, which has no concept of DST. Luckily you can detect if it's DST using PHP, and basically adjust appropriately.
Get UTC time using gmdate:
$utc_time = gmdate('U'); // return Unix seconds in UTC timezone
Detect if it's DST using I:
$is_dst = gmdate('I'); // 1 when it's DST, 0 otherwise
gmdate('U') will trail GMT time during DST by an hour, thus you need to give it +3600 seconds, or 1 hour when it's DST, so putting this together:
$gmt_time = gmdate('U') + (3600*gmdate('I'));

Categories