如何计算2个时间戳之间午夜之前和之后的小时数

I am working on a time clock application.

When an employee clocks in, the current date & time is saved as a timestamp assigned to the variable $clockin_time. When the employee clocks out, the current date & time is saved as a timestamp assigned to the variable $clockout_time. I then use some math to calculate the duration of time between the two timestamps to see how long that employee has worked between the clockin_time and the clockout_time. All of that is working fine.

Our company's pay periods run Thursday of one week through Thursday of the following week, so Thursday at midnight is the cutoff for the current pay period. However we have employees who work graveyard from 7PM - 5AM. If an employee works 7PM Wednesday night through 5AM Thursday morning, all of the hours worked BEFORE midnight should be added to their previous pay period and all hours worked AFTER midnight should be added to the next pay period.

My question is, if an employee clocks in on Wednesday night and clocks out on Thursday morning, and I have their starting time and ending time as timestamps, how do I figure out how many hours they worked on Wednesday and how many hours they worked on Thursday?

You should definitely check https://carbon.nesbot.com/docs/

Small example from docs:

$mutable = Carbon::now();
$immutable = CarbonImmutable::now();
$modifiedMutable = $mutable->add(1, 'day');
$modifiedImmutable = CarbonImmutable::now()->add(1, 'day');

var_dump($modifiedMutable === $mutable);             // bool(true)
var_dump($mutable->isoFormat('dddd D'));             // string(11) "Saturday 26"
var_dump($modifiedMutable->isoFormat('dddd D'));     // string(11) "Saturday 26"
// So it means $mutable and $modifiedMutable are the same object
// both set to now + 1 day.
var_dump($modifiedImmutable === $immutable);         // bool(false)
var_dump($immutable->isoFormat('dddd D'));           // string(9) "Friday 25"
var_dump($modifiedImmutable->isoFormat('dddd D'));   // string(11) "Saturday 26"
// While $immutable is still set to now and cannot be changed and
// $modifiedImmutable is a new instance created from $immutable
// set to now + 1 day.

$mutable = CarbonImmutable::now()->toMutable();
var_dump($mutable->isMutable());                     // bool(true)
var_dump($mutable->isImmutable());                   // bool(false)
$immutable = Carbon::now()->toImmutable();
var_dump($immutable->isMutable());                   // bool(false)
var_dump($immutable->isImmutable());                 // bool(true)

If you intend to do this in MySQL, then:

select timestampdiff(hour, clockout_time, clockin_time)
from work_sessions;

Gives you the differences in hours. Let's work this out further:

select timestampdiff(hour, clockout_time, date(clockout_time)) as aftermidnight, timestampdiff(hour, date(clockout_time), clockin_time)
from work_sessions;

I did not test this, so, if this gives you an integer value for hours, then you can increase precision by passing minute instead of hour and do your calculations subsequently.

In PHP, assuming you have two datetimes, $clockinTime and $clockoutTime, then

$diff = $clockoutTime->diff($clockinTime);

calculates the difference.

$totalHours = $diff->h;

will get you the total hours.

$afterMidnight = date('H', $date);
$beforeMidnight = $totalHours - $afterMidnight;

and you have the distances in hours.

Note, I did not test any of this code, so if you encounter a problem, please let me know about it.