PHP negative time calculation - php

If I add 1 hour and 35 minutes in PHP and subtract 4 hours, I get a remaining time of -3 hours and 30 minutes.
But correct would be -2 hours and 30 minutes. Where’s the mistake?
$minutes = null;
while ($z = $stmt->fetch()) {
$minutes += $z['minutes'];
}
if ($stmt = $pdo->prepare($sql)) {
$stmt->execute(array(
':user' => $user
));
$negativeTime = null;
while ($z = $stmt->fetch()) {
$negativeTime += $z['minutes'];
}
}
$minutes = $minutes - $negativeTime;
echo (floor($minutes / 60)) . " hours and " . ($minutes - floor($minutes / 60) * 60) . " minutes";

$minutes - floor($minutes/60) is positive. So what you're getting is -3 hours plus 30 minutes, which is -2:30.
You need to treat positive and negative values of $minutes differently, so that both the hours and minutes are the distance from zero. Use the abs() function to convert the time to positive, perform the calculation, then show the hours as negative if the original value of $minutes was negative.
$sign = $minutes < 0 ? '-' : '';
$minutes = abs($minutes);
$hours = floor($minutes / 60);
$minutes = $minutes % 60;
echo "$sign$hours hours and $minutes minutes";
DEMO

Related

convert negative seconds into hh:mm:ss format

wanne have a function that convert positive and negative seconds in Timeformat h:i:s
So i have value like
$seconds= -41880;
Try with first function
function secToHR($seconds)
{
$hours = floor($seconds / 3600);
$mins = floor($seconds / 60 % 60);
$secs = floor($seconds % 60);
$time = sprintf('%02d:%02d:%02d', $hours, $mins, $secs);
return $time;
}
result is
$time = -12:-38:00
When i use a positive value for $seconds
$seconds = 100380
then result is like
$time = 27:53:00
what is correct
Then second function
function secToHR2($seconds)
{
$time = gmdate("h:i:s", abs($seconds));
if ($seconds < 0) {
$time = '-' . $time;
}
return $time;
}
for
$seconds= -41880
result
$time = -11:38:00
wich is correct
but for
$seconds = 100380
result is now
$time : 03:53:00
which is now wrong
Does someone have the clue which functions i need and modified so that it is working correct for positive and negative values
gmdate() (and the other date-time functions as well) represents the number of seconds passed as argument as a date, not as a number of hours, minutes and seconds. It never returns a value greater than 23 for h and so on.
Combine the logic of the two functions: use the code of secToHR() to format the absolute value of its argument and the logic of secToHR2() to handle the sign.
function secToHR($seconds)
{
// Separate the sign and the absolute value of $seconds
$sign = '';
if ($seconds < 0) {
$sign = '-';
$seconds = -$seconds;
}
// Compute the components
$secs = $seconds % 60;
$minutes = ($seconds - $secs) / 60;
$mins = $minutes % 60;
$hours = ($minutes - $mins) / 60;
// P
return sprintf('%s%02d:%02d:%02d', $sign, $hours, $mins, $secs);
}
The easiest thing to do is to
extract any negative sign
call your function that's only defined for positive values (secToHR)
reinsert the negative sign if appropriate

PHP time elapsed, remove "and" before seconds

So, I've got this working code which converts a MySQL date to UNIX Timestamp and subtracts it from the current date() to show a "time elapsed since X"-like timer. (the part which takes the date from database is missing since it's in another script)
<?php
function time_elapsed($secs){
$bit = array(
' year' => $secs / 31556926 % 12,
' week' => $secs / 604800 % 52,
' day' => $secs / 86400 % 7,
' hour' => $secs / 3600 % 24,
' minute' => $secs / 60 % 60,
' second' => $secs % 60
);
foreach($bit as $k => $v){
if($v > 1)$ret[] = $v . $k . 's';
if($v == 1)$ret[] = $v . $k;
}
array_splice($ret, count($ret)-1, 0, 'and');
$ret[] = 'ago.';
return join(' ', $ret);
}
$nowtime = time() + 10; //add 10s to avoid error
$oldtime = strtotime($mysqltime2);
$time_elapsed = time_elapsed($nowtime-$oldtime)."\n";
echo wordwrap($time_elapsed,35,"<br />\n"); //split long line
?>
I managed to fix an error reporting missing array or something if the script was executed at the same time of the MySQL date by adding 10 seconds to the current timestamp.
Another issue I have is that the script shows "and X seconds" even if there aren't minutes/hours/days/etc before it.
E.g.
"and X seconds"
"Y minutes and X seconds"
"Z hours Y minutes and X seconds"
"N days Z hours Y minutes and X seconds"
I want to remove the "and" before seconds ONLY if there's no minutes/hours/etc before it.
Any tip on how to fix this?
You could only splice when needed:
if( count($ret) > 1 ) {
array_splice($ret, count($ret)-1, 0, 'and');
}
Not sure if this will help, but why not do most of the date maths in mysql?
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Here is something I did before to list posts in a comments section of a site, it outputs "post made 2 hours ago" etc
SQL:
UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(made_on) as madeon
PHP (pass madeon from query to here):
function seconds_to_textual_time_ago($seconds)
{
$hour = 60* 60;
$day = 24 * $hour;
$month = 30 * $day;
$year = 365 * $day;
switch(true)
{
case ($seconds < 60) :
$time_ago = "Less than 1 minute ago";
break;
case ($seconds >= 60 && $seconds < $hour):
$minutes = floor($seconds /60);
if ($minutes > 1)
$time_ago = "$minutes minutes ago";
else
$time_ago = "1 minute ago";
break;
case ($seconds >= $hour && $seconds < $day):
$hours = floor($seconds /$hour);
if ($hours > 1)
$time_ago = "$hours hours ago";
else
$time_ago = "1 hour ago";
break;
case ($seconds >= $day && $seconds < $month):
$days = floor($seconds /$day);
if ($days > 1)
$time_ago = "$days days ago";
else
$time_ago = "1 day ago";
break;
case ($seconds >= $month && $seconds < $year):
$months = floor($seconds /$month);
if ($months > 1)
$time_ago = "$months months ago";
else
$time_ago = "1 month ago";
break;
case ($seconds >= $year ):
$years = floor($seconds /$year);
if ($years > 1)
$time_ago = "$years years ago";
else
$time_ago = "1 year ago";
break;
default:
break;
}
return $time_ago;
}
The simplest I can think of is
$time_elapsed = time_elapsed($nowtime-$oldtime))."\n";
if($nowtime-$oldtime < 61){
$time_elapsed=str_replace('and ',' ',$time_elapsed);
}

