I'm calculating now the total garnered hours student get in school using php.
(Same concept in getting the total work hours in employee for timesheets)
So I have an array $attendance
where the student check in and out in school.
$attendance = [
"2019-07-01 08:03:00",
"2019-07-01 12:12:00",
"2019-07-01 13:03:00",
"2019-07-01 17:00:00",
];
$schedules is on what time the student should check in and out.
$schedules = [
[
"time_start" => "08:00:00",
"time_end" => "12:00:00",
"in_threshold" => 15,
"out_threshold" => 15
],
[
"time_start" => "13:00:00",
"time_end" => "17:00:00",
"in_threshold" => 15,
"out_threshold" => 15
]
];
The threshold is a minute the student should check in/out if the student check in above threshold it will result to late. (Eg. 08:16:00
checks in. He/she is late )
Code below is for storing time_start and time_end to array which is the basis for time_in and out:
foreach($schedules as $schedule){
// Set time_start and time_end with threshold
$mytime_start[] = date( "H:i:s",
strtotime('+'. $schedule[ 'in_threshold' ] .' minutes',
strtotime ( $schedule[ 'time_start' ]
)));
$mytime_end[] = date( "H:i:s",
strtotime('+'. $schedule[ 'out_threshold' ] .' minutes',
strtotime( $schedule[ 'time_end' ]
)));
// Get time_start and time_end to array
$sched_starts[] = ( $schedule[ 'time_start' ] );
$sched_ends[] = ( $schedule[ 'time_end' ] );
}
Note: The schedule time_start and time_end can be change. Function getClosestTime
will get the closest time of each attendance. It will identify if the logs is for schedule time_start
or time_end
.
function getClosestTime( $array, $date ){
foreach( $array as $day ){
$interval[] = abs(strtotime($date) - strtotime($day));
}
asort($interval);
$closest = key($interval);
return $array[$closest];
}
Get $attendance
by 2. for Punch IN and OUT
for ($index = 0; $index < count($attendance); $index += 2)
Expected the two element of array is in and out.
$date_start = $attendance[$index]; // Punch In
$date_end = $attendance[$index + 1]; // Punch Out
Get only date in $attendance (If the schedule cross midnights)
$to_date_start = date("Y-m-d", strtotime($date_start));
$to_date_end = date("Y-m-d", strtotime($date_end));
Get closest Time for each element in $attendance
$time_start = getClosestTime($mytime_start, date('H:i:s',strtotime($date_start)));
$time_end = getClosestTime($mytime_end, date('H:i:s',strtotime($date_end)));
If there's an instance if the student check in late and the closest time is not the exact time_start
for its time_end
.
if ($time_start > $time_end) {
$time_start = date("Y-m-d", strtotime($date_start));
}
Add dates in schedule time start and time_end
$time_start = date('Y-m-d H:i:s', strtotime("$to_date_start $time_start"));
$time_end = date('Y-m-d H:i:s', strtotime("$to_date_end $time_end"));
Set the exact datetime when the student should check in/out
$time_minus_start = date("Y-m-d H:i:s", strtotime("-15 minutes $time_start"));
$time_minus_end = date("Y-m-d H:i:s", strtotime("-15 minutes $time_end"));
Check check in
if it is above the threshould same logic for check out
if ($date_start > $time_start) {
$start = $late;
$total_late += 1;
}else {
$start = $exact_in;
}
If $attendace
is exact time_start and time_end return its date
if (isBetween($time_minus_start, $time_start, $date_start)
&& isBetween($time_minus_end, $time_end, $date_end)) {
$start = $within_in;
$end = $within_out;
} else if (isBetween($time_minus_start, $time_start, $date_start) && $date_end > $time_end) {
$start = $within_in;
$end = $late_out;
}
Sum check in and check out result
$total_garner_hours += ($end - $start);
In my algorithm:
Student check in early and check out late then $start
/$end
return the exact time student should check in/out.
Student check in late and check out early $start
/$end
return the real-time data.
Here is my live code: https://3v4l.org/9MaEc
I would like to make the code more efficient and reliable. I'm a beginner and I admit it, my code is so messed up.
early
orout
but here It calculate the total hours \$\endgroup\$ – Rubics Jul 24 '19 at 4:52