PHP subtracting Time getting negative results - php

I want to get the Time in and Time out then get the rendered hours, minutes and seconds but im having a problem on subtracting time here is a sample result
Time in: 10:00:33
Time out: 10:01:30
Total Hours rendered: 0
Total Minutes rendered: 1
Total Seconds rendered: -3
in the sample above it returns 1 minute already even though its not 1 minute yet and in the seconds it returns a negative value
here is my code
$time_out = date("H:i:s");
$nerd->time_out = $time_out;
$time_o = explode(":", $time_out);
$time = explode(":", $nerd->time_in);
$hours = $time_o[0] - $time[0];
$minutes = $time_o[1] - $time[1];
$seconds = $time_o[2] - $time[2];
if($minutes < 2){
$minutes_r = 0;
}else if($minutes <= 15){
$minutes_r = 15;
}else if($minutes <= 30){
$minutes_r = 30;
}else if($minutes <= 45){
$minutes_r = 45;
}else{
$minutes_r = 0;
}
in my code I explode the time to get values in hours, minutes and seconds.
Can anyone suggest a better way of doing this so there will be no negative results?

add this in middle:
if($seconds < 0) {
$seconds += 60;
$minutes--;
}
if($minutes < 0) {
$minutes += 60;
$hours--;
}

Related

Comparing MYSQL timestamps to retrieve time passed in specific units

Here is a PHP function I have designed, which is supposed to determine the amount of time passed in secs,mins,hours,days,weeks,months, and years - depending upon which bracket it is beneath. However Ive noticed that the values being returned seem to increase faster than actual time (within 30 mins, it outputs "1 weeks ago"). Im wondering if $time is actually in millis? That said, for the first 2 mins it outputs relatively accurate results.
Note: Running on 1and1 host.
Here's the function:
function get_relative_date($conn,$date,$post_id){
#get current timestamp
$q = "SELECT NOW() - INTERVAL 1 HOUR - `timestamp` FROM `posts` WHERE id=".$post_id.";";
# - INTERVAL 1 HOUR added due to server running 1 hour ahead.
$result = mysqli_query($conn,$q);
if ($result != null && $result != false){
$row = mysqli_fetch_array($result,MYSQLI_BOTH);
$time = $row[0]; #time passed since post
$min = 60;
$hour = $min*60;
$day = $hour*24;
$week = $day*7;
$month = $week*4;
$year = $month*12;
if ($time < $min){
return $time." secs ago";
}
if ($time < $hour){
return round(($time / $min))." mins ago";
}
if ($time < $day){
return round(($time / $hour))." hours ago";
}
if ($time < $week){
return round(($time / $day))." days ago";
}
if ($time < $month){
return round(($time / $week))." weeks ago";
}
if ($time < $year){
return round(($time / $month))." months ago";
}
if ($time >= $year){
return round(($time / $year))." years ago.";
}
return false;
}
}
Cheers.
I tried your query out and instead of 2 minutes and 40 seconds (in seconds) I was receiving 240 and instead of 1 hour 3 minutes and 40 seconds (in seconds) I got 10340.
You need this:
SELECT TIME_TO_SEC(TIMEDIFF(NOW(),`timestamp`)) FROM `posts` ...
This will select the time difference in seconds and hopefully give you the desired result.

PHP Countdown timer, when finished +7 days and repeat until certain number has been reached

