php Open daily day rage - php

I building restaurant service and currently i'm stuck figuring out how to display open daily restaurant like google Business.
I have table design
+-----+----------+------+----------+----------+
| ref | id_resto | day | open | close |
+-----+----------+------+----------+----------+
| 2 | 5 | 1 | 13:00:00 | 21:00:00 |
| 5 | 5 | 2 | 13:00:00 | 21:00:00 |
| 7 | 5 | 3 | 13:00:00 | 21:00:00 |
| 9 | 5 | 4 | 13:00:00 | 21:00:00 |
| 10 | 5 | 6 | 13:00:00 | 22:00:00 |
| 11 | 5 | 7 | 14:00:00 | 21:00:00 |
+-----+----------+------+----------+----------+
day 7 = sunday, 1 = monday, 2 = tuesday, 3 = Wednesday and soo on
according to my table it should be display
Monday-Thursday 13:00 - 21:00
Saturday 13:00 - 22:00
Sunday 14:00 - 21:00
i've try some algorithm, but noting happened -_-
any idea?
Thanks

With a small change to your table structure, it should be simple to implement.
Here is my code to create the tables:
CREATE TABLE `daytype` (
`id` int(11) NOT NULL,
`description` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `daytype` VALUES (1,'Monday - Thursday'),(2,'Saturday'),(3,'Sunday');
CREATE TABLE `hours` (
`ref` int(11) NOT NULL,
`id_resto` int(11) DEFAULT NULL,
`id_daytypes` int(11) DEFAULT NULL,
`open` char(5) DEFAULT NULL,
`close` char(5) DEFAULT NULL,
PRIMARY KEY (`ref`)
);
INSERT INTO `hours` VALUES (2,5,1,'13:00','21:00'),(5,5,2,'13:00','21:00'),(7,5,3,'14:00','21:00');
From this you can then easily get the data you want with a simple join:
SELECT d.description, CONCAT(open, ' - ', close) as hours FROM test.hours AS h INNER JOIN daytype AS d ON (d.id = h.id_daytypes);
Output:
This structure has the added benefit of allowing you to set up different breaks, and different displays for each of the restaurants, if needed. For example, if a restaurant had different hours on Monday, you could add an entry to the daytypes table for Monday, and Tuesday-Thursday.
Overall, this should save some space since you don't need to enter duplicate info for each of the days that are the same.
Hopefully this will help you get started.
UPDATE: Per request, here is an example of how to check if something is open today.
You could have a php function that returns a comma delimited list of all valid daytypes for the current day. Something like this:
<?php
/*
1 Monday - Thursday
2 Saturday
3 Sunday
4 Friday
5 Monday
*/
function getDayType()
{
$dayOfWeek = date('l');
switch($dayOfWeek)
{
case "Monday":
return "1, 5"
case "Tuesday":
case "Wednesday":
case "Thursday":
return "1";
case "Friday":
return "4":
case "Saturday":
return "2";
case "Sunday":
return "3"
}
}
Then is is simple to determine the shops that are open today.
For example, like this query which will return all the restaurants that are open.
SELECT
h.id_resto
FROM
test.hours AS h
INNER JOIN
daytype AS d ON (d.id = h.id_daytypes)
WHERE
id_daytypes IN (1 , 5)
AND (
(HOUR(NOW()) > HOUR(open) AND HOUR(NOW()) < HOUR(close))
OR
(HOUR(NOW()) = HOUR(open) AND MINUTE(NOW()) >= MINUTE(open))
OR
(HOUR(NOW()) = HOUR(close) AND MINUTE(NOW()) < MINUTE(close))
);

Related

How to check given date period is between two dates in MySQL and PHP

I have a travel history of the employee. I want to check, for the particular month, whether he is in outstation (traveled outside) or in the office, to calculate number of hours in travel. Just we are maintaining the travel database, in that we entered employee name with client place traveled with travel date and returned date.
One employee have the following data:
Traveled date: '2015-08-29' (29th Aug 2015)
returned date: '2015-11-06' (6th Nov 2015)
So here, I want to check in the month of October, all employees that are out of the office. Obviously this guy should come in that category, but I could not get him.
I also tried directly in MySQL workbench, but I didn't get the result.
My original PHP code:
// $req['date_start'] = '2015-10-01'
// $req['date_end'] = '2015-10-31'
$employeeTravel = new EmployeeTravelRecord();
$TravelEntryList = $employeeTravel->Find("(travel_date between ? and ? or return_date between ? and ? )",array($req['date_start'], $req['date_end'],$req['date_start'], $req['date_end']));
$startdate = $req['date_start'];
$enddate = $req['date_end'];
foreach($TravelEntryList as $Travelentry){
$key = $Travelentry->employee;
if($startdate >= $Travelentry->travel_date)
{
$firstdate = $startdate;
}
else
$firstdate = $Travelentry->travel_date;
if($enddate <= $Travelentry->return_date )
{
$lastdate = $enddate;
}
else
$lastdate = $Travelentry->return_date;
$holidays = $this->getholidays($firstdate,$lastdate);
$totalhours = $this->getWorkingDays($firstdate,$lastdate,$holidays); //It returns in total time of outstation in hours excluding company holidays
$amount = $totalhours;
if(isset($TravelTimeArray[$key])){
$TravelTimeArray[$key] += $amount;
}else{
$TravelTimeArray[$key] = $amount;
}
}
But my input data doesn't retrieve that particular employee record, because both traveled date and returned date don't fall in my input dates.
MySQL Workbench:
SELECT * FROM employeetravelrecords where travel_date between '2015-10-01' and '2015-10-31' or return_date between '2015-10-01' and '2015-10-31';
I got only the following result:
+----+----------+---------------+----------------+----------+------------------+------------------+----------------+
| id | employee | type | project | place | travel date | return date | details |
+----+----------+---------------+----------------+----------+------------------+------------------+----------------+
| 13 | 38 | International | PVMTC Training | Hongkong | 11/10/2015 13:33 | 28/11/2015 13:33 | PVMTC Training |
| 14 | 48 | International | PVMT | VIETNAM | 10/10/2015 9:28 | 1/1/2016 9:28 | PETRO |
| 17 | 57 | International | PVMT | Saudi | 10/10/2015 11:39 | 2/1/2016 11:39 | |
+----+----------+---------------+----------------+----------+------------------+------------------+----------------+
The following record didn't get retrieved by this query:
+---+----+---------------+------+-----+-----------------+-----------------+-----------------+
| 7 | 22 | International | MOHO | XYZ | 29/8/2015 18:00 | 6/11/2015 18:00 | FOR DDS review |
+---+----+---------------+------+-----+-----------------+-----------------+-----------------+
SELECT * FROM employeetravelrecords
WHERE
return_date >= '2015-10-01' /* start parameter */
and travel_date <= '2015-10-31' /* end parameter */
The logic seems a little mind-bending at first and I've even reordered the comparisons a little from my original comment above. Think of it this way: you need to return after the start of the range and leave before the end of the range in order to have an overlap.
For a longer explanation and discussion you might find this page useful: TestIfDateRangesOverlap
SELECT '2015-08-29' < '2015-10-31' AND '2015-11-06' >= '2015-10-01' on_leave;
+----------+
| on_leave |
+----------+
| 1 |
+----------+
You can use between for get data between two dates. Here is the working example.
Here is my table structure :
Table User
user_id user_name created_date modified_date
1 lalji nakum 2016-01-28 17:07:06 2016-03-31 00:00:00
2 admin 2016-01-28 17:25:38 2016-02-29 00:00:00
And here is my mysql query :
Query
SELECT * FROM `user` WHERE created_date between '2015-12-01' and '2016-12-31' or modified_date between '2015-12-01' and '2016-12-31'
Result of above query :
Result
user_id user_name created_date modified_date
1 lalji nakum 2016-01-28 17:07:06 2016-03-31 00:00:00
2 admin 2016-01-28 17:25:38 2016-02-29 00:00:00
You want to find all those people who are not available for the complete duration say between T1 & T2 (and T2 > T1). The query you used will only give users whose start date and return date both lie between the given interval which is not the required output.
So to get the desired output you need to check for all employees who have started their journey on or before T1 and return date is on or after T2 (thus unavailable for complete interval [T1, T2]). So the query you can use is:
SELECT * FROM employeetravelrecords where travel_date <= '2015-10-01' and return_date >= '2015-10-31';
If you want employees who are even partially not available between the given duration then we need employees who started their travel before T1 and have any return date later than T1 (thus making them atleast unavailable for a part of the given interval):
SELECT * FROM employeetravelrecords where travel_date <= '2015-10-01' and return_date > '2015-10-01';

Find Upcoming birthdays with Mysql

I want to select the next upcoming birthdays in MYSQL.
My date is stored as: 02/19/1981 and not in a date field. I think it has to sort by day and month and not year but i can not find out how.
How can i do this? This is the query till now:
$sql = "SELECT * FROM wp_postmeta WHERE meta_key='_web_date' ORDER BY ....";
If it's possible for you change the date column to type date.
Otherwise try this:
SELECT month(str_to_date(birthdayColumn, "%m/%d/%Y")) as month, day(str_to_date(birthdayColumn, "%m/%d/%Y")) as day FROM yourTable order by month, day;
Result:
+-------+------+
| month | day |
+-------+------+
| 1 | 12 |
| 2 | 19 |
| 9 | 10 |
| 12 | 15 |
+-------+------+
You can use the php date() function. For example ate('Y-m-d',strtotime("+7 day")); then create a sql query which selects dates which are in the upcoming 7 days
This is a test environment.
CREATE TEMPORARY TABLE `birthdays` (
`id` int(4),
`name` VARCHAR(50),
`dob` CHAR(10)
) ENGINE=MEMORY;
INSERT INTO birthdays VALUES (1,'Alice', '02/19/1951'), (2,'Bob', '09/10/2015'), (3,'Carol', '12/15/2000'), (4,'Doug', '01/12/2011');
I created this function to get the next birthday. The logic may throw some interesting results over 29th Feb / 1st March.
DELIMITER $$
CREATE FUNCTION `next_birth_day`(d_dob DATE) RETURNS DATE
DETERMINISTIC
BEGIN
/* NOTE: this logic ignores the handling of leap years */
/* MySQL will happily construct invalid leap years and they are ordered
between 29/2 & 1/3 in this code. */
DECLARE d_today DATE;
DECLARE d_this_year_bday DATE;
DECLARE d_next_year_bday DATE;
SET d_today = DATE(NOW());
SET d_this_year_bday = CONCAT(YEAR(d_today), '-', MONTH(d_dob), '-', DAY(d_dob));
SET d_next_year_bday = CONCAT(YEAR(d_today)+1, '-', MONTH(d_dob), '-', DAY(d_dob));
RETURN IF( d_this_year_bday < d_today, d_next_year_bday, d_this_year_bday);
END
$$
DELIMITER ;
Then you can do a query and order by next_birth_day:
SELECT *, str_to_date(dob, "%m/%d/%Y") AS dob_dt,
next_birth_day(str_to_date(dob, "%m/%d/%Y")) AS next_bday
FROM birthdays
ORDER BY next_birth_day(str_to_date(dob, "%m/%d/%Y")) ASC
giving results like this:
+------+-------+------------+------------+------------+
| id | name | dob | dob_dt | next_bday |
+------+-------+------------+------------+------------+
| 3 | Carol | 12/15/2000 | 2000-12-15 | 2015-12-15 |
| 4 | Doug | 01/12/2011 | 2011-01-12 | 2016-01-12 |
| 1 | Alice | 02/19/1951 | 1951-02-19 | 2016-02-19 |
| 2 | Bob | 09/10/2015 | 2015-09-10 | 2016-09-10 |
+------+-------+------------+------------+------------+

Get nearest continuous date period MySQL

I have this MySQL table:
| Date | Room | State |
|2015-06-15 | 26 | 1 |
|2015-06-16 | 26 | 1 |
|2015-06-17 | 26 | 1 |
|2015-06-18 | 26 | 1 |
|2015-06-20 | 26 | 1 |
|2015-06-21 | 26 | 0 |
|2015-06-22 | 26 | 0 |
|2015-06-23 | 26 | 1 |
|2015-06-24 | 26 | 0 |
|2015-06-30 | 26 | 1 |
|2015-07-01 | 26 | 1 |
I want to get the first date of the beginning of useful nearest (it means continuous day, State = 1) booking period (for example, 2 days).
How can I do it?
SELECT d.*
FROM dates d
WHERE EXISTS(SELECT `Date`
FROM dates
WHERE `Room` = d.`Room`
AND `Date` = Date_add(d.`Date`, INTERVAL 1 DAY)
AND `State` = 1)
AND d.`State` = 1;
for 2 Days.
SET #days=3;
SELECT d.*
FROM dates d
WHERE (SELECT Count(`date`)
FROM dates
WHERE `Room` = d.`Room`
AND `Date` <= Date_add(d.`Date`, INTERVAL #days - 1 DAY)
AND `Date` >= d.`Date`
AND `State` = 1) >= #days
AND d.`State` = 1;
for dynamic days value.
And the testdata I used:
create table Dates(
`Date` DATE,
`Room` INT DEFAULT 26,
`State` BOOL DEFAULT 0);
INSERT INTO Dates (`Date`,`State`) VALUES
('2015-01-01',1),
('2015-01-02',0),
('2015-01-03',1),
('2015-01-04',1),
('2015-01-05',0),
('2015-01-06',1),
('2015-01-07',1),
('2015-01-08',1),
('2015-01-09',0),
('2015-01-10',1),
('2015-01-11',1),
('2015-01-12',1),
('2015-01-13',1);
The query returns actually all posible dates. To get only one date add a LIMIT 1 at the end of the statement. But maybe it can be help full to get later Startdays that are Possible.
The second query returns with the testdata the following Dates:
2015-01-06 26 1
2015-01-10 26 1
2015-01-11 26 1

MySQL find all periods of given length without related record

I'm making a booking system in PHP/MySQL.
I want to be able to select a month, select a booking length, and find how many periods of the given length are available (ie, not marked as booked) within that month.
I started by creating a table of days, each day has a field that indicates if it's reserved or not, as well as a date. The two tables are:
CREATE TABLE `day` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` date NOT NULL,
`booking` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `booking` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start` date DEFAULT NULL,
`end` date DEFAULT NULL,
PRIMARY KEY (`id`)
)
So far I've been able to count how many days in a month aren't booked - but that doesn't necessarily tell me if say there are 7 days in a row:
SELECT
EXTRACT(YEAR FROM date) as year,
EXTRACT( MONTH FROM date) as month,
count(day.id)
FROM
day
WHERE booking IS NULL
GROUP BY year, month
At this point I'm considering loading all the days for my given month, and iterating through them in PHP to make up my numbers, but it seems kinda dumb and inefficient. Does anyone have a suggestion how I can find this information directly from MySQL?
Assuming you want ranges of at least 7 days in July, 2012, then:
SELECT
DATE_FORMAT(start, '%Y-%m-%d') start,
MAX(days) AS days,
DATE_FORMAT(start + INTERVAL MAX(days) - 1 DAY, '%Y-%m-%d') end
FROM (
SELECT
d2.`date` start,
(#days := IF(IFNULL(d2.booking, 0) = 0, #days + 1, 1)) AS days
FROM
(SELECT #days := 1) a,
day d1
LEFT JOIN
day d2 on d2.`date` = d1.`date` + INTERVAL 1 DAY
WHERE
IFNULL(d1.booking, 0) = 0
) d1
GROUP BY
start
HAVING
(
EXTRACT(YEAR_MONTH FROM start) = 201207 OR
EXTRACT(YEAR_MONTH FROM (start + INTERVAL MAX(days) - 1 DAY)) = 201207
) AND
days >= 7
ORDER BY
start
will produce this output:
| START | DAYS | END |
----------------------------------
| 2012-06-25 | 13 | 2012-07-07 |
| 2012-06-26 | 12 | 2012-07-07 |
| 2012-06-27 | 11 | 2012-07-07 |
| 2012-06-28 | 10 | 2012-07-07 |
| 2012-06-29 | 9 | 2012-07-07 |
| 2012-06-30 | 8 | 2012-07-07 |
| 2012-07-01 | 7 | 2012-07-07 |
| 2012-07-23 | 8 | 2012-07-30 |
| 2012-07-24 | 7 | 2012-07-30 |
The clause
(
EXTRACT(YEAR_MONTH FROM start) = 201207 OR
EXTRACT(YEAR_MONTH FROM (start + INTERVAL MAX(days) - 1 DAY)) = 201207
)
is used to include all ranges, even if the range extends into the previous, or next month. If you want ranges that fall exclusively in a single month, use:
EXTRACT(YEAR_MONTH FROM start) = 201207 AND
EXTRACT(YEAR_MONTH FROM (start + INTERVAL MAX(days) - 1 DAY)) = 201207
See http://sqlfiddle.com/#!2/4e36a/4 for an interactive demo.
You can try this:
SELECT EXTRACT(YEAR_MONTH FROM date) AS year_month, COUNT(*) AS cnt
FROM day
LEFT JOIN booking ON booking.start <= day.date + INTERVAL 6 DAY
AND booking.end >= day.date
WHERE booking.start IS NULL
GROUP BY year_month
The idea is that you're looking for those rows from day where no row from booking overlaps with the 7-day range starting at that day.

Finding the next times in a schedule table where stops are columns and trips are rows

I'm new to PHP, mysql etc. I've done some work in VB and Java, and am reasonably fluent in html.
I'm trying to set up a PHP webpage that looks up train times from a schedule that follows the form:
---------------------------------------------------------
| runId | stop1 | stop2 | stop3 | stop4 | stop5 | stop6 |
---------------------------------------------------------
| 1 | 5:00 | 5:10 | 5:21 | 5:34 | 5:40 | 6:00 |
---------------------------------------------------------
| 2 | 5:30 | 5:40 | 5:51 | 6:04 | 6:10 | 6:30 |
---------------------------------------------------------
| 3 | 6:00 | 6:10 | 6:21 | 6:34 | 6:40 | 7:00 |
---------------------------------------------------------
I then want to query the table knowing the current time and the stop number (column title) for the two entries that occur after the present time. So for example if I was at stop3 and it was 5:00 I would want the query to return $time[1]=5:21, $time[2]=5:51 but I would not want any more results to be returned (e.g. there should be no $time[3] = 6:21 set).
Any help would be greatly appreciated, this is a relatively small project, if it makes any difference to how you would recommend setting up the table.
The table should be like this:
runId stop time
1 1 5:00
1 2 5:10
1 3 5:21
...
2 1 5:30
2 2 5:40
...
create table schedule (runId int, stop int, `time` time);
insert into schedule (runId, stop, `time`) values
(1,1,'05:00'),
(1,2,'05:10'),
(1,3,'05:21'),
(1,4,'05:34'),
(1,5,'05:40'),
(1,6,'06:00'),
(2,1,'05:30'),
(2,2,'05:40'),
(2,3,'05:51'),
(2,4,'06:04'),
(2,5,'06:10'),
(2,6,'06:30'),
(3,1,'06:00'),
(3,2,'06:10'),
(3,3,'06:21'),
(3,4,'06:34'),
(3,5,'06:40'),
(3,6,'07:00')
;
And the query:
sql = "
select runId, stop, `time`
from schedule
where stop = $stop and `time` > current_time
limit 2
;
";

Categories