Calculating shift hours worked
I'm am trying to calculate the hours for someone based on the number of hours worked and the time period in which they worked.
For example:
The shift patterns are 07:00 to 15:00 is 'morning', 15:00 to 23:00 is 'afternoons', and 23:00 to 07:00 is 'nights'.
Therefore if I started at 08:00 and finished at 17:30, this would mean that I get paid 7 'morning' hours and 2.5 'afternoon' hour开发者_StackOverflow社区s.
I adapted a piece of code from a project I developed some time ago.
The function 'intersection' calculates the amount of time that overlaps between the two ranges s1-e1 and s2-e2.
Note that all the times are in seconds, and we add 3600*24 seconds when the time is in the next day.
<?php
function intersection($s1, $e1, $s2, $e2)
{
if ($e1 < $s2)
return 0;
if ($s1 > $e2)
return 0;
if ($s1 < $s2)
$s1 = $s2;
if ($e1 > $e2)
$e1 = $e2;
return $e1 - $s1;
}
$start = strtotime("07:00");
$end = strtotime("17:30");
// $end = strtotime("05:30") + 3600*24; // the work ended at 05:30 morning of the next day
$morning_start = strtotime("07:00");
$morning_end = strtotime("15:00");
$afternoon_start = strtotime("15:00");
$afternoon_end = strtotime("23:00");
$night_start = strtotime("23:00");
$night_end = strtotime("07:00") + 3600*24; // 07:00 of next day, add 3600*24 seconds
echo "morning: " . intersection( $start, $end, $morning_start, $morning_end ) / 3600 . " hours\n";
echo "afternoon: " . intersection( $start, $end, $afternoon_start, $afternoon_end ) / 3600 . " hours\n";
echo "night: " . intersection( $start, $end, $night_start, $night_end ) / 3600 . " hours\n";
You could have 3 counters, one for each shift. Then you'd need a way to increment by hour and for each hour you increment. You check if it is within each shift, and if it is within a certain one, then you increment that counter.
In the end, the values of each counter should be the amount you worked in each shift.
This is what I just threw together for fun.
There is much room for improvement and it can be easily extended to provide even more calculations, your imagination is the limit.
The array of shifts can be given named keys for readability, but I chose to remove them since 'night1' and 'night2' make no sense to me :-)
<?php
$shift_data = array(
array(
'rate' => 12.5,
'start' => strtotime('00:00:00'),
'end' => strtotime('07:00:00'),
),
array(
'rate' => 7.55,
'start' => strtotime('07:00:00'),
'end' => strtotime('15:00:00'),
),
array(
'rate' => 10,
'start' => strtotime('15:00:00'),
'end' => strtotime('23:00:00'),
),
array(
'rate' => 12.5,
'start' => strtotime('23:00:00'),
'end' => strtotime('07:00:00') + 86400, // next morning
),
);
function calculateWage($start, $end, $rate) {
$result = array();
$result['time']['seconds'] = $end - $start;
$result['time']['minutes'] = $result['time']['seconds'] / 60;
$result['time']['hours'] = $result['time']['minutes'] / 60;
$result['wages'] = $result['time']['hours'] * $rate;
//print_r($result);
return $result;
}
$shift_start = strtotime('08:00');
$shift_end = strtotime('17:30');
$shift_wages = 0;
foreach ($shift_data as $shift) {
if ($shift['start'] <= $shift_end) {
$start = ($shift_start <= $shift['start']) ? $shift['start'] : $shift_start;
$end = ($shift_end <= $shift['end']) ? $shift_end : $shift['end'];
$shift_wage = calculateWage($start, $end, $shift['rate']);
$shift_wages = $shift_wages + $shift_wage['wages'];
}
}
echo "\nTotal wages for today: $" . number_format($shift_wages, 2, '.', ',') . "\n\n";
?>
Here is another way: (I am assuming the start and end hours in unix timestamp)
- Get the starting and ending day of employee
- Get the work hours by a simple formula: $ending_hour - $starting_hour
- If work hours is more than 8 hours, the employee should get paid for extra.
- To calculate extra hours of next shift: $ending_hour - $next_shifts_starting_hour
My shift times are simplier: 22:00 -> 07:00 = nightwork, 07:00 -> 22:00 = daywork
But I got wrong answer with Javi R version if shifts are like 22:30 -> 08:00 (Result: day = 0 hours, night = 8:30 hours) and 20:00 -> 10:00 (Result: day = 2 hours, night = 9 hours) but right answer with shift time like 23:00 -> 07:00 (Result: day = 0 hours, night = 7 hours).
Sorry about that answer. I don't have enough rep but I need to get it work.
精彩评论