php date formatting for time difference - php

I just want to output as a result of a script to be executed through CLI the time the execution of the script took.
for doing that, I set a var at the start of the script
$start_time = time();
and then at the end
date('H:i:s',time() - $start_time);
the problem is that even when the ellapsed time might be in the range of seconds or minutes, it always print that at least an hour has passed:
>>> echo date('H:i:s',1);
01:00:01
>>> echo date('H:i:s', 10);
01:00:10
>>> echo date('H:i:s',3599);
01:59:59
>>> echo date('H:i:s',3600);
02:00:00
shouldn't it display 00:XX:YY, when less than an hour has passed?
is there something I'm missing, is there a bug?
thanks for your help!

Don't use date(). When you have time() - $start_time the result is in seconds. Multiply this up if you want it in mintues etc. or use the following function to convert the seconds to Hours, Minutes and Seconds.
<?php /**
*
* #convert seconds to hours minutes and seconds
*
* #param int $seconds The number of seconds
*
* #return string
*
*/
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;
} ?>
Example usage:
<?php
/*** time since EPOCH ***/
echo secondsToWords(time());
?>

You could try this function:
<?
$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
$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':'');
}
}
?>
From here:
PHP How to find the time elapsed since a date time?
This will give you a better means of getting the difference. Simply replace strtotime('2010-04-28 17:25:43'); with whatever your start date/time is (as a timestamp). One of the benefits is the function can be repurposed elsewhere.

Try this:
echo "Time left:". date('H:i:s', (strtotime('2000-01-01 00:00:00') + (time()-$start_time) ));

Use gmdate() instead of date() to display the correct time difference and compensate for the server's time zone

This function gives a "fully" formatted human readable time string..
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);
}

Related

Hide Unused/zero result from showing on format (Second to readable data format function) [duplicate]

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";

How can I limit time ago function to under 12 months and post actual date for year or later?

I would like to post the actual date of an article (i.e. April 5, 2015) if it has been a year or more since its post. If less than a year, I would like to use the time ago function (i.e. 6 months ago).
I've tried commenting out the year in the HumanTiming Time Ago Function (posted by arnorhs) and adding an if/else condition to it
$time = strtotime('2015-04-05 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'
);
if($time > $tokens){
echo "April 5, 2015";
} else {
foreach ($tokens as $unit => $text) {
if ($time < $unit) continue;
$numberOfUnits = floor($time / $unit);
return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
}
}
}
I expect the output to be "April 5, 2015", but it ignores the if/else condition and posts the date as "36 months ago".
How can I achieve the result I'm looking for?
using DateTime is way simpler
$now = new DateTime();
$then = new DateTime('April 5, 2015');
$diff = $now->diff($then); // returns DateInterval object or false on failure
if ($diff->y >= 1) {
// show your date
echo $then->format('Y-m-d H:i:s');
} else {
// show the interval
echo $diff->format('%d days ago');
}
check the documentation for more info
https://www.php.net/manual/en/class.dateinterval.php
https://www.php.net/manual/en/dateinterval.format.php
You need to check against the time of one year ago - not against the array $tokens. You can get the time of one year ago from strtotime('1 year ago'). If that is lesser than time()-$time (the current timestamp minus the $time timestamp), then the input-time is more than one year 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'
);
if (time()-$time < strtotime("1 year ago")) {
return date("F jS, Y", time()-$time);
} else {
foreach ($tokens as $unit => $text) {
if ($time < $unit) continue;
$numberOfUnits = floor($time / $unit);
return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'').' ago';
}
}
}
echo 'event happened '.humanTiming($time).'';
Live demo at https://3v4l.org/UH9df
<?php
$time = strtotime('2014-01-01 17:25:43');
function humanTiming ($time)
{
$back_time = $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 < 31536000){
$numberOfUnits = floor($time / $unit);
return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
}
}
return date("Y-m-d H:i:s", $back_time);
}
echo 'event happened '.humanTiming($time);
?>
Everyone's different. I personally like to convert dates into unix timestamps (actual whole numbers) and work from there. Between the function and the function call are some display lines (echos) I added to give you a visual of what's happening. You can remove them, obviously.
<?php
//first here's the function
function date_less_year($entered_date_unix)
{
$difference = time() - $entered_date_unix;
//31536000 is a 'unix year'
if ($difference <= 31536000)
{
return true; //is less than or equal to a year
}
else if ($difference > 31536000)
{
return false; //is more than a year
}
}
/* display in the format you asked for. you can google 'php date' to learn of
* different formats you can use
*/
$entered_date_string = '2015-04-05 17:25:43';
$entered_date_to_display = date($entered_date_string);
echo $entered_date_to_display . ' is the date entered<br/>';
//let's turn to a unix timestampe to compare differences
$entered_date_unix = strtotime($entered_date_string);
echo $entered_date_unix . ' is the unix timestamp for entered date<br/>';
echo time() . ' is unix time for NOW <br/>';
if (date_less_year($entered_date_unix) == true)
{
//do something for less than a year
echo 'is less than a year!';
}
else
{
//do something for more than a year
echo 'is more than a year!';
}
?>

how to get the date time or mintutes with past ago

How do I to get the minutes from a this datatime field
$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':'');
}
}
With DateTime you can achieve it like this:
$d1 = new DateTime('2010-04-28 17:25:43'); // start time
$d2 = new DateTime(); // end time (now)
$diff_seconds = $d2->getTimestamp() - $d1->getTimestamp();
$diff_minutes = $diff_seconds/60; // get amount of minutes
echo round($diff_minutes);
Convert both to timestamps, subtract, and format again such as
$timestamp = strtotime('22-09-2008');
$since = time() - $timestamp;
echo date('Y-m-d H:i:s', strtotime($since));
Not tested, please check the date function documentation and this answer:
How to calculate the difference between two dates using PHP?

sql while functions

function timeago($ptime) {
$etime = time() - $ptime;
if ($etime < 1) {
return '0 seconds';
}
$a = array( 12 * 30 * 24 * 60 * 60 => 'year',
30 * 24 * 60 * 60 => 'month',
24 * 60 * 60 => 'day',
60 * 60 => 'hour',
60 => 'minute',
1 => 'second'
);
foreach ($a as $secs => $str) {
$d = $etime / $secs;
if ($d >= 1) {
$r = round($d);
return $r . ' ' . $str . ($r > 1 ? 's' : '');
}
}
}
lets say i have that function, and i have an sql result that give me an array with multiple time stamps in UNIX form. using a while loop, how can i use this function for each timestamp so each loop result would contain the time ago of each sql UNIX timestamp?
You could use DateTime class.
function timeAgo($ptime){
$date1 = DateTime::createFromFormat("s", $ptime);//HOPE THIS WILL WORK
$date2 = new DateTime("now");
$interval = $date1->diff($date2);
$diff = $interval->format('%y-%m-%d');
return $diff;
}
invoke this method on each iteration and pass in the timestamp from the DB.

Convert seconds into days, hours, minutes and 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";

Categories