I am creating a site that utilizes the jquery ui datepicker. I have it where items have different rental lengths. So a car might be 7 days, while a tent might be 3 days.
When the user enters a quantity of items needed, the system checks if the span of days is available and then puts together an array of dates that are already in the system. This array is passed back to the jquery ui datepicker and those dates are blocked out on the calendar.
Here's my problem. If a user picks a date range that is say, 2 days long. from the 2nd to the 4th of the month. Then a user goes back and wants to choose the 1st, obviously if the item is rented on the 2nd then a 1st to 3rd of the month rental ISNT available.
I'm stumped on how to block out days where the full rental length is not available. Here is what I have so far for the code that creates the blocked date array:
$dateArray = array();
foreach($rentals as $rental) {
//Figure out how many days are between the start and end...
$now = strtotime($rental['periodEnd']);
$your_date = strtotime($rental['periodStart']);
$datediff = $now - $your_date;
$daysBetween = floor($datediff/(60*60*24));
$i = 0;
while($i < $daysBetween) {
if($i != 0) {
$date = date('Y-m-d', strtotime($rental['periodStart']. ' + ' . $i . ' days'));
}else {
$date = date('Y-m-d', strtotime($rental['periodStart']));
}
array_push($dateArray, $date);
$i++;
}
}
//Now get rid of duplicates...
$dateArray = array_unique($dateArray);
echo json_encode($dateArray);
I added this exact feature to a website that offered chartered fishing trips. There were a lot more variables involved in my solution, so this may be somewhat broad/vague, but should at least push you in the right direction.
I set up a callback function for Datepicker's beforeShowDay option:
A function takes a date as a parameter and must return an array with [0] equal to true/false indicating whether or not this date is selectable, [1] equal to a CSS class name or "" for the default presentation, and [2] an optional popup tooltip for this date. It is called for each day in the datepicker before it is displayed.
In my callback, I compare the user's current choices (the trip they chose, which can vary from 1/2 to 3 days, and their chosen departure date) with a list of unavailable dates (which I generate dynamically using PHP & json_encode() like yourself).
When the user opens the Datepicker, the callback will fire for every individual day on the currently-displayed calendar. So each day will go through a logic similar to:
Is this day in the past? (Can't charter a trip in the past!)
Is this day already reserved?
How long is this reservation for? Are there any reserved days in the future that conflict with this timeframe?
Note that in my descriptions, this is all front-end / jQuery based -- current chosen values inputted by the user are pulled using $('#item').val(). The callback has no interactions with the back end. You can use ajax in your callback, but I found it to be much much slower. Your mileage may vary.
Also, you should definitely have a back-end solution that does pretty much the same thing, as well. Don't rely on JS to do your filtering.
Hope that gets you on track!
Related
I am trying to write a php solution to calculate the planned end time considering the target in business hours.
It shouldn't consider some days (retrieved from setting saved in db) such as holidays.
Also business hours are retrieved from db (morning_from (8:30am), morning_to (1:00pm), evening_from (2:30pm), evening_to (6:30pm)).
I want to develop this script because I want that my page shows the remaining time for technical resolution of an opened ticket every day.
For example:
customer having contract with 10 working hours SLA opens a ticket
today (friday) 31/01/2020 16:00:00, considering that in the
noBusinessDays = array("saturday", "sunday") and businessHours set as mentioned before(8:30-13:00/14:30-18:30), the result will have to
be monday 3/02/2020 17:30:00.
Code example:
$noBusinessDays = array("saturday", "sunday");
$businessHours = array("morning_from" => "8:30", "morning_to" => "13:00", "evening_from" => "14:30", "evening_to" => "18:30");
$SLA = "10"; //hours
$ticketDate = new DateTime();
$ticketDate->setTimestamp(strtotime("31/01/2020 16:00:00"));
// I don't know how to use my arrays to say in this calculation how to use them
$maximumLimit = $ticketDate->add(new DateInterval("PT" . $SLA ."H"));
Thank you in advance.
You may use the following function
// intersection of 2 time intervals
// input - Unix timestamps (start,end)
// output - intersection in seconds
function time_union($b_1,$e_1,$b_2,$e_2)
{
return max(0,$e_1-$b_1 - max(0,$e_1-$e_2) - max(0,$b_2-$b_1));
}
You will start with an empty time interval [X, Y) where X is the timestamp of the ticket creation and Y initially is equal to X.
Then you start adding days to Y - one by one. Each time you expand the time interval to contain another day - you use the above function to check how much of the SLA hours are covered (i.e. overlapping) with the working hours in the day you have just added. If the day is marked as a holiday - you simple skip it and continue with the next date.
If you find out that SLA hours are partially covered with either the morning or evening business hours - you should simply subtract the extra hours.
In the end Y will be equal to the timestamp that you want to show in your application.
I think I'd break down the problem into pieces. After calculating the total number of days in the interval, first dispose of the trivial case that it's all happening in one week.
begin by calculating the number of "whole weeks." Each "whole week" is five business days. Subtract the corresponding interval of time and proceed. Now, look at the day-of-the-week of the start-date: each day adds a certain number of days. Then the day-of-week of the end date, likewise. You can then consider hour-of-the-day as needed.
Holidays are a simple table: if the day falls within the range, subtract one day.
Now ... having said all of that, the very first thing that I would do is to search GitHub and SourceForge! Because I am extremely sure that somebody out there has already done this. :-D
"Actum Ne Agas: Do Not Do A Thing Already Done."
I am working on a school project where I am keeping track of a user's tweeting frequency per week. I have working code, but at the end of each 1-week period, I need to manually adjust the new starting tweet total and the date of one week in the future.
How can I automate it so the final tweet count becomes the new starting tweet count, and one week gets added to the ending date? Am I heading in the right direction with the code below, or should I be storing these final tweet total values in a database? Thank you!
// Get current tweet total and calculate current count
$ptTotal = $ptObject->{'statuses_count'};
$ptStart = 572;
$ptCount = ($ptTotal-$ptStart);
// Set end date & convert to EST
$ptdatestr="2017-05-30 12:00:00";
$ptdate=strtotime($ptdatestr)+14400;
// Calculate time remaining
$ptdiff=$ptdate-time();
$ptdays=floor($ptdiff/86400);
$pthours=round(($ptdiff-$ptdays*86400)/3600);
// Re-set start value and add one week to countdown
if ($ptdiff <= 0) {
$ptStart = $ptTotal;
$ptdate = $ptDate + 604800;
}
I say regardless of how you are automating this code block (see Alejandro's comment), you should move away from using any approach that includes +86400 (or a factor of). Things will go BONK in the night when daylight savings is involved.
Instead, I recommend that you integrate DateTime objects. They are highly versatile and have specific features that will aid you in your specific project. This is a full list of related functions: http://php.net/manual/en/book.datetime.php
Implementing Datetime objects and functions will make your project solid and lean. Immerse yourself in the above php manual pages and the comments that follow; and continue to research on StackOverflow.
More to your specific questions: Yes, I think you are on the right path. Yes, I think I'd store the data in a database.
Good luck.
I’m struggling on how to design this small application. It’s going to be a table info where the columns will be dates and only 7 dates will be shown at any given time (the current day, plus the next six days).
The user NEEDS to be able to scroll to the left (or right, I suppose) and see previous dates with information that has bee entered for specific dates (ie, user wants to see the # of Service Jobs for February 14th, 2015).
What I have so far:
In this case there are 6 rows of information. The user can go in and edit this information. All of this data needs to be posted to a database, and the dates need to account for the whole year (ie, 1/1 to 12/31) and this has to happen every year. I’ve worked with the x-editable plugin a bit and have had some success, but I’m having a difficult time understanding how to account for all the differernt days of the year (365) and how to incorporate that into a MySQL database.
Current'y the 6 dates you see at the top of the img are shown using Javascript. The little dotted lines below the row values are from the X-editable plugin, and when you update this info it is posted to a database with a timestamp.
So my question is: how in the world do I account for 365 days for the year? It's not like I want 365 columns, each representing one day of the year, that seems crazy. (and the same thing will have to happen for 2016, 2017, etc etc...ongoing data).
I'm not sure if I've been taking the right approach on this. Feel like I'm making it much more painful than it needs to be.
Any input on how to design such an application would be greatly appreciated.
From a high level; I would just use an indexed DATE column.
A quick example:
<?php
$date_start = date('Y-m-d'); // Today
$date_end = date('Y-m-d', strtotime($date_start . ' + 6 days'));
// Assuming you have a PDO DB handler setup at this point...
$stmt = $dbh->prepare('SELECT * FROM `table` WHERE `day` BETWEEN ? AND ? ORDER BY `day` ASC');
$stmt->execute(array($date_start, $date_end));
$res = $stmt->fetchAll();
var_dump($res);
I'm having lots of trouble building an appointment booking site for personal trainers. To understand fully why I'm having so much trouble please be patient and let me explain. I wanted to use this free responsive calendar for the look and feel of my calendar because it's responsive and I like the way it looks, although I'll make some minor alterations to it like color scheme. If you go to the link below you will see a demo of it:
http://tympanus.net/Development/Calendario/index2.html
If you click back on the calendar arrow to November 2012, you will see that certain days have circles on them which indicate that there are events on those days. If you click on the circle a window will come up which is supposed to provide info about the event. The events are fetched from a JSON file whose format is the date for the keys and the values are URLs. When a user clicks on an event instead of the window coming up I want them to be taken to a separate page which will list the available time slots for the trainer on that particular day. Their availability will be based on two things:
1) The schedule that they set for themselves like for instance Mondays, Wednesdays, Fridays from 10am-5pm. I would provide a form on the site where they could set their schedule like this and then save it to a MySQL database and query that database to populate the JSON file.
2) What appointment slots are booked on available days. This is complicated since appointment times can vary. A session can last 15, 30, 45 minutes, 1 hour, 2 hours and 30 minutes, etc. All in 15 minute chunks. So for instance if the session that the user selected is a 1 hour session, I would have to query the schedule of the personal trainer and match that against his appointments booked on every single day and try to figure out where he has 1 hour slots available then show them to the user on a separate page after they've clicked on the calendar date.
I'm having lots of difficulty figuring this out. I can populate the JSON file by querying the schedule of the personal trainer and then using a trick similar to the one below to get all the dates for the next year for a certain day that the trainer is available like for instance Saturday below. Then store that info in the JSON file which will fetch the events for the calendar script:
<?php
$day = 'saturday';
$step = 1;
$unit = 'W';
$start = new DateTime('NOW');
$end = clone $start;
$start->modify($day); // Move to first occurence of day
$end->add(new DateInterval('P1Y')); // Move to 1 year from start
$interval = new DateInterval("P{$step}{$unit}");
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $date) {
echo $date->format('D, d M Y'), PHP_EOL;
echo "<br />";
}
?>
Why would you want to send them to a separate page, when the whole idea of this calendar is to load events inline?
In your json I would only pass the available timeslots for a given day, in order to keep your frontend logic as basic as possible. Figure out serverside what timeslots are still available by walking through that days' events. This is fairly straightforward (sort the appointments, measure the time between the end of event x and the start of event x+1).
Beware of concurrency.
Storing and retrieving schedules and appointments (have you considered recurring appointments too?) can get complicated. You could read up on Martin Fowler, who has an excellent article on modelling schedules and calendars.
In my database, there are some days with data and some without; I have one column with data, and another column with the date and time submitted. So I want to create this calendar. So it will show all the days in the month, and then the days with data will be a hyperlink.
When I click the link, it will show all the data submitted on that day. I would probably use a loop within the first loop. One for month, and then one for displaying each and every day.
However, being that each month of the year has different amount of days and also leap year is a problem, I don't know how to write the conditions.
Any help or guidance is appreciated.
$start = '2009-01-01';
$current = strtotime($start);
while(date('n',$current)==date('n',strtotime($start))) {
// do your stuff here, $current includes the current date.
// the loop will run through the complete month
$current = strtotime(date('Y-m-d',$current) . '+1 day');
}
You'll need to first find out what day of the week the month starts, so you know how many empty boxes to spit out. Then figure out how many days in that month. Then loop through your days, wrapping to the next line after Saturday. Then fill in the rest of the last row with empty boxes.
There's some quite simple (and commented) code that does this here:
http://gitorious.org/wfpl/wfpl/blobs/master/calendar.php
You can use that code without the rest of the framework it's designed for, if you simply rewrite calender_day() (which is called for each cell on the calendar, with it's first parameter telling you what sort of day it is (not in month, has events, eventless) and rewrite calendar_week() which is called at the end of each row.
Or you could just look through for how to do relevant stuff, like find out how far through the week the month starts and such.