Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8088957
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 5, 20262026-06-05T19:14:52+00:00 2026-06-05T19:14:52+00:00

I’m building a simple availability calendar with PHP and MySQL. I have a table

  • 0

I’m building a simple availability calendar with PHP and MySQL.

I have a table which stores the available dates for a property (currently all of them are blocks of 7 days)

available_dates:
    start_date    DATE
    end_date      DATE
    available_id  INT PRIMARY KEY
    property_id   INT
    booked        TINYINT(1)  

And a table of booked dates which references the available_id of my available_dates table:

bookings
    booking_id INT
    available_id INT

    ***user details***

I plan on having rows added to available_dates for each property to mark which dates can be booked, and then setting the booked flag on that table when somebody books that block.

What I’d like to do is show a list of dates (in blocks of x days, 7 in this case) that have no availability set – so the date does not appear in that table – for the next 24 months or so.

I’m having trouble wrapping my head around this and I know there is a simpler way to do it that my first ideas of looping through each property, then each block of 7 days, etc etc.

Can anyone enlighten me?


Update:

Thanks to @ZaneBien ‘s brilliant and comprehensive answer, I’ve managed to get the results I need by using his yeardate table & procedure.
What I’ve done is when the page that needs to show the dates with no availability set is requested, the PHP will call the procedure to add more yeardates if there aren’t any for CURYEAR()+2.

Then to get my results, a slightly modified version of Zane’s query:

SELECT
    a.yeardate AS blockstart,
    DATE_ADD(a.yeardate, INTERVAL 7 DAY) AS blockend
FROM
    yeardates a  
LEFT JOIN
    available_dates b 
        ON(a.yeardate BETWEEN b.start_date AND b.end_date)              
    OR      
    (DATE_ADD(a.yeardate, INTERVAL 7 DAY) BETWEEN b.start_date AND b.end_date)
WHERE
    b.date_id IS NULL AND WEEKDAY(a.yeardate)=5;

In my case, the blocks are of 7 days, saturday to saturday – so I added the second WHERE clause to the query so that I get distinct 1 week saturday to saturday blocks for each row, that happen one after the other.

So instead of:

+------------+------------+
| blockstart | blockend   |
+------------+------------+
| 2012-01-01 | 2012-01-08 |
| 2012-01-02 | 2012-01-09 |
| 2012-01-03 | 2012-01-10 |
| 2012-01-04 | 2012-01-11 |

I get this:

+------------+------------+
| blockstart | blockend   |
+------------+------------+
| 2012-01-07 | 2012-01-14 |
| 2012-01-14 | 2012-01-21 |
| 2012-01-21 | 2012-01-28 |
| 2012-01-28 | 2012-02-04 |

Which is exactly what I need. Thanks again to Zane for a great answer.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-05T19:14:54+00:00Added an answer on June 5, 2026 at 7:14 pm

    Understanding your question as Retrieve all 7 day interval blocks of the current and next year whose ranges do not overlap any interval blocks already existing in the available_dates table:

    To work with all days of the current and next year, we have to create a separate table (yeardates) containing DATEs of all days of the current and next year. This will facilitate our OUTER JOIN operation in the retrieval query.

    Code to define the yeardates table and insert dates:

    CREATE TABLE yeardates 
    (
        yeardate DATE NOT NULL,
        PRIMARY KEY (yeardate)
    ) ENGINE = MyISAM;
    
    DELIMITER $$
    CREATE PROCEDURE PopulateYear(IN inputyear INT)
        BEGIN
            DECLARE i INT;
            DECLARE i_end INT;
            SET i = 1;
            SET i_end = CASE WHEN inputyear % 4 THEN 365 ELSE 366 END;
            START TRANSACTION;
            WHILE i <= i_end DO
                INSERT INTO yeardates VALUES (MAKEDATE(inputyear, i));
                SET i = i + 1;
            END WHILE;
            COMMIT;
        END$$
    DELIMITER ;
    
    CALL PopulateYear(2012);
    CALL PopulateYear(2013);
    

    The table is then created and contains all days of the current and next year. If we ever need to insert days for subsequent years, just CALL the procedure again with the year as the parameter (e.g. 2014, 2015, etc..).

    Then we can get the 7-day blocks that don’t overlap blocks in the available_dates table:

    SELECT
        a.yeardate AS blockstart,
        DATE_ADD(a.yeardate, INTERVAL 7 DAY) AS blockend
    FROM
        yeardates a
    LEFT JOIN 
        available_dates b ON 
            (a.yeardate BETWEEN b.start_date AND b.end_date)
            OR
            (DATE_ADD(a.yeardate, INTERVAL 7 DAY) BETWEEN b.start_date AND b.end_date)
    WHERE
        b.available_id IS NULL
    

    That retrieves all free 7-day blocks based on the bookings of all properties, but if we need to get the free 7-day blocks for just a particular property, we can use:

    SELECT
        a.yeardate AS blockstart,
        DATE_ADD(a.yeardate, INTERVAL 7 DAY) AS blockend
    FROM
        yeardates a
    LEFT JOIN 
        (
            SELECT *
            FROM available_dates
            WHERE property_id = <property_id here>
        ) b ON 
            (a.yeardate BETWEEN b.start_date AND b.end_date)
            OR
            (DATE_ADD(a.yeardate, INTERVAL 7 DAY) BETWEEN b.start_date AND b.end_date)
    WHERE
        b.available_id IS NULL
    

    Where <property_id here> is the property_id. We can even do the selection based on multiple properties at a time by simply changing it to WHERE property_id IN (<comma sep'd list of property_ids here>).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I have just tried to save a simple *.rtf file with some websites and
this is what i have right now Drawing an RSS feed into the php,
I have a text area in my form which accepts all possible characters from
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I want to count how many characters a certain string has in PHP, but
I would like to count the length of a string with PHP. The string
I am trying to understand how to use SyndicationItem to display feed which is
I used javascript for loading a picture on my website depending on which small
I have a jquery bug and I've been looking for hours now, I can't

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.