我有给定时间的休息时间和工作时间,如何找到一天中确切的工作时间和一天中的休息时间?
工作时间输入是这样
以前,我以前只有一个场景,例如7月2日,那样的话我将休息时间转换为小时,并直接从工作时间中扣除。
$secondsPerHour = 3600;
// Getting break entries
$breakTimeEntries = TimeEntries::select('start_date', 'start_time', 'end_time', 'hour_type')
->where('hour_type', 'break')
->orderBy('start_date')->get();
$breakDurationPerDayArray = array();
// Looping through all the break entries and getting the break entries for each day
foreach($breakTimeEntries as $breakTimeEntry) {
$startDate = $breakTimeEntry->start_date;
$breakStartTime = $breakTimeEntry->start_time;
$breakEndTime = $breakTimeEntry->end_time;
$breakHours = $breakEndTime - $breakStartTime;
$breakHoursInSeconds = $breakHours/$secondsPerHour;
// Adding the break entry for the day to array
$breakTimePerDayArray[$startDate] = $breakHoursInSeconds;
}
// Getting work entries
$breakTimeEntries = TimeEntries::select('start_date', 'start_time', 'end_time', 'hour_type')
->where('hour_type', 'work')
->orderBy('start_date')->get();
$workAndBreakHoursArray = array();
// Looping through all the work entries and getting the actual work entries for each day
foreach($breakTimeEntries as $breakTimeEntry) {
$workStartTime = $workTimeEntry->start_time;
$workEndTime = $workTimeEntry->end_time;
$workHours = $workEndTime - $workStartTime;
$workHoursInSeconds = $breakHours/$secondsPerHour;
$startDate = $breakTimeEntry->start_date;
// Checking wether the start date is in array
if(in_array($startDate, $breakDurationPerDayArray)) {
$breakHoursInSeconds = $breakDurationPerDayArray[$startDate];
$actualWorkedHours = $workHoursInSeconds - $breakHoursInSeconds;
//To get the worked hours in minutes
$actualWorkedHoursInMins = $actualWorkedHours/$secondsPerHour;
//To get the break hours in minutes
$breakHoursInMin = $breakHoursInSeconds/$secondsPerHour;
$workAndBreakHoursArray[$startDate] = ['worked_hours' => $actualWorkedHoursInMins, 'break_hours' => $breakHoursInMin];
} else {
//To get the worked hours in minutes
$workHoursInMins = $workHoursInSeconds/$secondsPerHour;
$workAndBreakHoursArray[$startDate] = ['worked_hours' => $workHoursInMins, 'break_hours' => 0];
}
}
此刻我没主意了。好的,有人建议最好的处理方法。
预期的产量以小时为单位
[
[2018-07-02] => [Work => 8, Break =>1],
[2018-07-03] => [Work => 8, Break =>1],
[2018-07-04] => [Work => 8, Break =>1],
[2018-07-05] => [Work => 3.5, Break =>0.5],
[2018-07-06] => [Work => 4.5, Break =>0.5],
[2018-07-09] => [Work => 3.5, Break =>0.5],
[2018-07-10] => [Work => 4.5, Break =>0.5]
]
答案 0 :(得分:1)
您标记了Laravel,所以我认为您正在使用它。 它包含Carbon,它是处理与时间相关的所有问题的好工具。 https://carbon.nesbot.com/docs/#Difference
Edit1:这是一个示例,还假设您对条目进行了标准化:
$entries = [
[
'type' => 'work',
'start' => 1310198400,
'end' => 1310230800,
],
[
'type' => 'break',
'start' => 1310212800,
'end' => 1310216400,
],
[
'type' => 'work',
'start' => 1310284800,
'end' => 1310299200,
],
[
'type' => 'break',
'start' => 1310299200,
'end' => 1310302800,
],
[
'type' => 'work',
'start' => 1310302800,
'end' => 1310317200,
],
[
'type' => 'work',
'start' => 1310371200,
'end' => 1310385600,
],
[
'type' => 'break',
'start' => 1310384700,
'end' => 1310387400,
],
[
'type' => 'work',
'start' => 1310387400,
'end' => 1310403600,
]
];
$workEntries = collect();
$breakEntries = collect();
foreach ($entries as $entry)
{
if ($entry['type'] == 'work')
$workEntries->push($entry);
else if ($entry['type'] == 'break')
$breakEntries->push($entry);
}
/*
For each work entry, check if any break entry overlaps.
*/
foreach ($workEntries as $workEntry)
{
$workStart = $workEntry['start'];
$workEnd = $workEntry['end'];
foreach ($breakEntries as $breakEntry)
{
$breakStart = $breakEntry['start'];
$breakEnd = $breakEntry['end'];
$overlapDuration = 0;
if (!Carbon::createFromTimestamp($workStart)->isSameDay(Carbon::createFromTimestamp($breakStart)))
continue;
/*
Check if work and break overlap
Scenario 1:
Break started mid-work
Scenario 2:
Break started before work
*/
if (($breakStart >= $workStart) || ($breakStart < $workStart))
{
if ($breakStart >= $workStart)
$overlapStart = $breakStart;
else if ($breakStart < $workStart)
$overlapStart = $workStart;
/*
Break ends before work ends (or simultaneously)
*/
if ($breakEnd <= $workEnd)
$overlapEnd = $breakEnd;
/*
Break ends after work ends
*/
else
$overlapEnd = $workEnd;
/*
Calculate overlap length
*/
$overlapDuration = $overlapEnd - $overlapStart;
}
/*
Actual time worked that day is time worked - breaks that overlap work periods.
Get human-friendly date (day, month, year), display.
*/
$workDuration = ($workEnd - $workStart - $overlapDuration)/3600;
$date = Carbon::createFromTimestamp($workStart)->toFormattedDateString();
dump("Time worked on $date is $workDuration h.");
}
}
将打印:
"Time worked on Jul 9, 2011 is 8 h."
"Time worked on Jul 10, 2011 is 4 h."
"Time worked on Jul 10, 2011 is 4 h."
"Time worked on Jul 11, 2011 is 3.75 h."
"Time worked on Jul 11, 2011 is 4.5 h."
我认为将每天的数据分组不会造成太大麻烦:)
Edit2:在制作示例之前,我没有注意到您更改了问题,因此请原谅数据不会以您想要的格式显示。同样,使它适合您的需求应该很容易。