PHP time elapsed, remove "and" before seconds - php

So, I've got this working code which converts a MySQL date to UNIX Timestamp and subtracts it from the current date() to show a "time elapsed since X"-like timer. (the part which takes the date from database is missing since it's in another script)
<?php
function time_elapsed($secs){
$bit = array(
' year' => $secs / 31556926 % 12,
' week' => $secs / 604800 % 52,
' day' => $secs / 86400 % 7,
' hour' => $secs / 3600 % 24,
' minute' => $secs / 60 % 60,
' second' => $secs % 60
);
foreach($bit as $k => $v){
if($v > 1)$ret[] = $v . $k . 's';
if($v == 1)$ret[] = $v . $k;
}
array_splice($ret, count($ret)-1, 0, 'and');
$ret[] = 'ago.';
return join(' ', $ret);
}
$nowtime = time() + 10; //add 10s to avoid error
$oldtime = strtotime($mysqltime2);
$time_elapsed = time_elapsed($nowtime-$oldtime)."\n";
echo wordwrap($time_elapsed,35,"<br />\n"); //split long line
?>
I managed to fix an error reporting missing array or something if the script was executed at the same time of the MySQL date by adding 10 seconds to the current timestamp.
Another issue I have is that the script shows "and X seconds" even if there aren't minutes/hours/days/etc before it.
E.g.
"and X seconds"
"Y minutes and X seconds"
"Z hours Y minutes and X seconds"
"N days Z hours Y minutes and X seconds"
I want to remove the "and" before seconds ONLY if there's no minutes/hours/etc before it.
Any tip on how to fix this?

You could only splice when needed:
if( count($ret) > 1 ) {
array_splice($ret, count($ret)-1, 0, 'and');
}

Not sure if this will help, but why not do most of the date maths in mysql?
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Here is something I did before to list posts in a comments section of a site, it outputs "post made 2 hours ago" etc
SQL:
UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(made_on) as madeon
PHP (pass madeon from query to here):
function seconds_to_textual_time_ago($seconds)
{
$hour = 60* 60;
$day = 24 * $hour;
$month = 30 * $day;
$year = 365 * $day;
switch(true)
{
case ($seconds < 60) :
$time_ago = "Less than 1 minute ago";
break;
case ($seconds >= 60 && $seconds < $hour):
$minutes = floor($seconds /60);
if ($minutes > 1)
$time_ago = "$minutes minutes ago";
else
$time_ago = "1 minute ago";
break;
case ($seconds >= $hour && $seconds < $day):
$hours = floor($seconds /$hour);
if ($hours > 1)
$time_ago = "$hours hours ago";
else
$time_ago = "1 hour ago";
break;
case ($seconds >= $day && $seconds < $month):
$days = floor($seconds /$day);
if ($days > 1)
$time_ago = "$days days ago";
else
$time_ago = "1 day ago";
break;
case ($seconds >= $month && $seconds < $year):
$months = floor($seconds /$month);
if ($months > 1)
$time_ago = "$months months ago";
else
$time_ago = "1 month ago";
break;
case ($seconds >= $year ):
$years = floor($seconds /$year);
if ($years > 1)
$time_ago = "$years years ago";
else
$time_ago = "1 year ago";
break;
default:
break;
}
return $time_ago;
}

The simplest I can think of is
$time_elapsed = time_elapsed($nowtime-$oldtime))."\n";
if($nowtime-$oldtime < 61){
$time_elapsed=str_replace('and ',' ',$time_elapsed);
}

Related

PHP negative time calculation

If I add 1 hour and 35 minutes in PHP and subtract 4 hours, I get a remaining time of -3 hours and 30 minutes.
But correct would be -2 hours and 30 minutes. Where’s the mistake?
$minutes = null;
while ($z = $stmt->fetch()) {
$minutes += $z['minutes'];
}
if ($stmt = $pdo->prepare($sql)) {
$stmt->execute(array(
':user' => $user
));
$negativeTime = null;
while ($z = $stmt->fetch()) {
$negativeTime += $z['minutes'];
}
}
$minutes = $minutes - $negativeTime;
echo (floor($minutes / 60)) . " hours and " . ($minutes - floor($minutes / 60) * 60) . " minutes";
$minutes - floor($minutes/60) is positive. So what you're getting is -3 hours plus 30 minutes, which is -2:30.
You need to treat positive and negative values of $minutes differently, so that both the hours and minutes are the distance from zero. Use the abs() function to convert the time to positive, perform the calculation, then show the hours as negative if the original value of $minutes was negative.
$sign = $minutes < 0 ? '-' : '';
$minutes = abs($minutes);
$hours = floor($minutes / 60);
$minutes = $minutes % 60;
echo "$sign$hours hours and $minutes minutes";
DEMO