So here is what I need to do:
Get time from database (don't worry about the database stuff for the moment)
Countdown time in days, hours and minutes
When countdown has reached 0, add 7 days to countdown along with adding 1 to an episode count
repeat multiple times until episode count reaches certain number (set by database, again don't worry to much about the database stuff at the moment) then stop countdown and just echo Aired
Basically its going to countdown to the next episode of a TV show's airing time and show what episode number is next, this will carry on until all the episodes have aired.
Here is what I have currently, it works to a degree but will only +7 days/++episode once, after that the countdown will go into negatives. I've tried while loops and some other things but I haven't had too much luck.
$date = "February 12, 2013 5:06 PM";
$date = strtotime($date);
$remaining = $date - time();
$episode = 0;
if ($remaining < 0) {
++$episode;
$remaining = strtotime("+7 day", $date) -time();
}
$days_remaining = floor($remaining / 86400);
$hours_remaining = floor(($remaining % 86400) / 3600);
$mins_remaining = floor(($remaining % 86400 % 3600) / 60);
if ($episode == 3){
echo "Aired";
} else {
echo "$days_remaining:$hours_remaining:$mins_remaining Ep $episode";
}
Any advice is really appreciated, thanks!
Of course it will go to negative.
After $remaining reaches 0, another 7 days are added to it.
if ($remaining < 0) { // remaining: less than 0 days
++$episode; // episode becomes 1
$remaining = strtotime("+7 day", $date) -time(); // remaining: less than 7 days
}
However, after another 7 days, $remaining is still negative and only 7 days are added to it. Since you haven't saved $episode in a database, it is still 0 according to the code.
$episode = 0; // $episode starts at 0 according to the code
if ($remaining < 0) { // remaining: less than -7 days
++$episode; // episode becomes 1
So it continues to count negative and give you $episode == 1.
You should do this instead:
$date = strtotime("February 12, 2013 5:06 PM");
for ($i = 0; $i < 3; $i++) {
$episodes[$i+1] = strtotime("+". 7*$i ." day", $date);
$remainings[$i+1] = $episodes[$i+1] - time();
}
foreach ($remainings as $key => $remaining) {
if ($remaining > 0) {
$episode = $key;
$days_remaining = floor($remaining / 86400);
$hours_remaining = floor(($remaining % 86400) / 3600);
$mins_remaining = floor(($remaining % 86400 % 3600) / 60);
break;
}
}
if (!isset($episode)){
echo "Aired";
} else {
echo "$days_remaining:$hours_remaining:$mins_remaining Ep $episode";
}

Hide hours and mins if they are zero in the function provided

The function below outputs hours:0 whether the time is <1 hour or mins:0 when mins<1.
How can I show only the variables that are not zero?
Thank you.
function time_difference($endtime){
$hours =date("G",$endtime);
$mins =date("i",$endtime);
$secs =date("s",$endtime);
$diff="'hours': ".$hours.",'mins': ".$mins.",'sec': ".$secs;
return $diff;
}
$end_time =strtotime("+7 hours") - strtotime($entry->pubDate);
$difference = time_difference($end_time);
echo $difference;
Another possible approach:
function time_difference($endtime){
$times=array(
'hours' => date("G",$endtime),
'mins' => date("i",$endtime),
'secs' => date("s",$endtime),
);
//added a "just a moment ago" feature for you
if (intval($times['hours'], 10) == 0
&& intval($times['mins'], 10) == 0) {
return "just a moment ago";
}
$diff='';
foreach ($times as $k=>$v) {
$diff.=empty($diff) ? '' : ',';
$diff.=intval($v, 10) == 0 ? '' : "'$k':$v";
}
return $diff;
}
Use the ? operator.
$diff=($hours > 0) ? "'hours': ".$hours : "";
$diff=$diff.($minutes > 0) ? etc...
For larger time ranges, you'd better use maths instead of using date():
function time_difference($endtime){
// hours can get over 23 now, $endtime is in seconds
$hours = floor($endtime / 3600);
// modulo (%) already rounds down, not need to use floor()
$mins = $endtime / 60 % 60;
// the remainder of $endtime / 60 are seconds in a minute
$secs = $endtime % 60;
// this array holds the hour, minute and seconds if greater than 0
$diff = array();
if ($hours) $diff[] = "'hours': $hours";
if ($mins) $diff[] = "'mins': $mins";
if ($secs) $diff[] = "'sec': $secs";
// join the values with a comma
$diff = implode(',', $diff);
if (!$diff) { // hours, mins and secs are zero
$diff = "just a moment ago";
}
return $diff;
}
The below function would only return hours in the range 0 - 23. If the time exceeds a day, hours become zero:
function time_difference($endtime){
$hours = (int)date("G",$endtime);
$mins = (int)date("i",$endtime);
$secs = (int)date("s",$endtime);
// this array holds the hour, minute and seconds if greater than 0
$diff = array();
if ($hours) $diff[] = "'hours': $hours";
if ($mins) $diff[] = "'mins': $mins";
if ($secs) $diff[] = "'sec': $secs";
// join the values with a comma
$diff = implode(',', $diff);
if (!$diff) { // hours, mins and secs are zero
$diff = "just a moment ago";
}
return $diff;
}
(int) is needed to turn the string returned by date() into a string. "01" becomes 1 and "00" becomes "0" using this.

Converting MP3 duration time

I'm using my iTunes library to get data from about 1,100 mp3s and I'm running into a small issue in getting the duration of the library into minutes and seconds.
$duration = 1893642;
$minutes = bcmod(($duration / 60), 60);
$seconds = bcmod($duration, 60);
echo $minutes.":".$seconds; //returns 0:42
The problem is that this specific MP3 is actually 31:42. Any thoughts on why this isn't working?
$minutes = bcmod(($duration / 60), 60);
is taking the minutes modulo 60. Unless your track is over an hour it will always say 0.
You want it to be
$minutes = floor($duration / 60);
Try this function
function formatTime($secs) {
$times = array(3600, 60, 1);
$time = '';
$tmp = '';
for($i = 0; $i < 3; $i++) {
$tmp = floor($secs / $times[$i]);
if($tmp < 1) {
$tmp = '00';
}
elseif($tmp < 10) {
$tmp = '0' . $tmp;
}
$time .= $tmp;
if($i < 2) {
$time .= ':';
}
$secs = $secs % $times[$i];
}
return $time;
}
Not sure if the following function was available when this question was written, but as it's a question I've been asking myself so here goes.
I used the answer above:
$seconds = bcmod($row{'playtime_seconds'}, 60);
$minutes = floor($row{'playtime_seconds'} / 60);
$hours = floor($minutes / 60);
Which works for the majority of times, but there is no padding - so you can end up with 20:1 when it should be 20:01 - and it's not to good over an hour - one length comes in at length="1:70:9" - so an alternative is to use the "date" function.
<?=date("H:i:s", $duration); ?>
which returns 00:31:42 from that number of seconds
$duration_str = sprintf('%s:%02s:%02s',
floor($duration_int / 3600), // hours
floor($duration_int / 60) - floor($duration_int / 3600) * 60, // minutes
$duration_int % 60); // seconds
The *printf functions provide formatting. In this case the leading zero.
The minutes line is the most complex part, since you have to calculate the hours (duration [s] / 3600 [s/h]), then round down to integer (floor()), then multiply with 60 to transform to minutes, then subtract that from the total number of minutes (duration [s] / 60 [s/m]).
If your durations are shorter than an hour, the code is much simpler:
$duration_str = sprintf('%s:%02s', floor($duration_int / 60), $duration_int % 60);
The result is still correct for a duration greater than 59 minutes, but just not as readable (31560 minutes in the example).

Convert 2010-04-16 16:30:00 to "Tomorrow Afternoon"

Convert 2010-04-16 16:30:00 to "Tomorrow Afternoon" or convert another date to "this afternoon", "next year", "next week wednesday". You get the picture.
Anyone know of a PHP or Javascript library that can do this?
I think you can come a long way with what is said here: Calculate relative time in C#
The logic is there, and it's not too hard to do the javascript equivalent if a solution in a different language suits you.
There might be more elegant solutions out there (look for Natural language formatting), but personally I couldn't find any.
I would suggest calculating the distance from now to the date you're formatting, and using thresholds.
Pseudo solution:
diff = now - date
if (diff < one_day)
format for today
if (diff < two_days)
format for tomorrow
if (diff < one_week)
format using days from now
.
.
.
The comparison will work for both past and future dates, as long as you use compare with the abs value of diff. Display timeunit ago or timeunit from now by checking if diff is positive or negative.
For the morning, afternoon, evening etc. you only need to check for the time of day in the date, and regarding the formatting type you hit, either display the time as numbers (far away), or natural language (recent or near date).
function gett($sam){
$times = time() - $sam;
if ($times == 60){
$times = "a minute ago";
}
if (($times != 1) && ($times < 60) && ($times != 0)){
$times = "$times seconds ago";
}
if ($times == 0){
$times = "less than a second ago";
}
if ($times == 1){
$times = "a second ago";
}
if ($times > 60 && $times < 3600){
$times = ceil($times/60)." minutes ago";
}
if($times == 3600){
$times = "an hour ago";
}
if($times > 3600 && $times < 86400){
$times = ceil($times/3600)." hours ago";
}
if($times == 86400){
$times = "a day ago";
}
if($times > 86400){
$times = ceil($times/86400)." days ago";
}
return $times; }
Usage:
$updated = gett($timestamp);
where $timestamp is pretty self-explanatory..
From this link -> How do I calculate relative time in C#?
function posted(t) {
var now = new Date();
var diff = parseInt((now.getTime() - Date.parse(t)) / 1000);
if (diff < 60) { return 'less than a minute ago'; }
else if (diff < 120) { return 'about a minute ago'; }
else if (diff < (2700)) { return (parseInt(diff / 60)).toString() + ' minutes ago'; }
else if (diff < (5400)) { return 'about an hour ago'; }
else if (diff < (86400)) { return 'about ' + (parseInt(diff / 3600)).toString() + ' hours ago'; }
else if (diff < (172800)) { return '1 day ago'; }
else {return (parseInt(diff / 86400)).toString() + ' days ago'; }
}

Categories