Php 议程中可用时间的算法

Php 议程中可用时间的算法,php,mysql,sql,Php,Mysql,Sql,我真的陷入了这种境地 我有两张桌子: 员工工作计划(存储员工在特定日期工作的开始和结束时间) 雇员的任命 假设我们存储了这些行 员工工作时间表: start | end 10:00 | 18:00 雇员任命: start | end 10:10 | 11:00 11:20 | 12:00 14:30 | 15:20 在这种情况下,我想说明可用时间是: 10:00 | 10:10 11:00 | 11:20 12:00 | 14:30 15:20 | 18:00 有没有一种通过SQL实现

我真的陷入了这种境地

我有两张桌子:

  • 员工工作计划(存储员工在特定日期工作的开始和结束时间)
  • 雇员的任命
假设我们存储了这些行

员工工作时间表:

start | end
10:00 | 18:00
雇员任命:

start | end
10:10 | 11:00
11:20 | 12:00
14:30 | 15:20
在这种情况下,我想说明可用时间是:

10:00 | 10:10
11:00 | 11:20
12:00 | 14:30
15:20 | 18:00
有没有一种通过SQL实现的方法?我曾尝试用php实现,但至今没有成功


任何帮助都将不胜感激。

我可以用PHP为您提供解决方案,但如果您能在SQL中找到一些东西,当然会更快

//given you selected $employee_working_schedule
$dayStart = DateTime::createFromFormat('h:i',$employee_working_schedule['start']);
$dayEnd = DateTime::createFromFormat('h:i',$employee_working_schedule['end']);

//then assuming your query statement is named $timeQuery and use PDO 
$nextFreeStart = $dayStart;
$newFreeEnd = null;
$freeTime = array();//here we will store the free time intervals
while($times = $timeQuery->fetch(PDO::FETCH_ASSOC)){
    $nextFreeEnd = DateTime::createFromFormat('h:i',$times['start']);
    $freeTime[] = $nextFreeEnd->diff($nextFreeStart);
    $nextFreeStart = DateTime::createFromFormat('h:i',$times['end']);
}
$freeTime[] = $dayEnd->diff($nextFreeStart); //close the day

策略:收集所有起始点,找到每个起始点各自的端点,然后丢弃不符合要求的行

这是用MySQL编写的想法(未经测试):


下面是一种在纯PHP中执行此操作的方法:

class TimeSpan {

  function __construct($start, $end) {
    $this->start = $start;
    $this->end = $end;
  }

  function starttime() {
    list($hour, $minute) = explode(":", $this->start);
    return (int)$hour * 60 + (int)$minute;
  }

  function endtime() {
    list($hour, $minute) = explode(":", $this->end);
    return (int)$hour * 60 + (int)$minute;
  }

}

function convert_to_time($minutes) {
  $hour = (int) ($minutes / 60);
  $minutes = $minutes % 60;
  return str_pad($hour, 2, '0', STR_PAD_LEFT) . ':' . str_pad($minutes, 2, '0', STR_PAD_LEFT);
}

function open_times($shift, $appointments) {
  $alltimes = array_fill_keys(range($shift->starttime(), $shift->endtime()), 1);
  foreach ($appointments as $appt) {
    $alltimes = array_diff_key($alltimes, array_fill_keys(range($appt->starttime() + 1, $appt->endtime() - 1), 1));
  }
  $groups = array();
  $active_group = 0;

  $output = array();
  $output_counter = 0;
  $nums = array_keys($alltimes);
  foreach( $nums as $k => $num ) {
      if( $k !== 0 && $nums[$k] !== $nums[$k-1]+1 ) $active_group ++;
      $groups[ $active_group ][] = $num;
  }

  foreach( $groups as $group ) {
      $first = array_shift( array_values($group) );
      $output[$output_counter][] = $first;
      $last = array_pop( array_values($group) );
      if( $first !== $last )
          $output[$output_counter][] = $last;
      $output_counter++;
  }
  foreach ($output as &$span) {
    $span[0] = convert_to_time($span[0]);
    $span[1] = convert_to_time($span[1]);
  }
  return $output;
}

$shift = new TimeSpan("10:00", "18:00");
$appointments = array(
        new TimeSpan("10:10", "11:00"),
        new TimeSpan("11:20", "12:00"),
        new TimeSpan("14:30", "15:20"),
      );

print_r(open_times($shift, $appointments));
输出

Array
(
    [0] => Array
        (
            [0] => 10:00
            [1] => 10:10
        )

    [1] => Array
        (
            [0] => 11:00
            [1] => 11:20
        )

    [2] => Array
        (
            [0] => 12:00
            [1] => 14:30
        )

    [3] => Array
        (
            [0] => 15:20
            [1] => 18:00
        )

)

员工约会中的间隔是否不连续?我不知道你的意思。但是员工约会中的列是:员工id、日期、开始、结束谢谢!那对我来说太完美了。
Array
(
    [0] => Array
        (
            [0] => 10:00
            [1] => 10:10
        )

    [1] => Array
        (
            [0] => 11:00
            [1] => 11:20
        )

    [2] => Array
        (
            [0] => 12:00
            [1] => 14:30
        )

    [3] => Array
        (
            [0] => 15:20
            [1] => 18:00
        )

)