Calculating average time between unix timestamps - php

I have a database which contains posts that have both a creation date(unix timestamp) and a publication date(unix timestamp). I want to calculate the average time it takes a post to be published after its created. I guess im way off, but this is what i got so far:
$times = array();
foreach($posts as $post) {
$timeBetween = $post->publicationDate - $post->creationDate;
array_push($times, $timeBetween);
}
$average = array_sum($times) / count($times);
echo date("H:m:s",mktime(0,0,$average,0,0,0));
My optimal output would be something like: 1 day, 12 hours, 13 second..
Anyone?
Appreciate any help!

date() is not the correct tool for this job. date() doesn't understand a period of time like 2D 3H 27M, it only understands points in time.
In your code $average will contain a number of seconds, so you should finish with something like:-
$h = floor($average/3600);
$average -= $h*3600;
$m = floor($average/60);
$average -= $m*60;
$s = floor($average);
echo "$h:$m:$s";

Why don't you use the foreach-loop like this:
$time = 0;
foreach ( $posts as $post ) {
$time += $post->publicationDate - $post->creationDate;
}
$average = $time / count( $posts );
This way you don't need to use an array, and you got the same result.
If you want to show it like 2 days, 4 hours, 43 minutes and 2 seconds you can calculate it like this:
// 1 day = 24 hours * 60 minutes * 60 seconds = 86400 seconds
$days = floor( $average / 86400 );
$hours = floor( ( $average % 86400 ) / 3600 );
$minutes = floor( ( $average % 3600 ) / 60 );
$seconds = $average % 60;
echo $days . ' day' . ( $days > 0 ? 's' : '' ) . ', ';
echo $hours . ' hour' . ( $hours > 0 ? 's' : '' ) . ', ';
echo $minutes . ' minute' . ( $minutes > 0 ? 's' : '' ) . ', ';
echo $seconds . ' second' . ( $seconds > 0 ? 's' : '' );

Related

Getting two hours more than required

I am getting times in format of "hh:mm:ss".
I am doing sum of all those times. But here I am getting two hours more than required. so, where is the actual problem.
My code is like,
foreach($result as $key=>$value)
{
$total_markin_time[] = date('H:i:s', strtotime($value['clock_in']));
}
Getting result like,
00:33:41
16:15:22
11:06:59
11:03:59
11:13:38
15:43:34
11:29:35
foreach ( $total_markin_time as $time )
{
list( $g, $i, $s ) = explode( ':', $time );
//echo $g."-";
$total_markin_seconds += $g * 60 * 60;
$total_markin_seconds += $i * 60;
$total_markin_seconds += $s;
}
//echo $total_markin_seconds; exit;
$total_markin_hours = floor( $total_markin_seconds / 3600 );
$total_markin_seconds -= $total_markin_hours * 3600;
$total_markin_minutes = floor( $total_markin_seconds / 60 );
$total_markin_seconds -= $total_markin_minutes * 60;
When I am doing sum on this, I am gettin result 77:26:48.
Where is the problem?
Updated:
Is there any problem with floor that I have read like,
The floor() function rounds a number DOWN to the nearest integer, if necessary.
There is no error and it works right.
Calculation:
hours: 0+16+11+11+11+15+11 = 75 hours
minutes: 33+15+6+3+13+43+29 = 142 = 2 hours and 22 minutes
seconds: 41+22+59+59+38+34+35 = 288 = 4 minutes and 48 seconds
The result of sum is 77:26:48.
If you want to get just the sum of hours you should use something like this
foreach ( $total_markin_time as $time )
{
list( $g, $i, $s ) = explode( ':', $time );
$total_markin_hours += $g;
}
It's simple. All your times adds to:
288 s = 4m 48s
142 m = 2h 22m
75 h
Which in result (add hours + minutes + seconds) gives 77:26:48
You may think that You only add hours independent of minutes and seconds, but You have to add overflows of minutes and seconds.

Best scenario for calculating multiple dates from array ? - PHP

