I have a website where users enter data including hours, for example they enter '1:00' (Meaning = 1 hour) and '00:15' (Meaning = 15 minutes) and '2:30' (Meaning = 2 hour and 30 minutes).
Now I need to make show them how many hours they have entered in total, when I calculate it by just doing $count += $time in a loop I am getting the correct number but not what is standing after the ':'.
1:00 + 00:15 + 2:30 will become '3' while it should be 3:45.
How would I do this? Also now that I am thinking about it, I will also need if it goes over 60 it adds 1 to the first number (A new hour).
Thanks.
First, calculates minutes, then calculate how many hours are those minutes and add them to the hours:
<?php foreach ($data as $entry) {
list($hour, $minutes) = explode(':', $entry);
$total_hours += $hour;
$total_minutes += $minutes;
}
$hours_from_minutes = floor($total_minutes / 60);
$total_hours += $hours_from_minutes;
$total_minutes -= $hours_from_minutes * 60;
echo "$total_hours:$total_minutes"
A simple solution that supports everything varying from 00:00:00 to just 00:00 and 00
$times = ['00:15', '01:00:13', '24:43:12', '00:00:34'];
$total_seconds = 0;
$total_minutes = 0;
$total_hours = 0;
foreach ($times as $time) {
$array = explode(':', $time);
switch (sizeof($array)) {
case 3:
$total_seconds += (int) $array[2];
case 2:
$total_minutes += (int) $array[1];
case 1:
$total_hours += (int) $array[0];
break;
default:
throw new Exception('got more than expected!');
}
}
$total_minutes += floor($total_seconds / 60);
$total_seconds %= 60;
$total_hours += floor($total_minutes / 60);
$total_minutes %= 60;
printf('%dh %dm %ds', $total_hours, $total_minutes, $total_seconds);
// upd coz strtotime is not for this Q
Try to use DateIntervals, they may help you.
http://php.net/manual/ru/class.dateinterval.php
Related
I want to get the sum of the time in array. There are a lot of questions asked before related this question. Only problem this solution work the only sum is less than 24 hours. After 24 hours it will start at 00:00:00. How do I get more than 24 hours as total?
<?php
$total = [
'00:02:55',
'00:07:56',
'01:03:32',
'15:13:34',
'02:13:44',
'03:08:53',
'13:13:54'
];
$sum = strtotime('00:00:00');
$sum2=0;
foreach ($total as $v){
$sum1=strtotime($v)-$sum;
$sum2 = $sum2+$sum1;
}
$sum3=$sum+$sum2;
echo date("H:i:s",$sum3);
?>
RESULT
11:04:28
Expected result
35:04:28
DEMO LINK
Try the following code
<?php
function explode_time($time) { //explode time and convert into seconds
$time = explode(':', $time);
$time = $time[0] * 3600 + $time[1] * 60;
return $time;
}
function second_to_hhmm($time) { //convert seconds to hh:mm
$hour = floor($time / 3600);
$minute = strval(floor(($time % 3600) / 60));
if ($minute == 0) {
$minute = "00";
} else {
$minute = $minute;
}
$time = $hour . ":" . $minute;
return $time;
}
$time = 0;
$time_arr = [
'00:02:55',
'00:07:56',
'01:03:32',
'15:13:34',
'02:13:44',
'03:08:53',
'13:13:54'
];
foreach ($time_arr as $time_val) {
$time +=explode_time($time_val); // this fucntion will convert all hh:mm to seconds
}
echo second_to_hhmm($time);
?>
With the external DateTime Extension dt you can add all times to a date.
With DateTime::diff you get the result:
$dt = dt::create("2000-1-1"); //fix Date
$dtsum = clone $dt;
foreach($total as $time){
$dtsum->addTime($time);
}
$diff = $dt->diff($dtsum);
printf('%d:%02d:%02d',$diff->days * 24 + $diff->h,$diff->i,$diff->s);
Output:
35:04:28
Update
Without a DateTime-Extension:
$dt = date_create("2000-1-1"); //fix Date
$dtsum = clone $dt;
foreach($total as $time){
$timeArr = explode(":",$time);
$secondsAdd = $timeArr[0] * 3600 + $timeArr[1] * 60 +$timeArr[2];
$dtsum->modify($secondsAdd." Seconds");
}
$diff = $dt->diff($dtsum);
printf('%d:%02d:%02d',$diff->days * 24 + $diff->h,$diff->i,$diff->s);
Look at what you are doing: using time to make computations ignoring date part.
Maybe considering things in another way : 1 hour = 60 seconds * 60 minutes. So convert all you iterations as seconds, do the sum at the end and write time you need yourself.
Or, or you will use some greater things from php documentation
<?php
$january = new DateTime('2010-01-01');
$february = new DateTime('2010-02-01');
$interval = $february->diff($january);
// %a will output the total number of days.
echo $interval->format('%a total days')."\n";
// While %d will only output the number of days not already covered by the
// month.
echo $interval->format('%m month, %d days');
Adapt to your needs, and I am sure it will work well.
Personally I would completely avoid touching any date functions because you're not working with dates. You could do something like:
// Input data
$data = [
'00:02:55',
'00:07:56',
'01:03:32',
'15:13:34',
'02:13:44',
'03:08:53',
'13:13:54'
];
// Total to hold the amount of seconds
$total = 0;
// Loop the data items
foreach($data as $item):
$temp = explode(":", $item); // Explode by the seperator :
$total+= (int) $temp[0] * 3600; // Convert the hours to seconds and add to our total
$total+= (int) $temp[1] * 60; // Convert the minutes to seconds and add to our total
$total+= (int) $temp[2]; // Add the seconds to our total
endforeach;
// Format the seconds back into HH:MM:SS
$formatted = sprintf('%02d:%02d:%02d', ($total / 3600),($total / 60 % 60), $total % 60);
echo $formatted; // Outputs 35:04:28
So we loop the items in the input array and explode the string by the : to get an array containing hours, minutes and seconds in indexes 0, 1, and 2.
We then convert each of those values to seconds and add to our total. Once we're done, we format back into HH:MM:SS format
I am building an online timesheet for employees. At the end of the timesheet I need to show the total hours:mins worked.
I have the hours worked as variables:
$MondaysActual
$TuesdaysActual
$WednesdaysActual
$ThursdaysActual
$FridaysActual
The data held is something like 07:20 - the employee worked 7 hours 20 mins
How can I simply add these 5 times together and show the total as hrs:mins?
Try this
$times = array();
$times[] = "12:59";
$times[] = "0:58";
$times[] = "0:02";
// pass the array to the function
echo AddPlayTime($times);
function AddPlayTime($times) {
$minutes = 0; //declare minutes either it gives Notice: Undefined variable
// loop throught all the times
foreach ($times as $time) {
list($hour, $minute) = explode(':', $time);
$minutes += $hour * 60;
$minutes += $minute;
}
$hours = floor($minutes / 60);
$minutes -= $hours * 60;
// returns the time already formatted
return sprintf('%02d:%02d', $hours, $minutes);
}
php sum variable in while loop
I have to "sum" variable's values in while, here us my example :
while($row = mysql_fetch_array($result)){
$working_hour= $row[working_hour];
}
The code above will output if I put echo $working_hour; for example:
01:00:03, 01:03:04, 01:10:15
I want something like : sum($working_hour) or array_sum($working_hour) to count all the results of while loop. So, that i want to count: 01:00:03, 01:03:04, 01:10:15= 03:13:22
I try this way :
$total_working_hour=’00:00:00’;
while($row = mysql_fetch_array($result)){
$working_hour= $row[working_hour];
$total_working_hour+= $working_hour;
}
Echo $total_working_hour;
The code above provide output as:
03
How can I do it with php?
Thanks
$hours=0;$min=0;$sec=0;
while($row = mysql_fetch_array($result)){
$working_hour= $row[working_hour];
$arr=explode(':',$working_hour);
$hours=$hours+$arr[0];
$min=$min+$arr[1];
if($min>60){$hours++;$min=$min-60;}
$sec=$sec+$arr[2];
if($sec>60){$min++;$sec=$sec-60;}
}
echo 'Total working hours='.$hours.':'.$min.':'.$sec;
I used the answer here (how to sum the array time) and created the following function:
function addTime($a, $b) {
$array = [$a, $b];
$totalTimeSecs = 0;
foreach ($array as $time) { // Loop outer array
list($hours,$mins,$secs) = explode(':',$time); // Split into H:m:s
$totalTimeSecs += (int) ltrim($secs,'0'); // Add seconds to total
$totalTimeSecs += ((int) ltrim($mins,'0')) * 60; // Add minutes to total
$totalTimeSecs += ((int) ltrim($hours,'0')) * 3600; // Add hours to total
}
$hours = str_pad(floor($totalTimeSecs / 3600),2,'0',STR_PAD_LEFT);
$mins = str_pad(floor(($totalTimeSecs % 3600) / 60),2,'0',STR_PAD_LEFT);
$secs = str_pad($totalTimeSecs % 60,2,'0',STR_PAD_LEFT);
return "$hours:$mins:$secs";
}
So you can use this and replace
$total_working_hour+= $working_hour;
with
$total_working_hour = addTime($total_working_hour, $working_hour);
The value of $row["working_hour"] is clearly a string. So saying something like "01:00:03" + "01:03:04" clearly makes no sense. PHP assumes that what you meant to do was cast the strings to integers first and then add them together. The result of that is not what you're actually after.
Instead, you want to convert a string like "01:00:03" to an normalized integer value, like number of seconds, that can be added together and then converted back to a string value.
So to get the normalized value of the string as an integer in seconds you need a function like this...
function convertStringToNumSeconds($string) {
list($hours, $minutes, $seconds) = explode(":", $string, 3);
$totalSeconds = 0;
$totalSeconds += $hours * 3600; // There are 3600 seconds in an hour
$totalSeconds += $minutes * 60; // There are 60 seconds in a minute
$totalSeconds += $seconds; // There is 1 second in a second
return $totalSeconds;
}
Then to convert the seconds back to a formatted string you can do the opposite...
function secondsToString($seconds) {
$hours = (int) floor($seconds / 3600);
$seconds -= $hours * 3600;
$minutes = (int) floor($seconds / 60);
$seconds -= $minutes * 60;
return sprintf("%02d:%02d:%02d", $hours, $minutes, $seconds);
}
Now in your loop you can actually do something like this...
$totalWork = 0;
while($row = mysql_fetch_array($result)){
$totalWork += convertStringToNumSeconds($row["working_hour"]);
}
echo secondsToString($totalWork); // You should get your expected result
If the format in your example is fix, you can work with DateTime-Object and Date-Interval as well like this... (for further information to DateInterval, have a look at the PHP-Docu)
$dt = new \DateTime('00:00:00');
foreach ($dbRows as $row) {
$time = $row['working_hour'];
$timeSplit = explode(':', $time);
$interval = new \DateInterval(
'P0Y0DT'.$timeSplit[0].'H'.
$timeSplit[1].'M'.$timeSplit[2].'S'
);
$dt->add($interval);
}
echo $dt->format('H:i:s'); // Output: 03:13:22
I'm taking a total number of minutes and am trying to calculate total hrs & minutes.
If you do:
$elapsed = "6476"; // Trying to get 107:56 (107 hours, 56 min)
if ($elapsed > 60) { $format = "i:s"; }
if ($elapsed > 3600) { $format = "H:i:s"; }
$showdiff = gmdate($format, $elapsed);
The problem with this is it doesn't work for calculations above 23hrs 59min.
So, you can do simple division:
$elapsed = $elapsed / 60; // total hours
Only then you will get a fraction (in this case, 107.933333333). I need to keep this as hours and minutes. Any suggestions?
You should be able to use division (as you've stated) and modulus division to accomplish what you want.
$hours = floor($elapsed / 60);
$minutes = round(($elapsed / 60) % 60);
echo $hours . "hrs " . $minutes . "min";
you could try
$elapsed = $elapsed / 60; // total hours (107.933333333)
$parts = explode(".", $elapsed); // split 107.93333 into 2 parts using the . as a separator
$minutes = $parts[1] // $parts[0] is 107, this will be the .9333
$minutes = $minutes * 60 // = 55.99...
$minutes = round($minutes); // round 55.9999 up to 56
$hours = $parts[0];
echo "$hours hrs $minutes mins";
probably could be written a bit better but my excuse is I'm tired :)
That should give you an idea though and let you do what you need to.
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).