skip to Main Content

I need a code that calculates the following for me.

Night shift: 22:00:00 – 06:00:00

An employee works from 04:30:00 to 12:00:00. Here the output should be 1.50.
Another employee works from 21:00:00 to 08:00:00. Here the output should be 8.00.
Another employee works from 21:00:00 to 03:30:00. Here the output should be 5.50.

I need the number of hours where the night shift overlaps with the working time.
I’ve also tried ChatGPT, but I can’t get it to work.

How many hours are between 2 periods of time, that overlap?

Do you have an example code in PHP for me?

$check_in = $last_stemp->time;  //21:00:00
$check_out = $_POST['time'];  //07:00:00


$bonusFrom = '22:00:00';
$bonusTo = '06:00:00';

if(strtotime($bonusTo) >= strtotime($check_in)){                    
    $bonus = abs((strtotime($bonusTo) - strtotime($check_in)) / 3600);
}                   
if(strtotime($check_out) >= strtotime($bonusFrom)){                 
    $bonus = abs((strtotime($check_out) - strtotime($bonusFrom)) / 3600);
}

2

Answers


  1. You could try with:

    <?php
    
    $check_in = '04:30:00';
    $check_out = '12:00:00';
    
    checkHours($check_in, $check_out);
    
    $check_in = '21:00:00';
    $check_out = '08:00:00';
    
    checkHOurs($check_in, $check_out);
    
    $check_in = '21:00:00';
    $check_out = '03:30:00';
    
    checkHOurs($check_in, $check_out);
    
    function checkHours($check_in, $check_out) {
        $bonusFrom = '22:00:00';
        $bonusTo = '06:00:00';
        
        // Convert to timestamps
        $check_in_time = strtotime($check_in);
        $check_out_time = strtotime($check_out);
        $bonusFrom_time = strtotime($bonusFrom);
        $bonusTo_time = strtotime($bonusTo);
        
        // If the shift crosses midnight, adjust the check_out time
        if ($check_out_time < $check_in_time) {
            $check_out_time += 86400;
        }
        
        // If the bonus period crosses midnight, adjust the bonusTo time
        if ($bonusTo_time < $bonusFrom_time) {
            $bonusTo_time += 86400;
        }
        
        $overlap = 0;
        
        // Calculate overlap with the current day's bonus period
        if ($check_in_time < $bonusTo_time) {
            $overlap += max(0, min($check_out_time, $bonusTo_time) - max($check_in_time, $bonusFrom_time));
        }
        
        // If the bonus period crosses midnight, calculate overlap with the previous day's bonus period
        if ($bonusFrom_time < $bonusTo_time) {
            $overlap += max(0, min($check_out_time, $bonusTo_time - 86400) - max($check_in_time, $bonusFrom_time - 86400));
        }
        
        $overlap_hours = $overlap / 3600;
        
        echo "Overlap hours: " . $overlap_hours . PHP_EOL;
    }
    
    ?>
    

    Output:

    Overlap hours: 1.5
    Overlap hours: 8
    Overlap hours: 5.5
    
    Login or Signup to reply.
  2. It depends.

    Does the 2100-0800 shift happen to cross a daylight savings boundary? Because then it can be any one of 10, 11, or 12 hours. Eg:

    $shifts = [
        [ '2023-03-11', '2023-03-12' ],
        [ '2023-08-11', '2023-08-12' ],
        [ '2023-11-04', '2023-11-05' ]
    ];
    
    $tz = new DateTimezone('America/Vancouver');
    
    foreach($shifts as $shift) {
        $begin = new DateTime($shift[0] . "T21:00:00", $tz);
        $end   = new DateTime($shift[1] . "T08:00:00", $tz);
        
        var_dump($end->diff($begin)->h);
    }
    

    Output:

    int(10)
    int(11)
    int(12)
    

    Something like this is what you’d want to use if need perfect coverage, your employees are willing to work +/- an hour on daylight savings changes, and you want to track hours/pay them correctly.

    If you want to make sure that the shift is always a 11 hours no matter what, then:

    $days = [
        '2023-03-11',
        '2023-08-11',
        '2023-11-04'
    ];
    
    $shift_start  = '21:00:00';
    $shift_length = new DateInterval('PT11H');
    
    $tz = new DateTimezone('America/Vancouver');
    
    foreach($days as $day) {
        $begin = new DateTime($day . "T" . $shift_start, $tz);
        $end   = (clone $begin)->add($shift_length);
        
        printf("Begin: %s, End: %sn", $begin->format('c'), $end->format('c'));
    }
    

    Output:

    Begin: 2023-03-11T21:00:00-08:00, End: 2023-03-12T09:00:00-07:00
    Begin: 2023-08-11T21:00:00-07:00, End: 2023-08-12T08:00:00-07:00
    Begin: 2023-11-04T21:00:00-07:00, End: 2023-11-05T07:00:00-08:00
    

    Generally it’s helpful to think of "9 o’clock" without a corresponding date to be largely meaningless information. There are so many edge cases and pitfalls to dealing with dates and times that there are robust libraries like PHP’s DateTime to account for them.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search