Formatting seconds to a readable format [duplicate]

This question already has answers here:
Convert seconds into days, hours, minutes and seconds
(29 answers)
Closed 9 years ago.
I know about the date and gmdate functions, but my needs are different in this case.
I have a number of seconds which I need to convert to something like:
A days B hours C minutes D seconds
I don't know how to format my seconds like this.
Any help would be appreciated.
Just use floor and the values 86400 (seconds in a day - 60 * 60 * 24), 3600 (seconds in an hour - 60 * 60) and 60 (seconds in a minute):
<?php
function secondsToTime($seconds) {
$days = floor($seconds / 86400);
$seconds -= ($days * 86400);
$hours = floor($seconds / 3600);
$seconds -= ($hours * 3600);
$minutes = floor($seconds / 60);
$seconds -= ($minutes * 60);
$values = array(
'day' => $days,
'hour' => $hours,
'minute' => $minutes,
'second' => $seconds
);
$parts = array();
foreach ($values as $text => $value) {
if ($value > 0) {
$parts[] = $value . ' ' . $text . ($value > 1 ? 's' : '');
}
}
return implode(' ', $parts);
}
var_dump(secondsToTime(1234561));
//string(36) "14 days 6 hours 56 minutes 1 second"
?>
DEMO
This can be achieved with Date and Time extension:
Use example:
echo secondsToTime(1234563);
# 14 days, 6 hours, 56 minutes and 3 seconds
Link to the function + Demo.

PHP handle time value over 24:00H

I'm addditioning time value of a schedule.
When The value go over 24:00 I'm begining to have a problem..
Here is a simple example of what i'm trying to do.
$now = strtotime("TODAY");
$time_1 = strtotime('08:00:00') - $now;
$total = $time_1 * 5;
$total = $total + $now;
echo date('H:i', $total);
The echo value is 16:00:00
But it should be 40:00:00
24:00:00 + 16:00:00 = 40:00:00
So I understand that this is 1 day and 16 hours.
How can I echo 40:00:00
Below is your example code working the way you want.
As others have mentioned, you have to do the math yourself for cases like this.
<?php
$now = strtotime("TODAY");
$time_1 = strtotime('08:00:00') - $now;
$total = $time_1 * 5;
$secs = $total%60;
$mins = floor($total/60);
$hours = floor($mins/60);
$mins = $mins%60;
printf("%02d:%02d:%02d", $hours, $mins, $secs);
You can't. date() is intended to produce VALID date/time strings. 40 is not something that would appear in a normal time string. You'll have to use math to generate that time string on your own:
$seconds = $total;
$hours = $seconds % 3600;
$seconds -= ($seconds * 3600);
$minutes = $seconds % 60;
$seconds -= ($seconds * 60);
$string = "$hours:$minutes:$seconds";
The date function is for dates and times, not durations. Since the time is never "40:00", it will never return that string.
You can look into using the DateTimeInterface to get what you want, but it might be simpler just to do the math yourself.
$seconds = $total;
$minutes = (int)($seconds/60);
$seconds = $seconds % 60;
$hours = (int)($minutes / 60);
$minutes = $minutes % 60;
$str = "$hours:$minutes:$seconds";

User friendly countdown to midnight

I have a cron job that runs at midnight which resets all user limits for that day. I want to display something along the lines of Your limits reset in 1 hour 14 minutes to my users. Basically a countdown until midnight (server time).
At the moment I'm using this to find midnight:
strtotime('tomorrow 00:00:00');
which returns a timestamp for when midnight rolls over, but I have no idea how to display a user friendly countdown. Is there a PHP library for this or is this pretty easy without a library?
Simply this gives you left-minutes;
$x = time();
$y = strtotime('tomorrow 00:00:00');
$result = floor(($y - $x) / 60);
But you need to filter $result;
if ($result < 60) {
printf("Your limits rest in %d minutes", $result % 60);
} else if ($result >= 60) {
printf("Your limits rest in %d hours %d minutes", floor($result / 60), $result % 60);
}
Since you're looking for a rough estimate, you could leave out the seconds.
$seconds = strtotime('tomorrow 00:00:00') - now();
$hours = $seconds % 3600;
$seconds = $seconds - $hours * 3600;
$minutes = $seconds % 60;
$seconds = $seconds - $minutes *60;
echo "Your limit will reset in $hours hours, $minutes minutes, $seconds seconds.";
It is quite easy, just a little mathematics along with finding the difference in seconds between then and now.
// find the difference in seconds between then and now
$seconds = strtotime('tomorrow 00:00:00') - time();
$hours = floor($seconds / 60 / 60); // calculate number of hours
$minutes = floor($seconds / 60) % 60; // and how many minutes is that?
echo "Your limits rest in $hours hours $minutes minutes";

Categories