PHP timestamp hours to days

I have a timestamp which I need to return as:
When it's under 1 hour I need it to say "30 minutes ago".
When it's under 24 hours I need it to say "6 hours ago".
When it gets to 24 hours I need it to say "1 day ago".
When it gets to 48 hours I need it to say "2 days ago".
Would this be done with a conditional statement?
So far I can return the number of days:
$post_timestamp = strtotime($post_timestamp);
$current_date = strtotime(time());
$datediff = $current_date - $post_timestamp;
$days = floor($datediff/(60*60*24));
I guess you can use DateTime, DateInterval and DatePeriod:
$date1 = new DateTime();
$date2 = DateTime::createFromFormat('U', $post_timestamp); # I assume a unix timestamp here
//determine what interval should be used - 1 minute
$interval = new \DateInterval('PT1M');
//create periods every minute between the two dates
$periods = new \DatePeriod($date2, $interval, $date1);
//count the number of objects within the periods
$mins = iterator_count($periods);
if ($mins < 60)
{
$say = "30 minutes ago";
} elseif ( $mins >= 60 and $mins < 60 * 24)
{
$say = "6 hours ago";
} elseif ( $mins >= 60 * 24 and $mins < 60 * 48)
{
$say = "1 day ago";
} elseif ( $mins >= 60 * 48)
{
$say = "2 days ago";
}
print $say;
You can use code like following :
date_default_timezone_set('Asia/Calcutta');
$post_timestamp="2017-05-21 5:00 pm";
$post_timestamp = strtotime($post_timestamp);
$current_date = strtotime(date('Y-m-d h:i a'));
$datediff = $current_date - $post_timestamp;
$mins = ($datediff) / 60;
$hours = $datediff / ( 60 * 60 );
You will get minutes and hours using this, put your condition accordingly

User friendly date formatting [duplicate]