I have array of items like this:
Array
(
[0] => 0:16:0
[1] => 0:0:8
[2] => 0:5:0
...
[n] => 0:3:1
)
There could be more arrays, they are symbolize
hours, minutes, seconds.
How can I calculate 0 + 1 + 2 + ... + n and to get final number of hours, minutes and seconds?
Try this code out
$arr = array('0:16:0', '25:12:5', '0:0:10', '0:5:0');
// converting all the times to seconds
$t_seconds = 0;
foreach ($arr as $v) {
sscanf($v, "%d:%d:%d", $hours, $minutes, $seconds);
$t_seconds += $hours * 3600 + $minutes * 60 + $seconds;
}
// condition if seconds calculated are negative
$sign = ($t_seconds < 0 ? '-' : '');
$t_seconds = abs($t_seconds);
// converting seconds, taking care of wrong minutes/seconds formats like 02:63:65
$hours = floor($t_seconds / 3600);
$minutes = floor(($t_seconds / 60) % 60);
$seconds = $t_seconds % 60;
// final format
$sum = $sign . sprintf("%02d:%02d:%02d", $hours, $minutes, $seconds);
Result ($sum variable)
25:33:15
I solved by seperating hours, minutes, secounds as array from my foreach element. Then i call array, using array_sum
( thanks Rizier123 for point me on that function )
// receive values and calculate with current hours
$finalHourPause = array_sum($pauseArrayHours) . "\n";
$finalMinutePause = array_sum($pauseArrayMinutes) . "\n";
$finalSecoundsPause = array_sum($pauseArraySecounds) . "\n";

Trouble using percent sign operator (%) (PHP)

I'm attempting to convert 7500 seconds to minutes, and then the minutes to hours. If it comes out to 2 hours and 5 minutes, as in this example, I'd like to display it as "2 hours and 5 minutes". If its 2 hours even, I just want it to display "2 hours".
7500 divided by 60 divided by 60 comes out to 2.083 (3 repeated). Why does the % return 0? How can I determine if its hours exactly, or if there are minutes to display?
die("Test: " . ((7500 / 60) / 60) % 1);
For conversion, you can use:
function secondsToWords($seconds)
{
/*** return value ***/
$ret = "";
/*** get the hours ***/
$hours = intval(intval($seconds) / 3600);
if($hours > 0)
{
$ret .= "$hours hours ";
}
/*** get the minutes ***/
$minutes = bcmod((intval($seconds) / 60),60);
if($hours > 0 || $minutes > 0)
{
$ret .= "$minutes minutes ";
}
/*** get the seconds ***/
$seconds = bcmod(intval($seconds),60);
$ret .= "$seconds seconds";
return $ret;
}
echo secondsToWords(7500);
Because that is the modulus operator, which gives the remainder of the division.
You want to use /, the division operator, that returns a float. See here
I've created a nice function for that a while ago. It also does years and months (and anything you'd like) if you want.
Source + examples: http://hotblocks.nl/tests/time_ago.php
Function:
<?php
function time_ago( $f_seconds, $f_size = 2, $f_factor = 1.6 ) {
$units = array(
86400*365.25 => array(' year', ' years'),
86400*30 => array(' month', ' months'),
86400*7 => array(' week', ' weeks'),
86400 => array(' day', ' days'),
3600 => array(' hour', ' hours'),
60 => array(' minute', ' minutes'),
1 => array(' second', ' seconds'),
);
if ( isset($GLOBALS['g_units']) && is_array($GLOBALS['g_units']) ) {
$units = $GLOBALS['g_units'];
}
$timeAgo = array();
$seconds = (int)$f_seconds;
foreach ( $units AS $range => $unit ) {
if ( 1 == $range || $seconds >= $range * $f_factor ) {
is_array($unit) || $unit = array($unit, $unit);
$last = count($timeAgo) == $f_size-1;
$round = $last ? 'round' : 'floor';
$num = $round($seconds / $range);
$timeAgo[] = $num . $unit[(int)(1 != $num)];
if ( $last ) {
break;
}
$seconds -= $num * $range;
}
}
$separator = isset($GLOBALS['g_separator']) ? $GLOBALS['g_separator'] : ', ';
return implode($separator, $timeAgo);
}
?>
That's the way the mod (%) operator works. Every integer is divisible by 1, so
n % 1 = 0
for all integral n.
What are you trying to do with the % operator?
Whatever it is, you probably want to apply it on an integral value, like the number of seconds. It doesn't work for non-integral values; they are promoted to int values before the operator is applied.

Convert Standard Date to Current Time in Hours/Mins/

