Related
I would like to convert a variable $uptime which is seconds, into days, hours, minutes and seconds.
Example:
$uptime = 1640467;
Result should be:
18 days 23 hours 41 minutes
This can be achieved with DateTime class
Function:
function secondsToTime($seconds) {
$dtF = new \DateTime('#0');
$dtT = new \DateTime("#$seconds");
return $dtF->diff($dtT)->format('%a days, %h hours, %i minutes and %s seconds');
}
Use:
echo secondsToTime(1640467);
# 18 days, 23 hours, 41 minutes and 7 seconds
demo
This is the function rewritten to include days. I also changed the variable names to make the code easier to understand...
/**
* Convert number of seconds into hours, minutes and seconds
* and return an array containing those values
*
* #param integer $inputSeconds Number of seconds to parse
* #return array
*/
function secondsToTime($inputSeconds) {
$secondsInAMinute = 60;
$secondsInAnHour = 60 * $secondsInAMinute;
$secondsInADay = 24 * $secondsInAnHour;
// extract days
$days = floor($inputSeconds / $secondsInADay);
// extract hours
$hourSeconds = $inputSeconds % $secondsInADay;
$hours = floor($hourSeconds / $secondsInAnHour);
// extract minutes
$minuteSeconds = $hourSeconds % $secondsInAnHour;
$minutes = floor($minuteSeconds / $secondsInAMinute);
// extract the remaining seconds
$remainingSeconds = $minuteSeconds % $secondsInAMinute;
$seconds = ceil($remainingSeconds);
// return the final array
$obj = array(
'd' => (int) $days,
'h' => (int) $hours,
'm' => (int) $minutes,
's' => (int) $seconds,
);
return $obj;
}
Source: CodeAid() - http://codeaid.net/php/convert-seconds-to-hours-minutes-and-seconds-(php)
Based on the answer by Julian Moreno, but changed to give the response as a string (not an array), only include the time intervals required and not assume the plural.
The difference between this and the highest voted answer is:
For 259264 seconds, this code would give
3 days, 1 minute, 4 seconds
For 259264 seconds, the highest voted answer (by Glavić) would give
3 days, 0 hours, 1 minutes and 4 seconds
function secondsToTime($inputSeconds) {
$secondsInAMinute = 60;
$secondsInAnHour = 60 * $secondsInAMinute;
$secondsInADay = 24 * $secondsInAnHour;
// Extract days
$days = floor($inputSeconds / $secondsInADay);
// Extract hours
$hourSeconds = $inputSeconds % $secondsInADay;
$hours = floor($hourSeconds / $secondsInAnHour);
// Extract minutes
$minuteSeconds = $hourSeconds % $secondsInAnHour;
$minutes = floor($minuteSeconds / $secondsInAMinute);
// Extract the remaining seconds
$remainingSeconds = $minuteSeconds % $secondsInAMinute;
$seconds = ceil($remainingSeconds);
// Format and return
$timeParts = [];
$sections = [
'day' => (int)$days,
'hour' => (int)$hours,
'minute' => (int)$minutes,
'second' => (int)$seconds,
];
foreach ($sections as $name => $value){
if ($value > 0){
$timeParts[] = $value. ' '.$name.($value == 1 ? '' : 's');
}
}
return implode(', ', $timeParts);
}
I hope this helps someone.
Here it is a simple 8-lines PHP function that converts a number of seconds into a human readable string including number of months for large amounts of seconds:
PHP function seconds2human()
function seconds2human($ss) {
$s = $ss%60;
$m = floor(($ss%3600)/60);
$h = floor(($ss%86400)/3600);
$d = floor(($ss%2592000)/86400);
$M = floor($ss/2592000);
return "$M months, $d days, $h hours, $m minutes, $s seconds";
}
gmdate("d H:i:s",1640467);
Result will be 19 23:41:07. Even if the time is an extra 1 second, it causes the day to change. So it turns out 19. You can explode the result for your needs and fix this.
There are some very good answers here but none of them covered my needs. I built on Glavic's answer to add some extra features that I needed;
Don't print zeros. So "5 minutes" instead of " 0 hours, 5 minutes"
Handle plural properly instead of defaulting to the plural form.
Limit the output to a set number of units; So "2 months, 2 days" instead of "2 months, 2 days, 1 hour, 45 minutes"
You can see a running version of the code here.
function secondsToHumanReadable(int $seconds, int $requiredParts = null)
{
$from = new \DateTime('#0');
$to = new \DateTime("#$seconds");
$interval = $from->diff($to);
$str = '';
$parts = [
'y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
];
$includedParts = 0;
foreach ($parts as $key => $text) {
if ($requiredParts && $includedParts >= $requiredParts) {
break;
}
$currentPart = $interval->{$key};
if (empty($currentPart)) {
continue;
}
if (!empty($str)) {
$str .= ', ';
}
$str .= sprintf('%d %s', $currentPart, $text);
if ($currentPart > 1) {
// handle plural
$str .= 's';
}
$includedParts++;
}
return $str;
}
Short, simple, reliable :
function secondsToDHMS($seconds) {
$s = (int)$seconds;
return sprintf('%d:%02d:%02d:%02d', $s/86400, $s/3600%24, $s/60%60, $s%60);
}
Laravel example
700+ locales support by Carbon
\Carbon\CarbonInterval::seconds(1640467)->cascade()->forHumans(); //2 weeks 4 days 23 hours 41 minutes 7 seconds
The simplest approach would be to create a method that returns a DateInterval from the DateTime::diff of the relative time in $seconds from the current time $now which you can then chain and format. For example:-
public function toDateInterval($seconds) {
return date_create('#' . (($now = time()) + $seconds))->diff(date_create('#' . $now));
}
Now chain your method call to DateInterval::format
echo $this->toDateInterval(1640467)->format('%a days %h hours %i minutes'));
Result:
18 days 23 hours 41 minutes
function convert($seconds){
$string = "";
$days = intval(intval($seconds) / (3600*24));
$hours = (intval($seconds) / 3600) % 24;
$minutes = (intval($seconds) / 60) % 60;
$seconds = (intval($seconds)) % 60;
if($days> 0){
$string .= "$days days ";
}
if($hours > 0){
$string .= "$hours hours ";
}
if($minutes > 0){
$string .= "$minutes minutes ";
}
if ($seconds > 0){
$string .= "$seconds seconds";
}
return $string;
}
echo convert(3744000);
Although it is quite old question - one may find these useful (not written to be fast):
function d_h_m_s__string1($seconds)
{
$ret = '';
$divs = array(86400, 3600, 60, 1);
for ($d = 0; $d < 4; $d++)
{
$q = (int)($seconds / $divs[$d]);
$r = $seconds % $divs[$d];
$ret .= sprintf("%d%s", $q, substr('dhms', $d, 1));
$seconds = $r;
}
return $ret;
}
function d_h_m_s__string2($seconds)
{
if ($seconds == 0) return '0s';
$can_print = false; // to skip 0d, 0d0m ....
$ret = '';
$divs = array(86400, 3600, 60, 1);
for ($d = 0; $d < 4; $d++)
{
$q = (int)($seconds / $divs[$d]);
$r = $seconds % $divs[$d];
if ($q != 0) $can_print = true;
if ($can_print) $ret .= sprintf("%d%s", $q, substr('dhms', $d, 1));
$seconds = $r;
}
return $ret;
}
function d_h_m_s__array($seconds)
{
$ret = array();
$divs = array(86400, 3600, 60, 1);
for ($d = 0; $d < 4; $d++)
{
$q = $seconds / $divs[$d];
$r = $seconds % $divs[$d];
$ret[substr('dhms', $d, 1)] = $q;
$seconds = $r;
}
return $ret;
}
echo d_h_m_s__string1(0*86400+21*3600+57*60+13) . "\n";
echo d_h_m_s__string2(0*86400+21*3600+57*60+13) . "\n";
$ret = d_h_m_s__array(9*86400+21*3600+57*60+13);
printf("%dd%dh%dm%ds\n", $ret['d'], $ret['h'], $ret['m'], $ret['s']);
result:
0d21h57m13s
21h57m13s
9d21h57m13s
function seconds_to_time($seconds){
// extract hours
$hours = floor($seconds / (60 * 60));
// extract minutes
$divisor_for_minutes = $seconds % (60 * 60);
$minutes = floor($divisor_for_minutes / 60);
// extract the remaining seconds
$divisor_for_seconds = $divisor_for_minutes % 60;
$seconds = ceil($divisor_for_seconds);
//create string HH:MM:SS
$ret = $hours.":".$minutes.":".$seconds;
return($ret);
}
Solution that should exclude 0 values and set correct singular/plural values
use DateInterval;
use DateTime;
class TimeIntervalFormatter
{
public static function fromSeconds($seconds)
{
$seconds = (int)$seconds;
$dateTime = new DateTime();
$dateTime->sub(new DateInterval("PT{$seconds}S"));
$interval = (new DateTime())->diff($dateTime);
$pieces = explode(' ', $interval->format('%y %m %d %h %i %s'));
$intervals = ['year', 'month', 'day', 'hour', 'minute', 'second'];
$result = [];
foreach ($pieces as $i => $value) {
if (!$value) {
continue;
}
$periodName = $intervals[$i];
if ($value > 1) {
$periodName .= 's';
}
$result[] = "{$value} {$periodName}";
}
return implode(', ', $result);
}
}
I don't know why some of these answers are ridiculously long or complex. Here's one using the DateTime Class. Kind of similar to radzserg's answer. This will only display the units necessary, and negative times will have the 'ago' suffix...
function calctime($seconds = 0) {
$datetime1 = date_create("#0");
$datetime2 = date_create("#$seconds");
$interval = date_diff($datetime1, $datetime2);
if ( $interval->y >= 1 ) $thetime[] = pluralize( $interval->y, 'year' );
if ( $interval->m >= 1 ) $thetime[] = pluralize( $interval->m, 'month' );
if ( $interval->d >= 1 ) $thetime[] = pluralize( $interval->d, 'day' );
if ( $interval->h >= 1 ) $thetime[] = pluralize( $interval->h, 'hour' );
if ( $interval->i >= 1 ) $thetime[] = pluralize( $interval->i, 'minute' );
if ( $interval->s >= 1 ) $thetime[] = pluralize( $interval->s, 'second' );
return isset($thetime) ? implode(' ', $thetime) . ($interval->invert ? ' ago' : '') : NULL;
}
function pluralize($count, $text) {
return $count . ($count == 1 ? " $text" : " ${text}s");
}
// Examples:
// -86400 = 1 day ago
// 12345 = 3 hours 25 minutes 45 seconds
// 987654321 = 31 years 3 months 18 days 4 hours 25 minutes 21 seconds
EDIT: If you want to condense the above example down to use less variables / space (at the expense of legibility), here is an alternate version that does the same thing:
function calctime($seconds = 0) {
$interval = date_diff(date_create("#0"),date_create("#$seconds"));
foreach (array('y'=>'year','m'=>'month','d'=>'day','h'=>'hour','i'=>'minute','s'=>'second') as $format=>$desc) {
if ($interval->$format >= 1) $thetime[] = $interval->$format . ($interval->$format == 1 ? " $desc" : " {$desc}s");
}
return isset($thetime) ? implode(' ', $thetime) . ($interval->invert ? ' ago' : '') : NULL;
}
an extended version of Glavić's excellent solution , having integer validation, solving the 1 s problem, and additional support for years and months, at the expense of being less computer parsing friendly in favor of being more human friendly:
<?php
function secondsToHumanReadable(/*int*/ $seconds)/*: string*/ {
//if you dont need php5 support, just remove the is_int check and make the input argument type int.
if(!\is_int($seconds)){
throw new \InvalidArgumentException('Argument 1 passed to secondsToHumanReadable() must be of the type int, '.\gettype($seconds).' given');
}
$dtF = new \DateTime ( '#0' );
$dtT = new \DateTime ( "#$seconds" );
$ret = '';
if ($seconds === 0) {
// special case
return '0 seconds';
}
$diff = $dtF->diff ( $dtT );
foreach ( array (
'y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second'
) as $time => $timename ) {
if ($diff->$time !== 0) {
$ret .= $diff->$time . ' ' . $timename;
if ($diff->$time !== 1 && $diff->$time !== -1 ) {
$ret .= 's';
}
$ret .= ' ';
}
}
return substr ( $ret, 0, - 1 );
}
var_dump(secondsToHumanReadable(1*60*60*2+1)); -> string(16) "2 hours 1 second"
function secondsToTime($seconds) {
$time = [];
$minutes = $seconds / 60;
$seconds = $seconds % 60;
$hours = $minutes / 60;
$minutes = $minutes % 60;
$days = $hours / 24;
$hours = $hours % 24;
$month = $days /30;
$days = $days % 30;
$year = $month / 12;
$month = $month % 12;
if ((int)($year) != 0){
array_push($time,[ "year" => (int)($year)]);
}
if ($month != 0){
array_push($time, ["months" => $month]);
}
if ($days != 0){
array_push($time,["days" => $days]);
}
if ($hours != 0){
array_push($time,["hours" => $hours]);
}
if ($minutes != 0){
array_push($time,["minutes" => $minutes]);
}
if ($seconds != 0){
array_push($time,["seconds" => $seconds]);
}
return $time;
}
I think Carbon will give you all variety that you want
so for your example you will add this code
$seconds = 1640467;
$time = Carbon::now();
$humanTime = $time->diffForHumans($time->copy()->addSeconds($seconds), true, false, 4);
the output will be like this
2 weeks 4 days 23 hours 41 minutes
Interval class I have written can be used. It can be used in opposite way too.
composer require lubos/cakephp-interval
$Interval = new \Interval\Interval\Interval();
// output 2w 6h
echo $Interval->toHuman((2 * 5 * 8 + 6) * 3600);
// output 36000
echo $Interval->toSeconds('1d 2h');
More info here https://github.com/LubosRemplik/CakePHP-Interval
With DateInterval :
$d1 = new DateTime();
$d2 = new DateTime();
$d2->add(new DateInterval('PT'.$timespan.'S'));
$interval = $d2->diff($d1);
echo $interval->format('%a days, %h hours, %i minutes and %s seconds');
// Or
echo sprintf('%d days, %d hours, %d minutes and %d seconds',
$interval->days,
$interval->h,
$interval->i,
$interval->s
);
// $interval->y => years
// $interval->m => months
// $interval->d => days
// $interval->h => hours
// $interval->i => minutes
// $interval->s => seconds
// $interval->days => total number of days
A bit more elaborated, skipping the time units which are zero
function secondsToTime($ss)
{
$htmlOut="";
$s = $ss%60;
$m = floor(($ss%3600)/60);
$h = floor(($ss%86400)/3600);
$d = floor(($ss%2592000)/86400);
$M = floor($ss/2592000);
if ( $M > 0 )
{
$htmlOut.="$M months";
}
if ( $d > 0 )
{
if ( $M > 0 )
$htmlOut.=", ";
$htmlOut.="$d days";
}
if ( $h > 0 )
{
if ( $d > 0 )
$htmlOut.=", ";
$htmlOut.="$h hours";
}
if ( $m > 0 )
{
if ( $h > 0 )
$htmlOut.=", ";
$htmlOut.="$m minutes";
}
if ( $s > 0 )
{
if ( $m > 0 )
$htmlOut.=" and ";
$htmlOut.="$s seconds";
}
return $htmlOut;
}
All in one solution. Gives no units with zeroes. Will only produce number of units you specify (3 by default).
Quite long, perhaps not very elegant. Defines are optional, but might come in handy in a big project.
define('OneMonth', 2592000);
define('OneWeek', 604800);
define('OneDay', 86400);
define('OneHour', 3600);
define('OneMinute', 60);
function SecondsToTime($seconds, $num_units=3) {
$time_descr = array(
"months" => floor($seconds / OneMonth),
"weeks" => floor(($seconds%OneMonth) / OneWeek),
"days" => floor(($seconds%OneWeek) / OneDay),
"hours" => floor(($seconds%OneDay) / OneHour),
"mins" => floor(($seconds%OneHour) / OneMinute),
"secs" => floor($seconds%OneMinute),
);
$res = "";
$counter = 0;
foreach ($time_descr as $k => $v) {
if ($v) {
$res.=$v." ".$k;
$counter++;
if($counter>=$num_units)
break;
elseif($counter)
$res.=", ";
}
}
return $res;
}
Here's some code that I like to use for the purpose of getting the duration between two dates. It accepts two dates and gives you a nice sentence structured reply.
This is a slightly modified version of the code found here.
<?php
function dateDiff($time1, $time2, $precision = 6, $offset = false) {
// If not numeric then convert texts to unix timestamps
if (!is_int($time1)) {
$time1 = strtotime($time1);
}
if (!is_int($time2)) {
if (!$offset) {
$time2 = strtotime($time2);
}
else {
$time2 = strtotime($time2) - $offset;
}
}
// If time1 is bigger than time2
// Then swap time1 and time2
if ($time1 > $time2) {
$ttime = $time1;
$time1 = $time2;
$time2 = $ttime;
}
// Set up intervals and diffs arrays
$intervals = array(
'year',
'month',
'day',
'hour',
'minute',
'second'
);
$diffs = array();
// Loop thru all intervals
foreach($intervals as $interval) {
// Create temp time from time1 and interval
$ttime = strtotime('+1 ' . $interval, $time1);
// Set initial values
$add = 1;
$looped = 0;
// Loop until temp time is smaller than time2
while ($time2 >= $ttime) {
// Create new temp time from time1 and interval
$add++;
$ttime = strtotime("+" . $add . " " . $interval, $time1);
$looped++;
}
$time1 = strtotime("+" . $looped . " " . $interval, $time1);
$diffs[$interval] = $looped;
}
$count = 0;
$times = array();
// Loop thru all diffs
foreach($diffs as $interval => $value) {
// Break if we have needed precission
if ($count >= $precision) {
break;
}
// Add value and interval
// if value is bigger than 0
if ($value > 0) {
// Add s if value is not 1
if ($value != 1) {
$interval.= "s";
}
// Add value and interval to times array
$times[] = $value . " " . $interval;
$count++;
}
}
if (!empty($times)) {
// Return string with times
return implode(", ", $times);
}
else {
// Return 0 Seconds
}
return '0 Seconds';
}
Source: https://gist.github.com/ozh/8169202
The solution for this one I used (back to the days while learning PHP) without any in-functions:
$days = (int)($uptime/86400); //1day = 86400seconds
$rdays = (uptime-($days*86400));
//seconds remaining after uptime was converted into days
$hours = (int)($rdays/3600);//1hour = 3600seconds,converting remaining seconds into hours
$rhours = ($rdays-($hours*3600));
//seconds remaining after $rdays was converted into hours
$minutes = (int)($rhours/60); // 1minute = 60seconds, converting remaining seconds into minutes
echo "$days:$hours:$minutes";
Though this was an old question, new learners who come across this, may find this answer useful.
a=int(input("Enter your number by seconds "))
d=a//(24*3600) #Days
h=a//(60*60)%24 #hours
m=a//60%60 #minutes
s=a%60 #seconds
print("Days ",d,"hours ",h,"minutes ",m,"seconds ",s)
I am editing one of the code to work it well when negative value comes. floor() function is not giving the correct count when the value is negative. So we need to use abs() function before using it in the floor() function.
$inputSeconds variable can be the difference between the current time stamp and the required date.
/**
* Convert number of seconds into hours, minutes and seconds
* and return an array containing those values
*
* #param integer $inputSeconds Number of seconds to parse
* #return array
*/
function secondsToTime($inputSeconds) {
$secondsInAMinute = 60;
$secondsInAnHour = 60 * $secondsInAMinute;
$secondsInADay = 24 * $secondsInAnHour;
// extract days
$days = abs($inputSeconds / $secondsInADay);
$days = floor($days);
// extract hours
$hourSeconds = $inputSeconds % $secondsInADay;
$hours = abs($hourSeconds / $secondsInAnHour);
$hours = floor($hours);
// extract minutes
$minuteSeconds = $hourSeconds % $secondsInAnHour;
$minutes = abs($minuteSeconds / $secondsInAMinute);
$minutes = floor($minutes);
// extract the remaining seconds
$remainingSeconds = $minuteSeconds % $secondsInAMinute;
$seconds = abs($remainingSeconds);
$seconds = ceil($remainingSeconds);
// return the final array
$obj = array(
'd' => (int) $days,
'h' => (int) $hours,
'm' => (int) $minutes,
's' => (int) $seconds,
);
return $obj;
}
A variation on #Glavić's answer - this one hides leading zeros for shorter results and uses plurals in correct places. It also removes unnecessary precision (e.g. if the time difference is over 2 hours, you probably don't care how many minutes or seconds).
function secondsToTime($seconds)
{
$dtF = new \DateTime('#0');
$dtT = new \DateTime("#$seconds");
$dateInterval = $dtF->diff($dtT);
$days_t = 'day';
$hours_t = 'hour';
$minutes_t = 'minute';
$seconds_t = 'second';
if ((int)$dateInterval->d > 1) {
$days_t = 'days';
}
if ((int)$dateInterval->h > 1) {
$hours_t = 'hours';
}
if ((int)$dateInterval->i > 1) {
$minutes_t = 'minutes';
}
if ((int)$dateInterval->s > 1) {
$seconds_t = 'seconds';
}
if ((int)$dateInterval->d > 0) {
if ((int)$dateInterval->d > 1 || (int)$dateInterval->h === 0) {
return $dateInterval->format("%a $days_t");
} else {
return $dateInterval->format("%a $days_t, %h $hours_t");
}
} else if ((int)$dateInterval->h > 0) {
if ((int)$dateInterval->h > 1 || (int)$dateInterval->i === 0) {
return $dateInterval->format("%h $hours_t");
} else {
return $dateInterval->format("%h $hours_t, %i $minutes_t");
}
} else if ((int)$dateInterval->i > 0) {
if ((int)$dateInterval->i > 1 || (int)$dateInterval->s === 0) {
return $dateInterval->format("%i $minutes_t");
} else {
return $dateInterval->format("%i $minutes_t, %s $seconds_t");
}
} else {
return $dateInterval->format("%s $seconds_t");
}
}
php > echo secondsToTime(60);
1 minute
php > echo secondsToTime(61);
1 minute, 1 second
php > echo secondsToTime(120);
2 minutes
php > echo secondsToTime(121);
2 minutes
php > echo secondsToTime(2000);
33 minutes
php > echo secondsToTime(4000);
1 hour, 6 minutes
php > echo secondsToTime(4001);
1 hour, 6 minutes
php > echo secondsToTime(40001);
11 hours
php > echo secondsToTime(400000);
4 days
Added some formatting modified from Glavić's great answer for Facebook style time of post count up....
function secondsToTime($seconds) {
$dtF = new \DateTime('#0');
$dtT = new \DateTime("#$seconds");
switch($seconds){
case ($seconds<60*60*24): // if time is less than one day
return $dtF->diff($dtT)->format('%h hours, %i minutes, %s seconds');
break;
case ($seconds<60*60*24*31 && $seconds>60*60*24): // if time is between 1 day and 1 month
return $dtF->diff($dtT)->format('%d days, %h hours');
break;
case ($seconds<60*60*24*365 && $seconds>60*60*24*31): // if time between 1 month and 1 year
return $dtF->diff($dtT)->format('%m months, %d days');
break;
case ($seconds>60*60*24*365): // if time is longer than 1 year
return $dtF->diff($dtT)->format('%y years, %m months');
break;
}
foreach ($email as $temp => $value) {
$dat = strtotime($value['subscription_expiration']); //$value come from mysql database
//$email is an array from mysqli_query()
$date = strtotime(date('Y-m-d'));
$_SESSION['expiry'] = (((($dat - $date)/60)/60)/24)." Days Left";
//you will get the difference from current date in days.
}
$value come from Database. This code is in Codeigniter. $SESSION is used for storing user subscriptions. it is mandatory. I used it in my case, you can use whatever you want.
This is a function i used in the past for substracting a date from another one related with your question, my principe was to get how many days, hours minutes and seconds has left until a product has expired :
$expirationDate = strtotime("2015-01-12 20:08:23");
$toDay = strtotime(date('Y-m-d H:i:s'));
$difference = abs($toDay - $expirationDate);
$days = floor($difference / 86400);
$hours = floor(($difference - $days * 86400) / 3600);
$minutes = floor(($difference - $days * 86400 - $hours * 3600) / 60);
$seconds = floor($difference - $days * 86400 - $hours * 3600 - $minutes * 60);
echo "{$days} days {$hours} hours {$minutes} minutes {$seconds} seconds";
I would like to convert a variable $uptime which is seconds, into days, hours, minutes and seconds.
Example:
$uptime = 1640467;
Result should be:
18 days 23 hours 41 minutes
This can be achieved with DateTime class
Function:
function secondsToTime($seconds) {
$dtF = new \DateTime('#0');
$dtT = new \DateTime("#$seconds");
return $dtF->diff($dtT)->format('%a days, %h hours, %i minutes and %s seconds');
}
Use:
echo secondsToTime(1640467);
# 18 days, 23 hours, 41 minutes and 7 seconds
demo
This is the function rewritten to include days. I also changed the variable names to make the code easier to understand...
/**
* Convert number of seconds into hours, minutes and seconds
* and return an array containing those values
*
* #param integer $inputSeconds Number of seconds to parse
* #return array
*/
function secondsToTime($inputSeconds) {
$secondsInAMinute = 60;
$secondsInAnHour = 60 * $secondsInAMinute;
$secondsInADay = 24 * $secondsInAnHour;
// extract days
$days = floor($inputSeconds / $secondsInADay);
// extract hours
$hourSeconds = $inputSeconds % $secondsInADay;
$hours = floor($hourSeconds / $secondsInAnHour);
// extract minutes
$minuteSeconds = $hourSeconds % $secondsInAnHour;
$minutes = floor($minuteSeconds / $secondsInAMinute);
// extract the remaining seconds
$remainingSeconds = $minuteSeconds % $secondsInAMinute;
$seconds = ceil($remainingSeconds);
// return the final array
$obj = array(
'd' => (int) $days,
'h' => (int) $hours,
'm' => (int) $minutes,
's' => (int) $seconds,
);
return $obj;
}
Source: CodeAid() - http://codeaid.net/php/convert-seconds-to-hours-minutes-and-seconds-(php)
Based on the answer by Julian Moreno, but changed to give the response as a string (not an array), only include the time intervals required and not assume the plural.
The difference between this and the highest voted answer is:
For 259264 seconds, this code would give
3 days, 1 minute, 4 seconds
For 259264 seconds, the highest voted answer (by Glavić) would give
3 days, 0 hours, 1 minutes and 4 seconds
function secondsToTime($inputSeconds) {
$secondsInAMinute = 60;
$secondsInAnHour = 60 * $secondsInAMinute;
$secondsInADay = 24 * $secondsInAnHour;
// Extract days
$days = floor($inputSeconds / $secondsInADay);
// Extract hours
$hourSeconds = $inputSeconds % $secondsInADay;
$hours = floor($hourSeconds / $secondsInAnHour);
// Extract minutes
$minuteSeconds = $hourSeconds % $secondsInAnHour;
$minutes = floor($minuteSeconds / $secondsInAMinute);
// Extract the remaining seconds
$remainingSeconds = $minuteSeconds % $secondsInAMinute;
$seconds = ceil($remainingSeconds);
// Format and return
$timeParts = [];
$sections = [
'day' => (int)$days,
'hour' => (int)$hours,
'minute' => (int)$minutes,
'second' => (int)$seconds,
];
foreach ($sections as $name => $value){
if ($value > 0){
$timeParts[] = $value. ' '.$name.($value == 1 ? '' : 's');
}
}
return implode(', ', $timeParts);
}
I hope this helps someone.
Here it is a simple 8-lines PHP function that converts a number of seconds into a human readable string including number of months for large amounts of seconds:
PHP function seconds2human()
function seconds2human($ss) {
$s = $ss%60;
$m = floor(($ss%3600)/60);
$h = floor(($ss%86400)/3600);
$d = floor(($ss%2592000)/86400);
$M = floor($ss/2592000);
return "$M months, $d days, $h hours, $m minutes, $s seconds";
}
gmdate("d H:i:s",1640467);
Result will be 19 23:41:07. Even if the time is an extra 1 second, it causes the day to change. So it turns out 19. You can explode the result for your needs and fix this.
There are some very good answers here but none of them covered my needs. I built on Glavic's answer to add some extra features that I needed;
Don't print zeros. So "5 minutes" instead of " 0 hours, 5 minutes"
Handle plural properly instead of defaulting to the plural form.
Limit the output to a set number of units; So "2 months, 2 days" instead of "2 months, 2 days, 1 hour, 45 minutes"
You can see a running version of the code here.
function secondsToHumanReadable(int $seconds, int $requiredParts = null)
{
$from = new \DateTime('#0');
$to = new \DateTime("#$seconds");
$interval = $from->diff($to);
$str = '';
$parts = [
'y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
];
$includedParts = 0;
foreach ($parts as $key => $text) {
if ($requiredParts && $includedParts >= $requiredParts) {
break;
}
$currentPart = $interval->{$key};
if (empty($currentPart)) {
continue;
}
if (!empty($str)) {
$str .= ', ';
}
$str .= sprintf('%d %s', $currentPart, $text);
if ($currentPart > 1) {
// handle plural
$str .= 's';
}
$includedParts++;
}
return $str;
}
Short, simple, reliable :
function secondsToDHMS($seconds) {
$s = (int)$seconds;
return sprintf('%d:%02d:%02d:%02d', $s/86400, $s/3600%24, $s/60%60, $s%60);
}
Laravel example
700+ locales support by Carbon
\Carbon\CarbonInterval::seconds(1640467)->cascade()->forHumans(); //2 weeks 4 days 23 hours 41 minutes 7 seconds
The simplest approach would be to create a method that returns a DateInterval from the DateTime::diff of the relative time in $seconds from the current time $now which you can then chain and format. For example:-
public function toDateInterval($seconds) {
return date_create('#' . (($now = time()) + $seconds))->diff(date_create('#' . $now));
}
Now chain your method call to DateInterval::format
echo $this->toDateInterval(1640467)->format('%a days %h hours %i minutes'));
Result:
18 days 23 hours 41 minutes
function convert($seconds){
$string = "";
$days = intval(intval($seconds) / (3600*24));
$hours = (intval($seconds) / 3600) % 24;
$minutes = (intval($seconds) / 60) % 60;
$seconds = (intval($seconds)) % 60;
if($days> 0){
$string .= "$days days ";
}
if($hours > 0){
$string .= "$hours hours ";
}
if($minutes > 0){
$string .= "$minutes minutes ";
}
if ($seconds > 0){
$string .= "$seconds seconds";
}
return $string;
}
echo convert(3744000);
Although it is quite old question - one may find these useful (not written to be fast):
function d_h_m_s__string1($seconds)
{
$ret = '';
$divs = array(86400, 3600, 60, 1);
for ($d = 0; $d < 4; $d++)
{
$q = (int)($seconds / $divs[$d]);
$r = $seconds % $divs[$d];
$ret .= sprintf("%d%s", $q, substr('dhms', $d, 1));
$seconds = $r;
}
return $ret;
}
function d_h_m_s__string2($seconds)
{
if ($seconds == 0) return '0s';
$can_print = false; // to skip 0d, 0d0m ....
$ret = '';
$divs = array(86400, 3600, 60, 1);
for ($d = 0; $d < 4; $d++)
{
$q = (int)($seconds / $divs[$d]);
$r = $seconds % $divs[$d];
if ($q != 0) $can_print = true;
if ($can_print) $ret .= sprintf("%d%s", $q, substr('dhms', $d, 1));
$seconds = $r;
}
return $ret;
}
function d_h_m_s__array($seconds)
{
$ret = array();
$divs = array(86400, 3600, 60, 1);
for ($d = 0; $d < 4; $d++)
{
$q = $seconds / $divs[$d];
$r = $seconds % $divs[$d];
$ret[substr('dhms', $d, 1)] = $q;
$seconds = $r;
}
return $ret;
}
echo d_h_m_s__string1(0*86400+21*3600+57*60+13) . "\n";
echo d_h_m_s__string2(0*86400+21*3600+57*60+13) . "\n";
$ret = d_h_m_s__array(9*86400+21*3600+57*60+13);
printf("%dd%dh%dm%ds\n", $ret['d'], $ret['h'], $ret['m'], $ret['s']);
result:
0d21h57m13s
21h57m13s
9d21h57m13s
function seconds_to_time($seconds){
// extract hours
$hours = floor($seconds / (60 * 60));
// extract minutes
$divisor_for_minutes = $seconds % (60 * 60);
$minutes = floor($divisor_for_minutes / 60);
// extract the remaining seconds
$divisor_for_seconds = $divisor_for_minutes % 60;
$seconds = ceil($divisor_for_seconds);
//create string HH:MM:SS
$ret = $hours.":".$minutes.":".$seconds;
return($ret);
}
Solution that should exclude 0 values and set correct singular/plural values
use DateInterval;
use DateTime;
class TimeIntervalFormatter
{
public static function fromSeconds($seconds)
{
$seconds = (int)$seconds;
$dateTime = new DateTime();
$dateTime->sub(new DateInterval("PT{$seconds}S"));
$interval = (new DateTime())->diff($dateTime);
$pieces = explode(' ', $interval->format('%y %m %d %h %i %s'));
$intervals = ['year', 'month', 'day', 'hour', 'minute', 'second'];
$result = [];
foreach ($pieces as $i => $value) {
if (!$value) {
continue;
}
$periodName = $intervals[$i];
if ($value > 1) {
$periodName .= 's';
}
$result[] = "{$value} {$periodName}";
}
return implode(', ', $result);
}
}
I don't know why some of these answers are ridiculously long or complex. Here's one using the DateTime Class. Kind of similar to radzserg's answer. This will only display the units necessary, and negative times will have the 'ago' suffix...
function calctime($seconds = 0) {
$datetime1 = date_create("#0");
$datetime2 = date_create("#$seconds");
$interval = date_diff($datetime1, $datetime2);
if ( $interval->y >= 1 ) $thetime[] = pluralize( $interval->y, 'year' );
if ( $interval->m >= 1 ) $thetime[] = pluralize( $interval->m, 'month' );
if ( $interval->d >= 1 ) $thetime[] = pluralize( $interval->d, 'day' );
if ( $interval->h >= 1 ) $thetime[] = pluralize( $interval->h, 'hour' );
if ( $interval->i >= 1 ) $thetime[] = pluralize( $interval->i, 'minute' );
if ( $interval->s >= 1 ) $thetime[] = pluralize( $interval->s, 'second' );
return isset($thetime) ? implode(' ', $thetime) . ($interval->invert ? ' ago' : '') : NULL;
}
function pluralize($count, $text) {
return $count . ($count == 1 ? " $text" : " ${text}s");
}
// Examples:
// -86400 = 1 day ago
// 12345 = 3 hours 25 minutes 45 seconds
// 987654321 = 31 years 3 months 18 days 4 hours 25 minutes 21 seconds
EDIT: If you want to condense the above example down to use less variables / space (at the expense of legibility), here is an alternate version that does the same thing:
function calctime($seconds = 0) {
$interval = date_diff(date_create("#0"),date_create("#$seconds"));
foreach (array('y'=>'year','m'=>'month','d'=>'day','h'=>'hour','i'=>'minute','s'=>'second') as $format=>$desc) {
if ($interval->$format >= 1) $thetime[] = $interval->$format . ($interval->$format == 1 ? " $desc" : " {$desc}s");
}
return isset($thetime) ? implode(' ', $thetime) . ($interval->invert ? ' ago' : '') : NULL;
}
an extended version of Glavić's excellent solution , having integer validation, solving the 1 s problem, and additional support for years and months, at the expense of being less computer parsing friendly in favor of being more human friendly:
<?php
function secondsToHumanReadable(/*int*/ $seconds)/*: string*/ {
//if you dont need php5 support, just remove the is_int check and make the input argument type int.
if(!\is_int($seconds)){
throw new \InvalidArgumentException('Argument 1 passed to secondsToHumanReadable() must be of the type int, '.\gettype($seconds).' given');
}
$dtF = new \DateTime ( '#0' );
$dtT = new \DateTime ( "#$seconds" );
$ret = '';
if ($seconds === 0) {
// special case
return '0 seconds';
}
$diff = $dtF->diff ( $dtT );
foreach ( array (
'y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second'
) as $time => $timename ) {
if ($diff->$time !== 0) {
$ret .= $diff->$time . ' ' . $timename;
if ($diff->$time !== 1 && $diff->$time !== -1 ) {
$ret .= 's';
}
$ret .= ' ';
}
}
return substr ( $ret, 0, - 1 );
}
var_dump(secondsToHumanReadable(1*60*60*2+1)); -> string(16) "2 hours 1 second"
function secondsToTime($seconds) {
$time = [];
$minutes = $seconds / 60;
$seconds = $seconds % 60;
$hours = $minutes / 60;
$minutes = $minutes % 60;
$days = $hours / 24;
$hours = $hours % 24;
$month = $days /30;
$days = $days % 30;
$year = $month / 12;
$month = $month % 12;
if ((int)($year) != 0){
array_push($time,[ "year" => (int)($year)]);
}
if ($month != 0){
array_push($time, ["months" => $month]);
}
if ($days != 0){
array_push($time,["days" => $days]);
}
if ($hours != 0){
array_push($time,["hours" => $hours]);
}
if ($minutes != 0){
array_push($time,["minutes" => $minutes]);
}
if ($seconds != 0){
array_push($time,["seconds" => $seconds]);
}
return $time;
}
I think Carbon will give you all variety that you want
so for your example you will add this code
$seconds = 1640467;
$time = Carbon::now();
$humanTime = $time->diffForHumans($time->copy()->addSeconds($seconds), true, false, 4);
the output will be like this
2 weeks 4 days 23 hours 41 minutes
Interval class I have written can be used. It can be used in opposite way too.
composer require lubos/cakephp-interval
$Interval = new \Interval\Interval\Interval();
// output 2w 6h
echo $Interval->toHuman((2 * 5 * 8 + 6) * 3600);
// output 36000
echo $Interval->toSeconds('1d 2h');
More info here https://github.com/LubosRemplik/CakePHP-Interval
With DateInterval :
$d1 = new DateTime();
$d2 = new DateTime();
$d2->add(new DateInterval('PT'.$timespan.'S'));
$interval = $d2->diff($d1);
echo $interval->format('%a days, %h hours, %i minutes and %s seconds');
// Or
echo sprintf('%d days, %d hours, %d minutes and %d seconds',
$interval->days,
$interval->h,
$interval->i,
$interval->s
);
// $interval->y => years
// $interval->m => months
// $interval->d => days
// $interval->h => hours
// $interval->i => minutes
// $interval->s => seconds
// $interval->days => total number of days
A bit more elaborated, skipping the time units which are zero
function secondsToTime($ss)
{
$htmlOut="";
$s = $ss%60;
$m = floor(($ss%3600)/60);
$h = floor(($ss%86400)/3600);
$d = floor(($ss%2592000)/86400);
$M = floor($ss/2592000);
if ( $M > 0 )
{
$htmlOut.="$M months";
}
if ( $d > 0 )
{
if ( $M > 0 )
$htmlOut.=", ";
$htmlOut.="$d days";
}
if ( $h > 0 )
{
if ( $d > 0 )
$htmlOut.=", ";
$htmlOut.="$h hours";
}
if ( $m > 0 )
{
if ( $h > 0 )
$htmlOut.=", ";
$htmlOut.="$m minutes";
}
if ( $s > 0 )
{
if ( $m > 0 )
$htmlOut.=" and ";
$htmlOut.="$s seconds";
}
return $htmlOut;
}
All in one solution. Gives no units with zeroes. Will only produce number of units you specify (3 by default).
Quite long, perhaps not very elegant. Defines are optional, but might come in handy in a big project.
define('OneMonth', 2592000);
define('OneWeek', 604800);
define('OneDay', 86400);
define('OneHour', 3600);
define('OneMinute', 60);
function SecondsToTime($seconds, $num_units=3) {
$time_descr = array(
"months" => floor($seconds / OneMonth),
"weeks" => floor(($seconds%OneMonth) / OneWeek),
"days" => floor(($seconds%OneWeek) / OneDay),
"hours" => floor(($seconds%OneDay) / OneHour),
"mins" => floor(($seconds%OneHour) / OneMinute),
"secs" => floor($seconds%OneMinute),
);
$res = "";
$counter = 0;
foreach ($time_descr as $k => $v) {
if ($v) {
$res.=$v." ".$k;
$counter++;
if($counter>=$num_units)
break;
elseif($counter)
$res.=", ";
}
}
return $res;
}
Here's some code that I like to use for the purpose of getting the duration between two dates. It accepts two dates and gives you a nice sentence structured reply.
This is a slightly modified version of the code found here.
<?php
function dateDiff($time1, $time2, $precision = 6, $offset = false) {
// If not numeric then convert texts to unix timestamps
if (!is_int($time1)) {
$time1 = strtotime($time1);
}
if (!is_int($time2)) {
if (!$offset) {
$time2 = strtotime($time2);
}
else {
$time2 = strtotime($time2) - $offset;
}
}
// If time1 is bigger than time2
// Then swap time1 and time2
if ($time1 > $time2) {
$ttime = $time1;
$time1 = $time2;
$time2 = $ttime;
}
// Set up intervals and diffs arrays
$intervals = array(
'year',
'month',
'day',
'hour',
'minute',
'second'
);
$diffs = array();
// Loop thru all intervals
foreach($intervals as $interval) {
// Create temp time from time1 and interval
$ttime = strtotime('+1 ' . $interval, $time1);
// Set initial values
$add = 1;
$looped = 0;
// Loop until temp time is smaller than time2
while ($time2 >= $ttime) {
// Create new temp time from time1 and interval
$add++;
$ttime = strtotime("+" . $add . " " . $interval, $time1);
$looped++;
}
$time1 = strtotime("+" . $looped . " " . $interval, $time1);
$diffs[$interval] = $looped;
}
$count = 0;
$times = array();
// Loop thru all diffs
foreach($diffs as $interval => $value) {
// Break if we have needed precission
if ($count >= $precision) {
break;
}
// Add value and interval
// if value is bigger than 0
if ($value > 0) {
// Add s if value is not 1
if ($value != 1) {
$interval.= "s";
}
// Add value and interval to times array
$times[] = $value . " " . $interval;
$count++;
}
}
if (!empty($times)) {
// Return string with times
return implode(", ", $times);
}
else {
// Return 0 Seconds
}
return '0 Seconds';
}
Source: https://gist.github.com/ozh/8169202
The solution for this one I used (back to the days while learning PHP) without any in-functions:
$days = (int)($uptime/86400); //1day = 86400seconds
$rdays = (uptime-($days*86400));
//seconds remaining after uptime was converted into days
$hours = (int)($rdays/3600);//1hour = 3600seconds,converting remaining seconds into hours
$rhours = ($rdays-($hours*3600));
//seconds remaining after $rdays was converted into hours
$minutes = (int)($rhours/60); // 1minute = 60seconds, converting remaining seconds into minutes
echo "$days:$hours:$minutes";
Though this was an old question, new learners who come across this, may find this answer useful.
a=int(input("Enter your number by seconds "))
d=a//(24*3600) #Days
h=a//(60*60)%24 #hours
m=a//60%60 #minutes
s=a%60 #seconds
print("Days ",d,"hours ",h,"minutes ",m,"seconds ",s)
I am editing one of the code to work it well when negative value comes. floor() function is not giving the correct count when the value is negative. So we need to use abs() function before using it in the floor() function.
$inputSeconds variable can be the difference between the current time stamp and the required date.
/**
* Convert number of seconds into hours, minutes and seconds
* and return an array containing those values
*
* #param integer $inputSeconds Number of seconds to parse
* #return array
*/
function secondsToTime($inputSeconds) {
$secondsInAMinute = 60;
$secondsInAnHour = 60 * $secondsInAMinute;
$secondsInADay = 24 * $secondsInAnHour;
// extract days
$days = abs($inputSeconds / $secondsInADay);
$days = floor($days);
// extract hours
$hourSeconds = $inputSeconds % $secondsInADay;
$hours = abs($hourSeconds / $secondsInAnHour);
$hours = floor($hours);
// extract minutes
$minuteSeconds = $hourSeconds % $secondsInAnHour;
$minutes = abs($minuteSeconds / $secondsInAMinute);
$minutes = floor($minutes);
// extract the remaining seconds
$remainingSeconds = $minuteSeconds % $secondsInAMinute;
$seconds = abs($remainingSeconds);
$seconds = ceil($remainingSeconds);
// return the final array
$obj = array(
'd' => (int) $days,
'h' => (int) $hours,
'm' => (int) $minutes,
's' => (int) $seconds,
);
return $obj;
}
A variation on #Glavić's answer - this one hides leading zeros for shorter results and uses plurals in correct places. It also removes unnecessary precision (e.g. if the time difference is over 2 hours, you probably don't care how many minutes or seconds).
function secondsToTime($seconds)
{
$dtF = new \DateTime('#0');
$dtT = new \DateTime("#$seconds");
$dateInterval = $dtF->diff($dtT);
$days_t = 'day';
$hours_t = 'hour';
$minutes_t = 'minute';
$seconds_t = 'second';
if ((int)$dateInterval->d > 1) {
$days_t = 'days';
}
if ((int)$dateInterval->h > 1) {
$hours_t = 'hours';
}
if ((int)$dateInterval->i > 1) {
$minutes_t = 'minutes';
}
if ((int)$dateInterval->s > 1) {
$seconds_t = 'seconds';
}
if ((int)$dateInterval->d > 0) {
if ((int)$dateInterval->d > 1 || (int)$dateInterval->h === 0) {
return $dateInterval->format("%a $days_t");
} else {
return $dateInterval->format("%a $days_t, %h $hours_t");
}
} else if ((int)$dateInterval->h > 0) {
if ((int)$dateInterval->h > 1 || (int)$dateInterval->i === 0) {
return $dateInterval->format("%h $hours_t");
} else {
return $dateInterval->format("%h $hours_t, %i $minutes_t");
}
} else if ((int)$dateInterval->i > 0) {
if ((int)$dateInterval->i > 1 || (int)$dateInterval->s === 0) {
return $dateInterval->format("%i $minutes_t");
} else {
return $dateInterval->format("%i $minutes_t, %s $seconds_t");
}
} else {
return $dateInterval->format("%s $seconds_t");
}
}
php > echo secondsToTime(60);
1 minute
php > echo secondsToTime(61);
1 minute, 1 second
php > echo secondsToTime(120);
2 minutes
php > echo secondsToTime(121);
2 minutes
php > echo secondsToTime(2000);
33 minutes
php > echo secondsToTime(4000);
1 hour, 6 minutes
php > echo secondsToTime(4001);
1 hour, 6 minutes
php > echo secondsToTime(40001);
11 hours
php > echo secondsToTime(400000);
4 days
Added some formatting modified from Glavić's great answer for Facebook style time of post count up....
function secondsToTime($seconds) {
$dtF = new \DateTime('#0');
$dtT = new \DateTime("#$seconds");
switch($seconds){
case ($seconds<60*60*24): // if time is less than one day
return $dtF->diff($dtT)->format('%h hours, %i minutes, %s seconds');
break;
case ($seconds<60*60*24*31 && $seconds>60*60*24): // if time is between 1 day and 1 month
return $dtF->diff($dtT)->format('%d days, %h hours');
break;
case ($seconds<60*60*24*365 && $seconds>60*60*24*31): // if time between 1 month and 1 year
return $dtF->diff($dtT)->format('%m months, %d days');
break;
case ($seconds>60*60*24*365): // if time is longer than 1 year
return $dtF->diff($dtT)->format('%y years, %m months');
break;
}
foreach ($email as $temp => $value) {
$dat = strtotime($value['subscription_expiration']); //$value come from mysql database
//$email is an array from mysqli_query()
$date = strtotime(date('Y-m-d'));
$_SESSION['expiry'] = (((($dat - $date)/60)/60)/24)." Days Left";
//you will get the difference from current date in days.
}
$value come from Database. This code is in Codeigniter. $SESSION is used for storing user subscriptions. it is mandatory. I used it in my case, you can use whatever you want.
This is a function i used in the past for substracting a date from another one related with your question, my principe was to get how many days, hours minutes and seconds has left until a product has expired :
$expirationDate = strtotime("2015-01-12 20:08:23");
$toDay = strtotime(date('Y-m-d H:i:s'));
$difference = abs($toDay - $expirationDate);
$days = floor($difference / 86400);
$hours = floor(($difference - $days * 86400) / 3600);
$minutes = floor(($difference - $days * 86400 - $hours * 3600) / 60);
$seconds = floor($difference - $days * 86400 - $hours * 3600 - $minutes * 60);
echo "{$days} days {$hours} hours {$minutes} minutes {$seconds} seconds";
I have the following timestamp 1347216222 which is of day and am using it with a time_since function to check how long ago it was in hours.. minutes etc.
<?php
/* Works out the time since the entry post, takes a an argument in unix time (seconds) */
function time_since($original) {
// 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'),
);
$today = time(); /* Current unix time */
$since = $today - $original;
// $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) {
// DEBUG print "<!-- It's $name -->\n";
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 $print;
}
echo time_since(1347216222);
?>
The output is -1 years, 12 months. Can anyone help me to fix this?
I tailored the function to use DateTime and DateInterval, which makes it more readable.
It differs from the function you posted with regard to how the time difference is treated. In your case, you tested the values twice (once for each "unit"). This required complex calculations on your part.
The function below, on the other hand, takes advantage of the fact that DateInterval gives you a ready-to-use difference in years, moths, days, hours, minutes and seconds (e.g. the difference between 2015 and 2014 is 1 year and 0 seconds, as opposed to UNIX timestamps). Furthermore, the usage of DateTime allows you to handle timezones gracefully.
That being said, all you need to care of is how to print that difference, and this is exactly what the for loops are for - we extract two values and use an extra item (we call such items guardians), to save additional conditions when we want to extract the second item.
Here's the function:
<?php
function pluralize($number, $unit) {
return $number . ' ' . $unit . ($number !== 1 ? 's' : '');
}
function time_since(DateTime $original) {
$now = new DateTime('now');
$diff = $now->diff($original);
//is from the past?
if ($diff->invert) {
$chunks = [
[$diff->y, 'year'],
[$diff->m, 'month'],
[$diff->d, 'day'],
[$diff->h, 'hour'],
[$diff->i, 'minute'],
[$diff->s, 'second'],
[0, 'guardian'],
];
for ($i = 0; $i < count($chunks) - 1; $i ++) {
list ($value, $unit) = $chunks[$i];
if ($value !== 0) {
$text = pluralize($value, $unit);
//append next unit as well, if it's available and nonzero
list ($nextValue, $nextUnit) = $chunks[$i + 1];
if ($nextValue !== 0) {
$text .= ' ' . pluralize($nextValue, $nextUnit);
}
return $text;
}
}
}
return 'just now';
}
And the tests:
echo time_since(new DateTime('2014-01-01')) . PHP_EOL;
echo time_since(new DateTime('2014-10-09')) . PHP_EOL;
echo time_since(new DateTime('2014-11-09')) . PHP_EOL;
echo time_since(new DateTime('2014-11-10')) . PHP_EOL;
echo time_since(new DateTime('2014-11-10 13:05')) . PHP_EOL;
echo time_since(new DateTime('2114-11-10 13:05')) . PHP_EOL; //future
Results:
rr-#work:~$ php test.php
10 months 9 days
1 month 1 day
1 day 13 hours
13 hours 5 minutes
38 seconds
just now
Want to display a different message if the time is under a certain amount. I have then function that I have been working on, but cannot not get it to work unless the if for time is 1. Would like 10 minutes.
function TimeSince($timestamp)
{
// 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'),
);
// difference in seconds
$since = time() - $timestamp;
// calculate one chunk of time
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;
}
}
// set output var
$output = ($count == 1) ? '1 '.$name : "$count {$name}s";
// Displays time of if under 10 minutes displays Just Now
if($output < 10) {
return ("Just Now!");
}
else {
return ($output . " ago");
}
return $output;
}
In the following line of code:
$output = ($count == 1) ? '1 '.$name : "$count {$name}s";
You redefine $output as a string, consider checking before you assign it as one such as:
// Displays time of if under 10 minutes displays Just Now
if($count < 10) {
return ("Just Now!");
}
else {
// set output var
$output = ($count == 1) ? '1 '.$name : "$count {$name}s";
return ($output . " ago");
}
You're setting $output to a string value in this line:
$output = ($count == 1) ? '1 '.$name : "$count {$name}s";
And then attempting to compare it to a number. Try assigning a numeric value to $output.
This question already has answers here:
Converting timestamp to time ago in PHP e.g 1 day ago, 2 days ago...
(32 answers)
Closed 7 years ago.
How to find the time elapsed since a date time stamp like 2010-04-28 17:25:43, final out put text should be like xx Minutes Ago/xx Days Ago
Most of the answers seem focused around converting the date from a string to time. It seems you're mostly thinking about getting the date into the '5 days ago' format, etc.. right?
This is how I'd go about doing that:
$time = strtotime('2010-04-28 17:25:43');
echo 'event happened '.humanTiming($time).' ago';
function humanTiming ($time)
{
$time = time() - $time; // to get the time since that moment
$time = ($time<1)? 1 : $time;
$tokens = array (
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
foreach ($tokens as $unit => $text) {
if ($time < $unit) continue;
$numberOfUnits = floor($time / $unit);
return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
}
}
I haven't tested that, but it should work.
The result would look like
event happened 4 days ago
or
event happened 1 minute ago
Want to share php function which results in grammatically correct Facebook like human readable time format.
Example:
echo get_time_ago(strtotime('now'));
Result:
less than 1 minute ago
function get_time_ago($time_stamp)
{
$time_difference = strtotime('now') - $time_stamp;
if ($time_difference >= 60 * 60 * 24 * 365.242199)
{
/*
* 60 seconds/minute * 60 minutes/hour * 24 hours/day * 365.242199 days/year
* This means that the time difference is 1 year or more
*/
return get_time_ago_string($time_stamp, 60 * 60 * 24 * 365.242199, 'year');
}
elseif ($time_difference >= 60 * 60 * 24 * 30.4368499)
{
/*
* 60 seconds/minute * 60 minutes/hour * 24 hours/day * 30.4368499 days/month
* This means that the time difference is 1 month or more
*/
return get_time_ago_string($time_stamp, 60 * 60 * 24 * 30.4368499, 'month');
}
elseif ($time_difference >= 60 * 60 * 24 * 7)
{
/*
* 60 seconds/minute * 60 minutes/hour * 24 hours/day * 7 days/week
* This means that the time difference is 1 week or more
*/
return get_time_ago_string($time_stamp, 60 * 60 * 24 * 7, 'week');
}
elseif ($time_difference >= 60 * 60 * 24)
{
/*
* 60 seconds/minute * 60 minutes/hour * 24 hours/day
* This means that the time difference is 1 day or more
*/
return get_time_ago_string($time_stamp, 60 * 60 * 24, 'day');
}
elseif ($time_difference >= 60 * 60)
{
/*
* 60 seconds/minute * 60 minutes/hour
* This means that the time difference is 1 hour or more
*/
return get_time_ago_string($time_stamp, 60 * 60, 'hour');
}
else
{
/*
* 60 seconds/minute
* This means that the time difference is a matter of minutes
*/
return get_time_ago_string($time_stamp, 60, 'minute');
}
}
function get_time_ago_string($time_stamp, $divisor, $time_unit)
{
$time_difference = strtotime("now") - $time_stamp;
$time_units = floor($time_difference / $divisor);
settype($time_units, 'string');
if ($time_units === '0')
{
return 'less than 1 ' . $time_unit . ' ago';
}
elseif ($time_units === '1')
{
return '1 ' . $time_unit . ' ago';
}
else
{
/*
* More than "1" $time_unit. This is the "plural" message.
*/
// TODO: This pluralizes the time unit, which is done by adding "s" at the end; this will not work for i18n!
return $time_units . ' ' . $time_unit . 's ago';
}
}
I think I have a function which should do what you want:
function time2string($timeline) {
$periods = array('day' => 86400, 'hour' => 3600, 'minute' => 60, 'second' => 1);
foreach($periods AS $name => $seconds){
$num = floor($timeline / $seconds);
$timeline -= ($num * $seconds);
$ret .= $num.' '.$name.(($num > 1) ? 's' : '').' ';
}
return trim($ret);
}
Simply apply it to the difference between time() and strtotime('2010-04-28 17:25:43') as so:
print time2string(time()-strtotime('2010-04-28 17:25:43')).' ago';
To improve upon #arnorhs answer I've added in the ability to have a more precise result so if you wanted years, months, days & hours for instance since the user joined.
I've added a new parameter to allow you to specify the number of points of precision you wish to have returned.
function get_friendly_time_ago($distant_timestamp, $max_units = 3) {
$i = 0;
$time = time() - $distant_timestamp; // to get the time since that moment
$tokens = [
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
];
$responses = [];
while ($i < $max_units && $time > 0) {
foreach ($tokens as $unit => $text) {
if ($time < $unit) {
continue;
}
$i++;
$numberOfUnits = floor($time / $unit);
$responses[] = $numberOfUnits . ' ' . $text . (($numberOfUnits > 1) ? 's' : '');
$time -= ($unit * $numberOfUnits);
break;
}
}
if (!empty($responses)) {
return implode(', ', $responses) . ' ago';
}
return 'Just now';
}
If you use the php Datetime class you could use:
function time_ago(Datetime $date) {
$time_ago = '';
$diff = $date->diff(new Datetime('now'));
if (($t = $diff->format("%m")) > 0)
$time_ago = $t . ' months';
else if (($t = $diff->format("%d")) > 0)
$time_ago = $t . ' days';
else if (($t = $diff->format("%H")) > 0)
$time_ago = $t . ' hours';
else
$time_ago = 'minutes';
return $time_ago . ' ago (' . $date->format('M j, Y') . ')';
}
Be warned, the majority of the mathematically calculated examples have a hard limit of 2038-01-18 dates and will not work with fictional dates.
As there was a lack of DateTime and DateInterval based examples, I wanted to provide a multi-purpose function that satisfies the OP's need and others wanting compound elapsed periods, such as 1 month 2 days ago. Along with a bunch of other use cases, such as a limit to display the date instead of the elapsed time, or to filter out portions of the elapsed time result.
Additionally the majority of the examples assume elapsed is from the current time, where the below function allows for it to be overridden with the desired end date.
/**
* multi-purpose function to calculate the time elapsed between $start and optional $end
* #param string|null $start the date string to start calculation
* #param string|null $end the date string to end calculation
* #param string $suffix the suffix string to include in the calculated string
* #param string $format the format of the resulting date if limit is reached or no periods were found
* #param string $separator the separator between periods to use when filter is not true
* #param null|string $limit date string to stop calculations on and display the date if reached - ex: 1 month
* #param bool|array $filter false to display all periods, true to display first period matching the minimum, or array of periods to display ['year', 'month']
* #param int $minimum the minimum value needed to include a period
* #return string
*/
function elapsedTimeString($start, $end = null, $limit = null, $filter = true, $suffix = 'ago', $format = 'Y-m-d', $separator = ' ', $minimum = 1)
{
$dates = (object) array(
'start' => new DateTime($start ? : 'now'),
'end' => new DateTime($end ? : 'now'),
'intervals' => array('y' => 'year', 'm' => 'month', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second'),
'periods' => array()
);
$elapsed = (object) array(
'interval' => $dates->start->diff($dates->end),
'unknown' => 'unknown'
);
if ($elapsed->interval->invert === 1) {
return trim('0 seconds ' . $suffix);
}
if (false === empty($limit)) {
$dates->limit = new DateTime($limit);
if (date_create()->add($elapsed->interval) > $dates->limit) {
return $dates->start->format($format) ? : $elapsed->unknown;
}
}
if (true === is_array($filter)) {
$dates->intervals = array_intersect($dates->intervals, $filter);
$filter = false;
}
foreach ($dates->intervals as $period => $name) {
$value = $elapsed->interval->$period;
if ($value >= $minimum) {
$dates->periods[] = vsprintf('%1$s %2$s%3$s', array($value, $name, ($value !== 1 ? 's' : '')));
if (true === $filter) {
break;
}
}
}
if (false === empty($dates->periods)) {
return trim(vsprintf('%1$s %2$s', array(implode($separator, $dates->periods), $suffix)));
}
return $dates->start->format($format) ? : $elapsed->unknown;
}
One thing to note - the retrieved intervals for the supplied filter values do not carry over to the next period. The filter merely displays the resulting value of the supplied periods and does not recalculate the periods to display only the desired filter total.
Usage
For the OP's need of displaying the highest period (as of 2015-02-24).
echo elapsedTimeString('2010-04-26');
/** 4 years ago */
To display compound periods and supply a custom end date (note the lack of time supplied and fictional dates).
echo elapsedTimeString('1920-01-01', '2500-02-24', null, false);
/** 580 years 1 month 23 days ago */
To display the result of filtered periods (ordering of array doesn't matter).
echo elapsedTimeString('2010-05-26', '2012-02-24', null, ['month', 'year']);
/** 1 year 8 months ago */
To display the start date in the supplied format (default Y-m-d) if the limit is reached.
echo elapsedTimeString('2010-05-26', '2012-02-24', '1 year');
/** 2010-05-26 */
There are bunch of other use cases. It can also easily be adapted to accept unix timestamps and/or DateInterval objects for the start, end, or limit arguments.
One option that'll work with any version of PHP is to do what's already been suggested, which is something like this:
$eventTime = '2010-04-28 17:25:43';
$age = time() - strtotime($eventTime);
That will give you the age in seconds. From there, you can display it however you wish.
One problem with this approach, however, is that it won't take into account time shifts causes by DST. If that's not a concern, then go for it. Otherwise, you'll probably want to use the diff() method in the DateTime class. Unfortunately, this is only an option if you're on at least PHP 5.3.
I liked Mithun's code, but I tweaked it a bit to make it give more reasonable answers.
function getTimeSince($eventTime)
{
$totaldelay = time() - strtotime($eventTime);
if($totaldelay <= 0)
{
return '';
}
else
{
$first = '';
$marker = 0;
if($years=floor($totaldelay/31536000))
{
$totaldelay = $totaldelay % 31536000;
$plural = '';
if ($years > 1) $plural='s';
$interval = $years." year".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$marker = 1;
$first = ", ";
}
if($months=floor($totaldelay/2628000))
{
$totaldelay = $totaldelay % 2628000;
$plural = '';
if ($months > 1) $plural='s';
$interval = $months." month".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$marker = 1;
$first = ", ";
}
if($days=floor($totaldelay/86400))
{
$totaldelay = $totaldelay % 86400;
$plural = '';
if ($days > 1) $plural='s';
$interval = $days." day".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$marker = 1;
$first = ", ";
}
if ($marker) return $timesince;
if($hours=floor($totaldelay/3600))
{
$totaldelay = $totaldelay % 3600;
$plural = '';
if ($hours > 1) $plural='s';
$interval = $hours." hour".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$marker = 1;
$first = ", ";
}
if($minutes=floor($totaldelay/60))
{
$totaldelay = $totaldelay % 60;
$plural = '';
if ($minutes > 1) $plural='s';
$interval = $minutes." minute".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$first = ", ";
}
if($seconds=floor($totaldelay/1))
{
$totaldelay = $totaldelay % 1;
$plural = '';
if ($seconds > 1) $plural='s';
$interval = $seconds." second".$plural;
$timesince = $timesince.$first.$interval;
}
return $timesince;
}
}
Convert [saved_date] to timestamp. Get current timestamp.
current timestamp - [saved_date] timestamp.
Then you can format it with date();
You can normally convert most date formats to timestamps with the strtotime() function.
Use This one and you can get the
$previousDate = '2013-7-26 17:01:10';
$startdate = new DateTime($previousDate);
$endDate = new DateTime('now');
$interval = $endDate->diff($startdate);
echo$interval->format('%y years, %m months, %d days');
Refer this
http://ca2.php.net/manual/en/dateinterval.format.php
Try one of these repos:
https://github.com/salavert/time-ago-in-words
https://github.com/jimmiw/php-time-ago
I just started using the latter, does the trick, but no stackoverflow-style fallback on exact date when the date in question is too far away, nor is there support for future dates - and the API is a little funky, but at least it works seemingly flawlessly and is maintained...
To find out time elapsed i usually use time() instead of date() and formatted time stamps.
Then get the difference between the latter value and the earlier value and format accordingly. time() is differently not a replacement for date() but it totally helps when calculating elapsed time.
example:
The value of time() looks something like this 1274467343 increments every second. So you could have $erlierTime with value 1274467343 and $latterTime with value 1274467500, then just do $latterTime - $erlierTime to get time elapsed in seconds.
Wrote my own
function getElapsedTime($eventTime)
{
$totaldelay = time() - strtotime($eventTime);
if($totaldelay <= 0)
{
return '';
}
else
{
if($days=floor($totaldelay/86400))
{
$totaldelay = $totaldelay % 86400;
return $days.' days ago.';
}
if($hours=floor($totaldelay/3600))
{
$totaldelay = $totaldelay % 3600;
return $hours.' hours ago.';
}
if($minutes=floor($totaldelay/60))
{
$totaldelay = $totaldelay % 60;
return $minutes.' minutes ago.';
}
if($seconds=floor($totaldelay/1))
{
$totaldelay = $totaldelay % 1;
return $seconds.' seconds ago.';
}
}
}
Here I am using custom function for finding the time elapsed since a date time.
echo Datetodays('2013-7-26 17:01:10');
function Datetodays($d) {
$date_start = $d;
$date_end = date('Y-m-d H:i:s');
define('SECOND', 1);
define('MINUTE', SECOND * 60);
define('HOUR', MINUTE * 60);
define('DAY', HOUR * 24);
define('WEEK', DAY * 7);
$t1 = strtotime($date_start);
$t2 = strtotime($date_end);
if ($t1 > $t2) {
$diffrence = $t1 - $t2;
} else {
$diffrence = $t2 - $t1;
}
//echo "".$date_end." ".$date_start." ".$diffrence;
$results['major'] = array(); // whole number representing larger number in date time relationship
$results1 = array();
$string = '';
$results['major']['weeks'] = floor($diffrence / WEEK);
$results['major']['days'] = floor($diffrence / DAY);
$results['major']['hours'] = floor($diffrence / HOUR);
$results['major']['minutes'] = floor($diffrence / MINUTE);
$results['major']['seconds'] = floor($diffrence / SECOND);
//print_r($results);
// Logic:
// Step 1: Take the major result and transform it into raw seconds (it will be less the number of seconds of the difference)
// ex: $result = ($results['major']['weeks']*WEEK)
// Step 2: Subtract smaller number (the result) from the difference (total time)
// ex: $minor_result = $difference - $result
// Step 3: Take the resulting time in seconds and convert it to the minor format
// ex: floor($minor_result/DAY)
$results1['weeks'] = floor($diffrence / WEEK);
$results1['days'] = floor((($diffrence - ($results['major']['weeks'] * WEEK)) / DAY));
$results1['hours'] = floor((($diffrence - ($results['major']['days'] * DAY)) / HOUR));
$results1['minutes'] = floor((($diffrence - ($results['major']['hours'] * HOUR)) / MINUTE));
$results1['seconds'] = floor((($diffrence - ($results['major']['minutes'] * MINUTE)) / SECOND));
//print_r($results1);
if ($results1['weeks'] != 0 && $results1['days'] == 0) {
if ($results1['weeks'] == 1) {
$string = $results1['weeks'] . ' week ago';
} else {
if ($results1['weeks'] == 2) {
$string = $results1['weeks'] . ' weeks ago';
} else {
$string = '2 weeks ago';
}
}
} elseif ($results1['weeks'] != 0 && $results1['days'] != 0) {
if ($results1['weeks'] == 1) {
$string = $results1['weeks'] . ' week ago';
} else {
if ($results1['weeks'] == 2) {
$string = $results1['weeks'] . ' weeks ago';
} else {
$string = '2 weeks ago';
}
}
} elseif ($results1['weeks'] == 0 && $results1['days'] != 0) {
if ($results1['days'] == 1) {
$string = $results1['days'] . ' day ago';
} else {
$string = $results1['days'] . ' days ago';
}
} elseif ($results1['days'] != 0 && $results1['hours'] != 0) {
$string = $results1['days'] . ' day and ' . $results1['hours'] . ' hours ago';
} elseif ($results1['days'] == 0 && $results1['hours'] != 0) {
if ($results1['hours'] == 1) {
$string = $results1['hours'] . ' hour ago';
} else {
$string = $results1['hours'] . ' hours ago';
}
} elseif ($results1['hours'] != 0 && $results1['minutes'] != 0) {
$string = $results1['hours'] . ' hour and ' . $results1['minutes'] . ' minutes ago';
} elseif ($results1['hours'] == 0 && $results1['minutes'] != 0) {
if ($results1['minutes'] == 1) {
$string = $results1['minutes'] . ' minute ago';
} else {
$string = $results1['minutes'] . ' minutes ago';
}
} elseif ($results1['minutes'] != 0 && $results1['seconds'] != 0) {
$string = $results1['minutes'] . ' minute and ' . $results1['seconds'] . ' seconds ago';
} elseif ($results1['minutes'] == 0 && $results1['seconds'] != 0) {
if ($results1['seconds'] == 1) {
$string = $results1['seconds'] . ' second ago';
} else {
$string = $results1['seconds'] . ' seconds ago';
}
}
return $string;
}
?>
You can get a function for this directly form WordPress core files take a look here
http://core.trac.wordpress.org/browser/tags/3.6/wp-includes/formatting.php#L2121
function human_time_diff( $from, $to = '' ) {
if ( empty( $to ) )
$to = time();
$diff = (int) abs( $to - $from );
if ( $diff < HOUR_IN_SECONDS ) {
$mins = round( $diff / MINUTE_IN_SECONDS );
if ( $mins <= 1 )
$mins = 1;
/* translators: min=minute */
$since = sprintf( _n( '%s min', '%s mins', $mins ), $mins );
} elseif ( $diff < DAY_IN_SECONDS && $diff >= HOUR_IN_SECONDS ) {
$hours = round( $diff / HOUR_IN_SECONDS );
if ( $hours <= 1 )
$hours = 1;
$since = sprintf( _n( '%s hour', '%s hours', $hours ), $hours );
} elseif ( $diff < WEEK_IN_SECONDS && $diff >= DAY_IN_SECONDS ) {
$days = round( $diff / DAY_IN_SECONDS );
if ( $days <= 1 )
$days = 1;
$since = sprintf( _n( '%s day', '%s days', $days ), $days );
} elseif ( $diff < 30 * DAY_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) {
$weeks = round( $diff / WEEK_IN_SECONDS );
if ( $weeks <= 1 )
$weeks = 1;
$since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks );
} elseif ( $diff < YEAR_IN_SECONDS && $diff >= 30 * DAY_IN_SECONDS ) {
$months = round( $diff / ( 30 * DAY_IN_SECONDS ) );
if ( $months <= 1 )
$months = 1;
$since = sprintf( _n( '%s month', '%s months', $months ), $months );
} elseif ( $diff >= YEAR_IN_SECONDS ) {
$years = round( $diff / YEAR_IN_SECONDS );
if ( $years <= 1 )
$years = 1;
$since = sprintf( _n( '%s year', '%s years', $years ), $years );
}
return $since;
}
Improvisation to the function "humanTiming" by arnorhs. It would calculate a "fully stretched" translation of time string to human readable text version. For example to say it like "1 week 2 days 1 hour 28 minutes 14 seconds"
function humantime ($oldtime, $newtime = null, $returnarray = false) {
if(!$newtime) $newtime = time();
$time = $newtime - $oldtime; // to get the time since that moment
$tokens = array (
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
$htarray = array();
foreach ($tokens as $unit => $text) {
if ($time < $unit) continue;
$numberOfUnits = floor($time / $unit);
$htarray[$text] = $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
$time = $time - ( $unit * $numberOfUnits );
}
if($returnarray) return $htarray;
return implode(' ', $htarray);
}
Had to do this recently - hope this helps someone. It doesn't cater for every possibility, but met my needs for a project.
https://github.com/duncanheron/twitter_date_format
https://github.com/duncanheron/twitter_date_format/blob/master/twitter_date_format.php