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.
2 Answers 2
The algorithm does not allow for the possibility of a transition from daylight time to standard time or vice versa.
Without knowing the mechanism for obtaining the date and time, it's impossible to say if the algorithm needs to be aware of time zones. In principle, the student could be attending by video conference and be in a different time zone.
If the time and date is obtained from a device belonging to the student, the student may prefer to operate the device on a time zone different from the school. For example, both the student and the school could be located in New York but the student corresponds with people all over the world, so keeps her laptop set to UTC.
Adding to what Gerard has answered, there are some PHP libraries that deal with time very well which you could implement. One example is Carbon.
I would separate out your date comparisons into its own function. May be useful elsewhere and is a little clearer. Everything in your for loop up to your first if statement could be its own function.
You could improve your formatting a little (don't know if copy and pasting into Stack Exchange has caused it) but you can take a look at PSR-2. Naming variables a little clearer will be helpful to you, those reviewing your code and to anybody who may now/in the future work on this code, e.g. mytime_start
doesn't make it clear what time you are talking about, and index
could simply be referred to as the standard i
.
Remember to type hint your parameters and give return values.
Hope this helps a bit!
-
\$\begingroup\$ Like these? 3v4l.org/XDTsI \$\endgroup\$Rubics– Rubics2019年07月28日 04:34:07 +00:00Commented Jul 28, 2019 at 4:34
early
orout
but here It calculate the total hours \$\endgroup\$