1

時間枠に基づいて、ショップが開いているか閉じているかを示すmySQLテーブルがあります。

 shift table
--------------
 shift_id
 day_of_week    (1-7 : Monday-Sunday)
 open_time      (time, default NULL)
 close_time     (time, default NULL)
 type           (1 || 2)

フィールドタイプの説明: 1は同じ日の最初の時間枠を示し、2はその時間枠が同じ日の2番目の時間枠であることを示します。たとえば、ショップは13:00〜15:00および18:00〜01:00にオープンします。

以下の方法で当日を取得しています。

$jd = cal_to_jd(CAL_GREGORIAN,date("m"),date("d"),date("Y"));
    $day = jddayofweek($jd, 0);

    switch($day){
        case 0:
            $curDay = 7;
        break;
        default:
            $curDay = $day;
        break;
    }
    return $curDay;

以下の方法で現在時刻を取得しています。

$timeString = "%H:%i:%s";
$curTime = mdate($timeString, time());

複雑な例は次のとおりです。
現在の日:月曜日
現在の時刻:02:00。
日曜日の時間枠:15:00〜18:00および21:00〜02:30。
月曜日の時間枠:08:30-15:30。

明らかにシフトはOPENですが、現在の日である月曜日ではなく、日曜日の時間枠に基づいています。

テーブルをクエリする(または必要に応じてテーブルを変更する)ための最良の方法、またはシフトが開いているか閉じているかを特定の日の特定の時間に毎回定義する100%正確な方法は何ですか?

4

3 に答える 3

0
function shop_open(){
    //Get current day
    $day = $this->_get_current_day();

    //Get current time
    $timeString = "%H:%i:%s";
    $ordertime = mdate($timeString, time());
    //Predefine ability to order to false
    $canOrder = false;

    $getShift = $this->db->query("select * from `shop_hours` where `day_of_week` = $day AND !ISNULL(`open_time`) ORDER BY `type`");
    $day_num_rows = $getShift->num_rows();

    switch($day_num_rows){
        case 0: //No records
            $canOrder = false;
            break;

        case 1: //Only 1 timeframe
            foreach($getShift->result() as $row){
                $open_time = $row->open_time;
                $close_time = $row->close_time;
            }

            if($open_time <= $close_time){//Timeframe is within the same day [no overlap]

                if($open_time < $ordertime && $close_time > $ordertime){//Current time is within timeframe
                    $canOrder = true;
                }else{
                    $canOrder = false;
                }

            }else if($open_time > $close_time){//There s your overlap [timframe "catches" the next day]

                if($open_time < $ordertime && '23:59' >= $ordertime){//Check till midnight first
                    $canOrder = true;
                }else{//Check in the previous day

                    if($day == 1){ $previousDay = 7; }else{ $previousDay = $day-1; }

                    $getPrvDayShift = $this->db->query("select * from `shop_hours` where `day_of_week` = $previousDay ORDER BY `type`");
                    $prv_day_num_rows = $getPrvDayShift->num_rows();

                    switch($prv_day_num_rows){
                        case 0://No records
                            $canOrder = false;
                            break;
                        case 1://One record found
                            foreach($getPrvDayShift->result() as $row2){
                                $prv_close_time = $row2->close_time;
                            }

                            if($prv_close_time > $ordertime){ //So if the previous day close time is greater than current, we are good to go
                                $canOrder = true;
                            }else{
                                $canOrder = false;
                            }

                            break;
                        case 2: //2nd record found
                            foreach($getPrvDayShift->result() as $row2){
                                if($row2->type == 2){
                                    $prv_close_time = $row2->close_time;
                                }
                            }
                            if($prv_close_time > $ordertime){ //Same shit, different timeframe within the same day 
                                $canOrder = true;
                            }else{
                                $canOrder = false;
                            }
                            break;
                    }

                }

            }
            break;

        case 2: //Ok now we have to check the case of 2 timeframes together

            for($i=1; $i<3; $i++){
                foreach($getShift->result() as $row){
                    if($row->type == $i){
                        $open_time = $row->open_time;
                        $close_time = $row->close_time;
                    }
                }
                if($open_time <= $close_time){//Again, same day [no overlap]
                    if($open_time < $ordertime && $close_time > $ordertime){//Good to go we are within timeframe
                        $canOrder = true;
                    }else{
                        $canOrder = false;
                    }
                }else if($open_time > $close_time){//There s your overlap
                    //Check till midnight
                    if($open_time < $ordertime && '23:59' >= $ordertime){ $canOrder = true; }
                }
            }

            if(!$canOrder){
                //Now we should check the previous day also if $canOrder is still negative
                if($day == 1){ $previousDay = 7; }else{ $previousDay = $day-1; }
                $getPrvDayShift = $this->db->query("select * from `shop_hours` where `day_of_week` = $previousDay ORDER BY `type`");
                $prv_day_num_rows = $getPrvDayShift->num_rows();

                switch($prv_day_num_rows){
                    case 0:
                        $canOrder = false;
                        break;
                    case 1:
                        foreach($getPrvDayShift->result() as $row2){
                            $prv_close_time = $row2->close_time;
                        }
                        if($prv_close_time > $ordertime){ $canOrder = true; }else{ $canOrder = false; }

                        break;
                    case 2:
                        foreach($getPrvDayShift->result() as $row2){
                            if($row2->type == 2){
                                $prv_close_time = $row2->close_time;
                            }
                        }
                        if($prv_close_time > $ordertime){ $canOrder = true; }else{ $canOrder = false; }
                        break;
                }
            }

            break;
    }
    return $canOrder;
}

