I have used a few forms to establish a duration of time that a user has worked as well as get the amount of overtime they have worked. Problem is that I want to know how many hours can be billed in overtime and how many is normal time. Now its rather obvious, subtract overtime from total time,however I used the following script to obtain the time amounts:
$logtime = new CGenRs("SELECT time_id,
profile_id ,
user_number ,
start_time ,
end_time,
description,
exported,ovt_start_time,ovt_end_time, EXTRACT(hour FROM(end_time - start_time)) as diff,EXTRACT(minute FROM(end_time - start_time))as difference,EXTRACT(hour FROM(ovt_end_time-ovt_start_time)) as ovt_diff,EXTRACT(minute FROM(ovt_end_time-ovt_start_time)) as ovt_difference from adapt_profile_time where exported = 'f' order by user_number", $cao);
$logtime->first();
The Extract feature works well to show the times but when I start to subtract its where it gets a bit messy.
$tot_mins = 0;
$ovt_mins = 0;
}
$tot_mins = ($tot_mins + $logtime->valueof('diff') * 60) + $logtime->valueof('difference');
$ovt_mins = ($ovt_mins + $logtime->valueof('ovt_diff') * 60) + $logtime->valueof('ovt_difference');
$total_test= floor(($tot_mins / 60)-($ovt_mins / 60))." hours ".(($tot_mins % 60)-($ovt_mins % 60))." minutes ";
When using the echo $total_test it does the calculation but if the user has worked 7 hours 0 minutes which consists out of 3 hours 40 minutes overtime the result of the above calculation returns 3 hours -40 minutes. Which is wrong.
So where am I going wrong here?
I believe the problem lies with the EXTRACT hours and minutes not working well with the "-" "+" operators. I added a total colum in my table that adds the total time with the overtime (It should be subtracted but I did it to test) I used the following code:
<td><?php echo ($logtime->valueof('diff') + $logtime->valueof('ovt_diff')) . " " . "hours" . " ".(($logtime->valueof('difference') + $logtime->valueof('ovt_difference')))." "."minutes" ?></td>
The result was interesting. If user worked 3 hours 50 minutes of which it all was overtime, the result returned was 6 hours 100 minutes. So the addition is working, its just the values aren't recognized in a time format
As I stated in the comments, it is wise to use the DateTime classes for any date/time actions you want to do. Including getting the difference between times.
Check out this example:
// Create two new DateTime-objects...
$Date1 = new DateTime('2015-10-21T8:00:00');
$Date2 = new DateTime('2015-10-21T18:30:00');
// The diff-methods returns a new DateInterval-object...
$Diff = $Date2->diff($Date1);
// Call the format method on the DateInterval-object
echo $Diff->format('%h:%i');
The output from the code above should be "10:30"
From here on you can simply get the difference between the times and check if it is more then 8 hours. If it is, you can get your amount of overtime.
I eventually got it working. I changed my query to the following:
$logtime = new CGenRs("SELECT time_id,
profile_id ,
user_number ,
start_time ,
end_time,
description,
exported,ovt_start_time,ovt_end_time, EXTRACT(hour FROM(end_time - start_time)) as diff,EXTRACT(minute FROM(end_time - start_time))as difference ,EXTRACT(hour FROM(ovt_end_time-ovt_start_time)) as ovt_diff,EXTRACT(minute FROM(ovt_end_time-ovt_start_time)) as ovt_difference,EXTRACT(EPOCH FROM (end_time - start_time)) as super,EXTRACT(EPOCH FROM (ovt_end_time - ovt_start_time)) as spar FROM adapt_profile_time where exported = 'f' order by user_number", $cao);
$logtime->first();
As you can see I added the EXTRACT Epoch to the query for both the over time and the total work time.
I then added the next piece of code:
<td><?php $epoch_1 = $logtime->valueof('super');
$epoch_2 = $logtime->valueof('spar');
$diff_seconds = $epoch_1 - $epoch_2;
$diff_weeks = floor($diff_seconds / 604800);
$diff_seconds -= $diff_weeks * 604800;
$diff_days = floor($diff_seconds / 86400);
$diff_seconds -= $diff_days * 86400;
$diff_hours = floor($diff_seconds / 3600);
$diff_seconds -= $diff_hours * 3600;
$diff_minutes = floor($diff_seconds / 60);
$diff_seconds -= $diff_minutes * 60;
echo $diff_hours." "."hours ".$diff_minutes." minutes" ?></td>
<td>
And so I got the correct values to display in the table.
That being done I changed the code in my question to the following:
$tot_mins = 0;
$ovt_mins = 0;
$total_mens = ($logtime->valueof('super') /60 ) + ($logtime->valueof('spar')/60);
while (!$logtime->eof()) {
while (!$logtime->eof()) {
if ($curr_userno != $logtime->valueof('user_number')) {
$total_time = floor($tot_mins / 60) . " hours " . ($tot_mins % 60) . " minutes";
$total_ovt = floor($ovt_mins / 60) . " hours " . ($ovt_mins % 60) . " minutes";
$total_test = floor($total_mens/60)." hours ".($total_mens%60). " minutes";
And now its working.The values are adding up perfectly and carrying over when necessary.
Related
Currently i working with the attendance management system.i calculate how many hours work done in employees.i already calculate the how much hours working in day and it store in the mysql database.
$totaltime = (strtotime($time_out) - strtotime($time_in));
$hours = sprintf('%02d', intval($totaltime / 3600));
$seconds_remain = ($totaltime - ($hours * 3600));
$minutes = sprintf('%02d', intval($seconds_remain / 60));
$seconds = sprintf('%02d' ,($seconds_remain - ($minutes * 60)));
$final = '';
if ($time_in == '' || $time_out == '')
{
$final = '';
}
else
{
$final .= $hours.':'.$minutes.':'.$seconds;
}
for example
$time_in = 08:09:57
$time_out = 16:04:50
$final = 07:54:53 (total working hours)
now i want to get the current month total working time for each employee.how do get sum of the $final using php?
sample data of the month_data
Emp_no Date Time_in Time_out Total_hours TranID
23 2019-08-01 07:54:40 16:01:40 08:07:00 1
23 2019-08-02 07:42:35 16:02:53 08:20:18 2
i want get the sum of the Total_hours for related one employee
If you ask me this can be easily done using plain MySQL, no meed for PHP to calculate this.
You could take a look at a query somewhat like this
SELECT SEC_TO_TIME(SUM(`Total_hours`) ) FROM `month_data` GROUP BY `Emp_no`;
there is a simple SUM function which can do this for you, it returns the total time in seconds though.
In order to turn that into readable time you can use the MySQL function SEC_TO_TIME.
edit
If the said column is not a TIME column you can CAST it to be handled as this type of column using CAST() the needed SQL would look something like
SELECT SEC_TO_TIME(SUM(CAST(`Total_hours` AS TIME)) ) FROM `month_data` GROUP BY `Emp_no`;
My suggestion would be to change the column type to TIME though.
edit 2
I was under the assumption that SUM() would be smart enough to convert the time to seconds and come up with the correct sum of the given times.
Not sure why yet but this is not the case, therefore you need to convert the given times to seconds first.
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(`Total_hours`)) ) FROM `month_data` GROUP BY `Emp_no`;
Now I have not tested this but TIME_TO_SEC() seems to accept VARCHAR just fine so need to CAST() the column anymore.
take a look at this:
echo OverallTime($allTimes);
$allTimes = array();
function OverallTime($allTimes) {
$minutes = 0;
foreach ($allTimes as $time) {
list($hour, $minute) = explode(':', $time);
$minutes += $hour * 60;
$minutes += $minute;
}
$hours = floor($minutes / 60);
$minutes -= $hours * 60;
return sprintf('%02d:%02d', $hours, $minutes);
<?php
$total = [
'00:02:55',
'00:07:56',
'01:03:32',
'01:13:34',
'02:13:44',
'03:08:53',
'03: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);
?>
In case this is useful to someone looking for this, this is what I use on my music website. This code gets the duration in seconds of all the songs in an album, adds them up, and returns the total album length in hh mm ss.
$record_id = $this->record->id; <!--variable for record-->
.$query = 'SELECT SUM(duration) FROM #__songs WHERE `record_id` = '. $db->quote( (int) $record_id ); <!--selects the duration of all the songs in the album-->
$db->setQuery($query);
$results = $db->loadResult();
echo gmdate("H:i:s", $results); <!--echo total time in hh mm ss.-->
Not an expert here. If you see something, say something XD
I'm building a check in and out system for my work, the employee can set a start time and after his shift he can set the end time. but here is the problem:
If i start at 17:00 till 23:15 I want to show te result as 6.25 hours worked.
For example 15 minutes (¼ hour) equals .25, 30 minutes (½ hour) equals .50, etc.
Googled a lot of this but i can't find a solution for php.
Someone who can help me with this? :)
Many thanks.
There isn't one function, but the DateTimeInterface (http://php.net/manual/en/class.datetimeinterface.php) provides some tools to help, along with some basic maths:
<?php
const secsInAnHour = 3600;
const minsInAnHour = 60;
const hoursInADay = 24;
const decimalPlaces = 2;
$date1 = new DateTime();
$date2 = new DateTime();
$date1->setTime(17, 00);
$date2->setTime(23, 15);
$diff = $date2->diff($date1);
$convertToHours = $diff->s / secsInAnHour + $diff->i / minsInAnHour + $diff->h + $diff->days * hoursInADay;
$hours = round($convertToHours, decimalPlaces);
// Hours between two dateTimes, to 2 dp.
echo $hours;
You could put this into a function inside your implementation, if you wanted to (with start and end times as args).
I'm currently working with a timekeeping system which computes the sum of the basic hours of the week and deduct certain time if there's a late record.
Given that the employee has a total hours rendered for this week is 45 hours (45:00), and he she/has a total late record for that week of 50 minutes (00:50),
Using, PHP. How can I deduct the late record to the total hours rendered without converting time to decimal? The desired output for the above sample is 44:10 since 00:50 is deducted to 45:00.
I see so your goal is to subtract durations ex.
45:00 - 00:50 = 44:10
1: Create a function that convert them into hours
function convertToHours($duration) {
$duration = explode(':',$duration);
$hours+= (int)$duration[0];
$hours+= (int)$duration[1] / 60;
return $hours;
}
2: Create a funciton thats convert from seconds to duration hours:seconds
function secondsToDuration($seconds) {
$H = floor($seconds / 3600);
$i = ($seconds / 60) % 60;
$s = $seconds % 60;
return sprintf("%02d:%02d:%02d", $H, $i, $s);
}
Convert them into hours using function created
$duration1 = convertToHours("25:00");
$duration2 = convertToHours("00:50");
Then subtract them
$difference = $duration1 - $duration2;
Lastly use the created method which convert them back into duration
$duration = secondsToDuration($difference * 3600);
See Demo here
Hope it helps you
You can convert the string to a date and get the difference.
$d1 = "00:45:00";
$d2 = "00:00:50";
date_default_timezone_set("utc");
$fakedate = '01/01/2017';
$d1 = $fakedate . ' ' . $d1;
$d2 = $fakedate . ' ' . $d2;
$dt1 = new DateTime($d1);
$dt2 = new DateTime($d2);
$diff = $dt1->diff($dt2);
echo $diff->format("%H:%I:%S");
The output will be: 00:44:10
i have this code in php
$minutes = date("i", $time);
$seconds = date("s", $time);
$hours = date("H", $time);
$toMinutes = ($hours*60) + $minutes + ($seconds/60);
$KmPerHour = $distance / ($toMinutes/60);
$MperMin = ($distance*1000) / $toMinutes;
$KmPerMin = 1/($distance/$toMinutes);
$MperSec = 100/(($distance*1000)/($toMinutes*60));
all works except this line
$KmPerMin = 1/($distance/$toMinutes);
basicly calcule the time in minutes in running 1 kilometer (the distance is in kilometers)
but for example
10km in 00:39:00 > 39 mins results 3.9
but it should be 3:54 mins
how i can transform 3.9 to mins?
Try something like this:
$min = 3.9;
$min = floor($min) . ':' . ($min - floor($min)) * 60; //3:54
See demo
3.9 minutes is 3m54s, because nine tenths of a minute is fifty-four seconds.
Use the whole part 3 for minutes.
Multiply the fractional part 0.9 by 60 to get seconds.
The following PHP code:
$min = 3.9;
$intmin = floor($min);
$sec = ($min - $intmin) * 60;
if ($sec < 10) {
echo $intmin.':0'.$sec;
} else {
echo $intmin.':'.$sec;
}
will output:
3:54
You can even use fractional seconds, such as with 3.14159 minutes giving 3:08.4954.
I'd provide the code for handling hours as well but, if it's taking you that long to run a kilometre, you may want to find another exercise regime :-)
As an aside, KmPerMin is the wrong sense for what you're calculating, it should more rightly be called MinPerKm.
This code may help you
<?php
$KmPerMin = 3.9;
$KmPerMin = intval($KmPerMin) + (intval(( ($KmPerMin - intval($KmPerMin))*100 * 60)/100)+1)/100;
echo $KmPerMin; // shows 3.54
?>
to show the $KmPerMin in 3:54 format
echo explode(".",$KmPerMin)[0] . ":" . explode(".",$KmPerMin)[1]; // shows 3:54
I am trying to convert a decimal time into an actual time format with hours and minutes, ie: in xx:xx hours.
My query is:
select SUM(vt.vluchtdec) AS vluchttijddecimal
from tbl_vluchtgegevens vg
left join tbl_vluchttijd vt
on vg.vluchttijddec = vt.vluchttijdID
WHERE vg.vertrekdatum <=NOW();
And I am echoing
. $row['vluchttijddecimal'] .
I have also tried this, but this also still gives me my response in a decimal format:
$result = mysql_query("select SUM(vt.vluchtdec) AS vluchttijddecimal
from tbl_vluchtgegevens vg
left join tbl_vluchttijd vt
on vg.vluchttijddec = vt.vluchttijdID
WHERE vg.vertrekdatum <=NOW();");
while($row = mysql_fetch_array($result))
{
$dec = $row['vluchttijddecimal'];
function
convertTime($dec)
{
// start by converting to seconds
$seconds = $dec * 3600;
// we're given hours, so let's get those the easy way
$hours = floor($dec);
// since we've "calculated" hours, let's remove them from the seconds variable
$seconds -= $hours * 3600;
// calculate minutes left
$minutes = floor($seconds / 60);
// remove those from seconds as well
$seconds -= $minutes * 60;
// return the time formatted HH:MM:SS
return lz($hours).":".lz($minutes).":".lz($seconds);
}
// lz = leading zero
function lz($num)
{
return (strlen($num) < 2) ? "0{$num}" : $num;
}
echo "" .$dec."";
In MS Access I would do something like this:
CInt([vluchttijddecimal]) & ":" & Format([vluchttijddecimal]*60 Mod 60;"00")
But this does not work or I don't know how to do so in MySQL / php.
For anyone that is interested... This is how you would convert decimal time (Where 0.1 == 6 minutes) to hours and minutes (0.2333 == 14 minutes) in MYSQL alone. no PHP is needed. This also accounts for the need to round seconds to minutes.
SELECT CONCAT(FLOOR(timeInDec),':', LPAD(ROUND((timeInDec - FLOOR(timeInDec)) * 60) % 60,2,0)) AS TimeInHoursMinutes
FROM YourTable;
Replace timeInDec with the column name that contains the decimal time you would like to convert.
This will return 0:06 for 0.1000 decimal value so leading zeros are accounted for in single digit minutes.
You can do this in you SQL statement something like this:
SELECT CONCAT(CEIL(mydecimal),':', LPAD(Floor(mydecimal*60 % 60),2,'0')) as formated text
Where mydecimal is your unformatted field name
I think I have calculated your time values... although it was kinda pain.
It appears your "decimal time" is "hours.minutes"? Rather horrible and definitely not a good format: for dealing with time its best to stick to integers that specify either a total of minutes/seconds/hours or whatever granularity you need.
But assuming it is hours.minutes, you should be able to do it like this in PHP:
while($row = mysql_fetch_array($result))
{
$dec = $row['vluchttijddecimal'];
return sprintf("%2d:%2d", floor($dec), floor(($dec - floor($dec))*100));
}
Hopefully I am correct in assuming that you mean, for example that 2.5 hours = 2H 30mins. If so, then your 'time' is a time interval and is best represented by the DateInterval class.
This function will do what you want:-
/**
* Converts a 'decimal time' in the format 1.5hours to DateInterval object
*
* #param Int $decimalTime
* #return DateInterval
*/
function decTimeToInterval($decimalTime)
{
$hours = floor($decimalTime);
$decimalTime -= $hours;
$minutes = floor($decimalTime * 60);
$decimalTime -= ($minutes/60);
$seconds = floor($decimalTime * 3600);
$interval = new \DateInterval("PT{$hours}H{$minutes}M{$seconds}S");
return $interval;
}
echo decTimeToInterval(512.168)->format("%H:%I:%S");
See it working
If you want to add times in the format 'H:i' without converting them to and from decimals, you can do it like this:-
function sumTimes($time1, $time2)
{
list($hours1, $minutes1) = explode(':', $time1);
list($hours2, $minutes2) = explode(':', $time2);
$totalHours = $hours1 + $hours2;
$totalMinutes = $minutes1 + $minutes2;
if($totalMinutes >= 60){
$hoursInMins = floor($totalMinutes/60);
$totalHours += $hoursInMins;
$totalMinutes -= ($hoursInMins * 60);
}
return "$totalHours:$totalMinutes";
}
echo sumTimes('12:54', '100:06') . PHP_EOL;
echo sumTimes('12:54', '100:20') . PHP_EOL;
See it working
This is what I used for my Payroll System:
SELECT If(total_late>0, LPAD(CONCAT(REPLACE(FLOOR(total_late/60) + FORMAT(total_late%60*0.01,2), '.', ':'), ':00'), 8, 0), '00:00:00') FROM MyTable
I multiplied it by 0.01 because my variables are in Seconds. Eg. 60.00 = 1min
I would suggest this to include seconds. It is based on #Richard's solutions. Just notice I've changed CEIL by FLOOR in #Richard's solution.
SET #timeInDec=1.505;
SELECT CONCAT(FLOOR(#timeInDec),':', LPAD(FLOOR(#timeInDec*60 % 60),2,'0'),':', LPAD(FLOOR(MOD(#timeInDec*60 % 60,1)*100),2,0)) as timeInDec;