This question already has answers here:
Converting timestamp to time ago in PHP e.g 1 day ago, 2 days ago...
(32 answers)
Closed 9 years ago.
I am trying to display user friendly date formatting such as "1 hour and 15 minutes", "4 days and 8 hours" to the user. However my script is displaying 0 hours as 23 for some reason.
$date = '2014-01-15 15:00' # PAST DATE
$now = Date("Y-m-d H:m:s");
$seconds = strtotime($now) - strtotime($date);
$days = floor($seconds / 86400);
$hours = floor(($seconds - ($days * 86400)) / 3600);
$minutes = floor(($seconds - ($days * 86400) - ($hours * 3600))/60);
$seconds = floor(($seconds - ($days * 86400) - ($hours * 3600) - ($minutes*60)));
if($days > 0)
{
if($days == 1)
{
return $days . ' dag ' . $hours . ' timmar';
} else {
return $days . ' dagar ' . $hours . ' timmar';
}
}
if(($hours < 24) AND ($hours > 0))
{
return $hours . ' timmar';
}
if($minutes < 60)
{
return $minutes . ' minuter';
}
Can anyone see what is causing this? Am I doing it the correct way? Note that $date is user supplied in the past.
There are much easier ways to do this:
$past = new DateTime('2014-01-15 15:00');
$now = new DateTime();
$interval = $now->diff($past);
echo $interval->format('%y years, %m months, %d days,
%h hours, %i minutes, %S seconds');
An obvious improvement is to use now show periods of time that have zero values (i.e. 0 days):
$elapsed = $interval->format('%y years, %m months, %d days,
%h hours, %i minutes');
$elapsed = str_replace(array('0 years,', ' 0 months,', ' 0 days,',
' 0 hours,', ' 0 minutes,'), '', $elapsed);
$elapsed = str_replace(array('1 years, ', ' 1 months, ', ' 1 days, ',
' 1 hours, ', ' 1 minutes'), array('1 year, ',
'1 month, ', ' 1 day, ', ' 1 hour, ', ' 1 minute'),
$elapsed);
Use something like this:
$date = '2014-01-15 15:00' # PAST DATE
now = Date("Y-m-d H:m:s");
$t = strtotime($now) - strtotime($date);
$time = date('g:iA M dS', $t );
$diff = time() - $t;
if ( $diff < 60 )
{
return "a few seconds ago";
}
elseif ( $diff < 3600 )
{
return "about ".( int ) ($diff/60) ." mins ago";
}
elseif ( $diff < 86400 )
{
if ( ( int ) ($diff/3600) == 1 )
{
return "about an hour ago";
}
else
{
return "about ".( int ) ($diff/3600) ." hours ago";
}
}
else if( $diff < 172800 )
{
return "about a day ago";
}
elseif ( $diff > 172800 )
{
return "$time";
}

PHP time conversion

Is there a PHP library that will convert a unix timestamp into something like this format:
8 hours and 17 minutes ago
I made my own script a while back that did this, I just can't track it down and would rather not spend the time recreating it (plus I think it could have been done far more efficiently).
My original code was something along the lines of:
$seconds = time() - $timestamp;
$minutes = 0;
$hours = 0;
$days = 0;
$weeks = 0;
$months = 0;
$years = 0;
while($seconds >= 60)
{
$seconds -= 60;
$minutes ++;
if($minutes >= 60)
{
$minutes -= 60;
$hours ++;
if($hours >= 24)
{
// etc
}
}
}
if($hours < 1) return "$minutes minute" . ($minutes == 1 ? "" : "s")) . " and $seconds seconds" . ($seconds == 1 ? "" : "s"));
if($minutes < 1) return "$seconds second" . ($seconds == 1 ? "" : "s"));
// etc
Better yet, if there's a nicer way to approach the above I'll give it a crack myself as well.
Yes, check The DateTime class.
$datetime1= new DateTime();
$datetime2= new DateTime();
$datetime2->setTimestamp($timestamp);
$interval = $datetime2->diff($datetime1);
echo $interval->format('%a days %h hours and %i minutes ago');
function TimeAgo($datefrom,$dateto=-1)
{
// Defaults and assume if 0 is passed in that
// its an error rather than the epoch
if($datefrom<=0) { return "A long time ago"; }
if($dateto==-1) { $dateto = time(); }
// Calculate the difference in seconds betweeen
// the two timestamps
$difference = $dateto - $datefrom;
// If difference is less than 60 seconds,
// seconds is a good interval of choice
if($difference < 60)
{
$interval = "s";
}
// If difference is between 60 seconds and
// 60 minutes, minutes is a good interval
elseif($difference >= 60 && $difference<60*60)
{
$interval = "n";
}
// If difference is between 1 hour and 24 hours
// hours is a good interval
elseif($difference >= 60*60 && $difference<60*60*24)
{
$interval = "h";
}
// If difference is between 1 day and 7 days
// days is a good interval
elseif($difference >= 60*60*24 && $difference<60*60*24*7)
{
$interval = "d";
}
// If difference is between 1 week and 30 days
// weeks is a good interval
elseif($difference >= 60*60*24*7 && $difference <
60*60*24*30)
{
$interval = "ww";
}
// If difference is between 30 days and 365 days
// months is a good interval, again, the same thing
// applies, if the 29th February happens to exist
// between your 2 dates, the function will return
// the 'incorrect' value for a day
elseif($difference >= 60*60*24*30 && $difference <
60*60*24*365)
{
$interval = "m";
}
// If difference is greater than or equal to 365
// days, return year. This will be incorrect if
// for example, you call the function on the 28th April
// 2008 passing in 29th April 2007. It will return
// 1 year ago when in actual fact (yawn!) not quite
// a year has gone by
elseif($difference >= 60*60*24*365)
{
$interval = "y";
}
// Based on the interval, determine the
// number of units between the two dates
// From this point on, you would be hard
// pushed telling the difference between
// this function and DateDiff. If the $datediff
// returned is 1, be sure to return the singular
// of the unit, e.g. 'day' rather 'days'
switch($interval)
{
case "m":
$months_difference = floor($difference / 60 / 60 / 24 /
29);
while (mktime(date("H", $datefrom), date("i", $datefrom),
date("s", $datefrom), date("n", $datefrom)+($months_difference),
date("j", $dateto), date("Y", $datefrom)) < $dateto)
{
$months_difference++;
}
$datediff = $months_difference;
// We need this in here because it is possible
// to have an 'm' interval and a months
// difference of 12 because we are using 29 days
// in a month
if($datediff==12)
{
$datediff--;
}
$res = ($datediff==1) ? "$datediff month ago" : "$datediff
months ago";
break;
case "y":
$datediff = floor($difference / 60 / 60 / 24 / 365);
$res = ($datediff==1) ? "$datediff year ago" : "$datediff
years ago";
break;
case "d":
$datediff = floor($difference / 60 / 60 / 24);
$res = ($datediff==1) ? "$datediff day ago" : "$datediff
days ago";
break;
case "ww":
$datediff = floor($difference / 60 / 60 / 24 / 7);
$res = ($datediff==1) ? "$datediff week ago" : "$datediff
weeks ago";
break;
case "h":
$datediff = floor($difference / 60 / 60);
$res = ($datediff==1) ? "$datediff hour ago" : "$datediff
hours ago";
break;
case "n":
$datediff = floor($difference / 60);
$res = ($datediff==1) ? "$datediff minute ago" :
"$datediff minutes ago";
break;
case "s":
$datediff = $difference;
$res = ($datediff==1) ? "$datediff second ago" :
"$datediff seconds ago";
break;
}
return $res;
}
/*
Input parameter is the UNIX timestamp
of the starting date.
The second parameter is optional -
It's value is the ending date,
also UNIX timestamp. If this
parameter is not given, the
default date is current date.
*/
function duration($start,$end=null) {
$end = is_null($end) ? time() : $end;
$seconds = $end - $start;
$days = floor($seconds/60/60/24);
$hours = $seconds/60/60%24;
$mins = $seconds/60%60;
$secs = $seconds%60;
$duration='';
if($days>0) $duration .= "$days days ";
if($hours>0) $duration .= "$hours hours ";
if($mins>0) $duration .= "$mins minutes ";
if($secs>0) $duration .= "$secs seconds ";
//$duration = trim($duration);
if($duration=='') $duration = '0 seconds';
return $duration;
}
It it not suits you better use some classes, given below
http://www.phpclasses.org/browse/file/6330.html