$ this-> _ get_current_day()が私の質問です。

もっとエレガントで安全な解決策があるに違いないと思います。

于 2012-12-16T18:12:13.863 に答える
0

翌日までの時間枠とそうでない時間枠を区別するために、24時間を超える時間枠は使用できません。したがって、これらの時間枠の終了時間は、開始時間以下である必要があります。

このクエリは、指定された時間にオープンシフトを見つける必要があります。

SELECT shift_id
FROM shifts
WHERE :curDay = day_of_week   
AND :curTime >= open_time                                -- today
AND (:curTime <= close_time OR close_time <= open_time)  -- shift may end tomorrow
OR :curDay = IF(day_of_week=1,7,day_of_week-1)           -- check yesterday
AND :curTime <= close_time AND close_time <= open_time   -- shift started yesterday

可能であれば、テーブルを変更して、深夜にまたがるシフトを2つのシフトに分割します。1つは24:00に終了し、もう1つは翌日の00:00に開始します。

于 2012-12-16T21:27:46.210 に答える
0

これは私が考えていたものです:

CREATE TABLE Shifts (
  shift_id INT AUTO_INCREMENT PRIMARY KEY,
  start_day CHAR(9) NOT NULL,
  start_time TIME NOT NULL,
  end_day CHAR(9) NOT NULL,
  end_time TIME NOT NULL
) ENGINE = InnoDB;

今考えてみると、本当に必要なのかわかりませんend_day。ただし、以下を使用します。

INSERT INTO Shifts (
  start_day,
  start_time,
  end_day,
  end_time
) VALUES
( LOWER('Sunday'), '15:00:00', LOWER('Sunday'), '18:30:00' ),
( LOWER('Sunday'), '21:00:00', LOWER('Monday'), '26:30:00' ),
( LOWER('Monday'), '12:00:00', LOWER('Monday'), '18:00:00' ),
( LOWER('Tuesday'), '10:00:00', LOWER('Tuesday'), '20:45:00' ),
( LOWER('Wednesday'), '16:00:00', LOWER('Wednesday'), '19:30:00' ),
( LOWER('Thursday'), '10:00:00', LOWER('Thursday'), '17:00:00' ),
( LOWER('Thursday'), '19:00:00', LOWER('Friday'), '25:30:00' ),
( LOWER('Friday'), '16:00:00', LOWER('Saturday'), '24:30:00' ),
( LOWER('Saturday'), '15:00:00', LOWER('Saturday'), '20:00:00' ),
( LOWER('Saturday'), '18:30:00', LOWER('Sunday'), '27:00:00' )

次に、次のようなものを使用できます。

SELECT DAYNAME(NOW()), start_day
FROM Shifts
WHERE (start_day = LOWER(DAYNAME(NOW()))
       AND start_time < CURTIME()
       AND end_time > CURTIME())
   OR (start_day = LOWER(DAYNAME(DATE_SUB(NOW(), INTERVAL 1 DAY)))
       AND start_time < ADDTIME('24:00:00', CURTIME())
       AND end_time > ADDTIME('24:00:00', CURTIME()))

ここでテストできます:

http://sqlfiddle.com/#!2/41a26/34

そして、さまざまなテスト値で試してください。

SELECT DAYNAME(NOW()), start_day
FROM Shifts
WHERE (start_day = LOWER('Friday')
       AND start_time < '01:12:35'
       AND end_time > '01:12:35')
   OR (start_day = LOWER('Thursday')
       AND start_time < ADDTIME('24:00:00', '01:12:35')
       AND end_time > ADDTIME('24:00:00', '01:12:35'))

http://sqlfiddle.com/#!2/41a26/33

于 2012-12-20T22:10:32.220 に答える