Rooneyl
Rooneyl

Reputation: 7902

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' hours.

Upvotes: 4

Views: 4016

Answers (5)

HenerH
HenerH

Reputation: 19

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.

Upvotes: 0

user716580
user716580

Reputation:

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";

?>

Upvotes: 1

Javi R
Javi R

Reputation: 2350

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";

Upvotes: 2

Valour
Valour

Reputation: 810

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

Upvotes: 0

&#211;lafur Waage
&#211;lafur Waage

Reputation: 70001

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.

Upvotes: 1

Related Questions