Say I have a date function that produces
the output: 2011-10-03
PHP:
$todayDt = date('Y-m-d');
Anyway to get this date to instead show 2 days 1 hour ago
This function might be of some use. You might want to refine the check for months a bit, but this is just a quick example:
function RelativeTime($iTimestamp, $iLevel = 2)
{
!ctype_digit($iTimestamp)
&& $iTimestamp = strtotime($iTimestamp);
$iSecondsInADay = 86400;
$aDisplay = array();
// Start at the largest denominator
$iDiff = time() - $iTimestamp;
$aPeriods = array(
array('Period' => $iSecondsInADay * 356, 'Label' => 'year'),
array('Period' => $iSecondsInADay * 31, 'Label' => 'month'),
array('Period' => $iSecondsInADay, 'Label' => 'day'),
array('Period' => 3600, 'Label' => 'hour'),
array('Period' => 60, 'Label' => 'minute'),
array('Period' => 1, 'Label' => 'second'),
);
foreach ($aPeriods as $aPeriod)
{
$iCount = floor($iDiff / $aPeriod['Period']);
if ($iCount > 0)
{
$aDisplay[] = $iCount . ' ' . $aPeriod['Label'] . ($iCount > 1 ? 's' : '');
$iDiff -= $iCount * $aPeriod['Period'];
}
}
$iRange = count($aDisplay) > $iLevel
? $iLevel
: count($aDisplay);
return implode(' ', array_slice($aDisplay, 0, $iRange)) . ' ago';
}
And some examples of usage:
echo RelativeTime(time() - 102, 1);
// Will output: 1 minute ago
echo RelativeTime(time() - 2002);
// Will output: 33 minutes 22 seconds ago
echo RelativeTime(time() - 100002002, 6);
// Will output: 3 years 2 months 27 days 10 hours 20 minutes 2 seconds ago
echo RelativeTime('2011-09-05');
// Will output: 30 days 22 hours ago
This is post is just for a solution that does not use the DateTime::diff method. It also uses inputs with greater precision, so be aware of that.
$now = date('Y-m-d H:i:s');
$then = '2011-10-03 00:00:00'; // This will calculate the difference
// between now and midnight October 3rd
$nowTime = strtotime($now);
$thenTime = strtotime($then);
$diff = $nowTime - $thenTime;
$secs = $diff % 60;
$diff = intval($diff / 60);
$minutes = $diff % 60;
$diff = intval($diff / 60);
$hours = $diff % 24;
$diff = intval($diff / 24);
$days = $diff;
echo($days . ' days ' . $hours . ' hours ' . $minutes . ' minutes ' . $secs . ' seconds ago');
At the moment I tested it, the output was:
2 days 16 hours 6 minutes 2 seconds ago
If all you want are the days and hours, then you can just choose to echo those two out:
echo($days . ' days ' . $hours . ' hours ago');
2 days 16 hours ago

PHP Time calculation

Say I have the following 2 dates, a start date and end date:
Year-Month-Day Hours:Minutes:Seconds
Start Date: 2010-12-03 14:04:41
Expiry Date: 2010-12-06 12:59:59
How could I, using PHP subtract the two dates and be left with something like:
Difference: -3 days, 2 minutes and 18 seconds (If expiry date is past 3 days for example).
http://www.php.net/manual/en/datetime.diff.php
<?php
$datetime1 = date_create('2009-10-11');
$datetime2 = date_create('2009-10-13');
$interval = date_diff($datetime1, $datetime2);
echo $interval->format('%R%d days');
//result will be +2 days
?>
I hope that is what you are looking for.
This is based on numerous online examples; you'll see similar code all around if you get your google on.
function timeSince($dateFrom, $dateTo) {
// array of time period chunks
$chunks = array(
array(60 * 60 * 24 * 365 , 'year'),
array(60 * 60 * 24 * 30 , 'month'),
array(60 * 60 * 24 * 7, 'week'),
array(60 * 60 * 24 , 'day'),
array(60 * 60 , 'hour'),
array(60 , 'minute'),
);
$original = strtotime($dateFrom);
$now = strtotime($dateTo);
$since = $now - $original;
$message = ($now < $original) ? '-' : null;
// If the difference is less than 60, we will show the seconds difference as well
if ($since < 60) {
$chunks[] = array(1 , 'second');
}
// $j saves performing the count function each time around the loop
for ($i = 0, $j = count($chunks); $i < $j; $i++) {
$seconds = $chunks[$i][0];
$name = $chunks[$i][1];
// finding the biggest chunk (if the chunk fits, break)
if (($count = floor($since / $seconds)) != 0) {
break;
}
}
$print = ($count == 1) ? '1 ' . $name : $count . ' ' . $name . 's';
if ($i + 1 < $j) {
// now getting the second item
$seconds2 = $chunks[$i + 1][0];
$name2 = $chunks[$i + 1][1];
// add second item if it's greater than 0
if (($count2 = floor(($since - ($seconds * $count)) / $seconds2)) != 0) {
$print .= ($count2 == 1) ? ', 1 ' . $name2 : ', ' . $count2 . ' ' . $name2 . 's';
}
}
return $message . $print;
}
It was intended to show the difference between a given time and the current time, but I've made slight changes to show the difference between two times instead. You may wish to change the output from a postfix of ' ago' to a prefix of 'Difference: '.

Categories