Use PHP to truncate the age of a MySQL entry to the nearest unit of time

I have a table with a datetime field, and I want to pull that time stamp and use PHP to convert it to the nearest largest unit of time. For example, if the entry was made 2 minutes and 36 seconds ago, I want to echo 2 minutes in PHP. If it was 3 hours and 5 minutes ago, I want it to say 3 hours. If it was 6 days and 4 hours and 40 minutes ago, it should say 6 days. You get my drift. And if it's under a minute, just the number of seconds.
I am not familiar at all about any of PHP's date or time functions, so please don't assume I already know anything. Thanks.
Here's another function for you:
function relativeTime($timestamp, $format = "Y-m-d")
{
$difference = time() - $timestamp;
if ($difference >= 604800) { // 7 days
return date($format, $timestamp);
}
$periods = array("Second", "Minute", "Hour", "Day");
$lengths = array("60","60","24","7","4.35","12","10");
$ending = "Ago";
for($j = 0; $difference >= $lengths[$j]; $j++)
$difference /= $lengths[$j];
$difference = round($difference);
if($difference != 1) $periods[$j].= "s";
$text = "$difference $periods[$j] $ending";
return $text;
}
It returns values like "5 Minutes Ago", "3 Days Ago", and "34 Seconds Ago". However if the date is over 7 days old, it just returns the full date, i.e. "2010-04-19".
If your field is date or datetime use
SELECT UNIX_TIMESTAMP(field) FROM...
if your field is stored as an int (seconds since 1970) just use
SELECT field FROM...
Get that integer value from the database into a PHP variable $secs, this is the number of seconds since 1970. We assume the date is in the past, then
$diff = time() - $secs;
if ($diff < 60) echo $diff . ' seconds';
else {
$diff = intval($diff / 60);
if ($diff < 60) echo $diff . ' minutes';
else {
$diff = intval($diff / 60);
if ($diff < 24) echo $diff . ' hours';
else {
$diff = intval($diff / 24);
echo $diff . ' days';
}
}
}

Categories