php - loop through dates to predict 4on 40ff shift schedule - php

Gooooood evening all...
Edit:
I'm trying to write a php script to output the dates I will work for the remainder of the year if given a specific start date.
For example I start on 2020-05-14 and work for 4 days then take 4 days off.
This continues for the remainder of the year.
I would like to output the dates i will work and think it could probably be done using the php for loop, however i've been thinking of how to do this for too long and can't seem to break through the wall.
The start of my code is this:
<?php
$z = date("z",mktime(0,0,0,05,14,2020));
for($i=$z;$i<=365;$i+=4) {
echo("$i<br>");
}
?>
Any advice would be much appreciated on a possible solution.

You're computing the day of the year (e.g. for 2020-05-14, that would be 134), which is fine for letting your script know when to stop.
However, you're wanting to output dates, where you're currently outputting the day of the year instead.
I think there's an easier way to do what you're trying to accomplish.
<?php
$start = new \DateTime("2020-05-14 00:00:00");
$end = new \DateTime($start->format("Y") . "-12-31 00:00:00");
$four = new \DateInterval("P4D");
$one = new \DateInterval("P1D");
$format = 'Y-m-d';
$date = $start;
while ($date <= $end) {
echo $date->format($format), PHP_EOL;
for ($day = 2; $day <= 4; $day++) {
$date->add($one);
echo $date->format($format), PHP_EOL;
}
$date->add($four);
}

Related

How to loop 2 dates to output like this?

Here's my code that display date with for loop.
Topic: Im creating a script to generate payment due(from to start).
$y = 1;
$period = 3;
$start = date('m/15/Y');
echo "<table>";
echo '<thead><th>From</th>';
echo '<th>To</th></thead>';
for ($y; $y <= $period; $y++) {
$month_mid = date("m/15/Y", strtotime($start));
$month_last = date("m/t/Y", strtotime($start));
echo '<td>'.$month_mid = date("m/t/Y", strtotime($start)).'</td>';
echo '<td>'.$month_last = date("m/15/Y", strtotime($start)).'</td></tr>';
$start = date("m/d/Y",strtotime($start." +1month"));
}
echo '</table>';
output I get:
09/15/2017 09/30/2017
10/15/2017 10/31/2017
11/15/2017 11/31/2017
I want to appear like this:
09/15/2017 09/30/2017
09/30/2017 10/15/2017
10/15/2017 10/31/2017
Im new in date php hope you can help me with this thanks.
Here you go:
$y = 1;
$period = 5;
$start = date('m/15/Y');
echo "<table>";
echo '<thead><th>From</th>';
echo '<th>To</th></thead>';
for ($y; $y <= $period; $y++) {
$month_mid = date("m/15/Y", strtotime($start));
$month_last = date("m/t/Y", strtotime($start));
echo '<tr><td>'.$month_mid = date("m/t/Y", strtotime($start)).'</td>';
echo '<td>'.$month_last = date("m/15/Y", strtotime($start)).'</td></tr>';
$start = date("m/d/Y",strtotime($start." +1month"));
}
echo "</table>";
You missed the opening and clousure of table and <tr>.
You don't want to be skipping ahead by a month in your loop. Well, not the way you are doing it here.
You should use DatePeriod::getEndDate and DatePeriod::getStartDate, along with DateTime::add to skip by semi-monthly amounts. The idea is that you only get to the next month by letting the datetime API add 15 days to a given start date, and use that to figure out the mid-month and end-month dates.
Keep everything in these date objects until you need to format and print them, and save the second one in the pair as input for the next round of the loop at the end where you just have to calculate the new second value.
I feel like you could write a function that gets the "next" date from any other first or last date of the month to simplify the loop.
(Since this is semi-monthly and not bi-weekly, you can actually just walk the months in your period, hard-coding the 15th for one value and using your end-of-month function for the second. It depends on your requirements and how complicated the API gets.)
Or
For each month in your period, calculated the mid-month (i.e., exactly 15 days from the start of the month) and end-month dates. Save them in a Collection of couplets of some sort.
Write a display routine that takes this Collection and outputs the dates, but saves the previous formatted string made from the second item in the couplet as the first item to be printed (after the first line.)
I actually prefer this one because it separates the presentation from the data abstraction, allowing you freedom to display and format the date how you see fit.
But, at the end of the day (pun not intended, but what a great pun), stop using date strings as input to figure out other dates when you have access to normalized epoch representations. This will only lead to madness.
$y = 1;
$period = 3;
$start = date('m/d/Y');
$end = date('m/t/Y');
echo "<table>";
echo '<thead><th>From</th>';
echo '<th>To</th></thead>';
for ($y; $y <= $period; $y++) {
echo '<tr><td>'.$start.'</td>';
echo '<td>'.$end.'</td></tr>';
$getLast = date('d',strtotime($end));
if($getLast >= 28) {
$start = date("m/t/Y", strtotime($start));
$end = date("m/d/Y", strtotime("+15 day", strtotime($end)));
}else {
$start = date("m/d/Y", strtotime("+15 day", strtotime($start)));
$end = date("m/t/Y",strtotime($end));
}
}
echo "</table>";
Result:
From To
09/15/2017 09/30/2017
09/30/2017 10/15/2017
10/15/2017 10/31/2017

Why does my datetime have trouble with the 31st?

I have the following piece of code on a site I'm working on. It was written by a previous developer, so I am unsure of exactly how to deal with it:
$datetime = new DateTime("$dt_start_ymd +$gap month");
$dt_next = new DateTime("Thursday " . $datetime->format('Y-m-01'));
$dt_next_0 = $dt_next->setTime(02, 00)->getTimestamp();
$dt_next = $dt_next->getTimestamp();
The variable $gap is an incrementing count (1, 2, 3, etc). The code above should output a sequence of dates listing the first thursday for each month for a number of months as indicated by $gap
i.e. 05/07/2017, 03/08/2017, 07/09/2017 (those being the first Thursday of those respective months).
The code works fine on most dates, but for a reason I cannot fathom if it is passed a date that is the 31st of a month (i.e. 2017-05-31) the system breaks and outputs incorrect answers.
I think this code is unnecessarily complicated. In addition, you're in a situation where if the given date is the 31st and you attempt to add 1 month, you're ending up in a situation where it's attempting to find the 31st of the next month, which does not exist except in December->January.
You might want to consider something like
$currentDate = new \DateTime();
$iterations = 10;
for ($i = 0; $i < $iterations; $i++) {
$first_thursday = new \DateTime(
sprintf('first Thursday of %s', $currentDate->format('F Y'))
);
$nextDate = new \DateTime($currentDate->format('Y-m-d'));
$nextDate->add(new \DateInterval('P1M'));
if ($nextDate->format('m') > $currentDate->format('m') + 1) {
$nextDate->sub(new \DateInterval('P1D'));
}
$currentDate = $nextDate;
echo $first_thursday->format('Y-m-d');
}
This will give you the first Thursday in every month for the next 10 months, and I think is much easier to read than the example you gave.
EDIT: I've updated the code so that it doesn't skip out months. See my comment below.

php for loop for date increment each time

I want to loop a date so that every time date is increment by previous date. my code is here. plz reply anyone, thanks in advance
$today = date('Y-m-d');
for($i=1; $i<=4; $i++){
$repeat = strtotime("+2 day",strtotime($today));
echo $rdate = date('Y-m-d',$repeat);
}
I want result as if today is 2016-04-04 than, 2016-04-06, 2016-04-08, 2016-04-10, 2016-04-12.
actually i want to make a reminder date where user enter reminder. lets a user want to add reminder today and want repeat it 5 time after 2days, 3days or what ever he wants, in next comming day. than how i repeat date with for loop.
Try this:
<?php
$today = date('Y-m-d');
for($i=1; $i<=4; $i++)
{
$repeat = strtotime("+2 day",strtotime($today));
$today = date('Y-m-d',$repeat);
echo $today;
}
Output:
2016-04-06
2016-04-08
2016-04-10
2016-04-12
The easiest way is what answer
aslawin
The below example is to go through the date
$begin = new DateTime($check_in);
$end = new DateTime($check_out);
$step = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($begin, $step, $end);
foreach ($period as $dt)
{
<sample code here>
}
You can try this:
$today = date('Y-m-d');
for($i=1; $i<=8; $i++){
if($i%2 == 0){
$repeat = strtotime("+$i day",strtotime($today));
echo $rdate = date('Y-m-d',$repeat);
}
}
Result:
2016-04-06
2016-04-08
2016-04-10
2016-04-12
In this example, you can use $i%2 == 0 with limit <= 8
Use a for loop with base 2, then directly output your dates:
for( $i=2; $i<9; $i=$i+2 )
{
echo date('Y-m-d', strtotime( "+ $i days" )) . PHP_EOL;
}
Result:
2016-04-06
2016-04-08
2016-04-10
2016-04-12
actually i want to make a reminder date where user enter reminder.
lets a user want to add reminder today and want repeat it 5 time after
2days, 3days or what ever he wants, in next comming day. than how i
repeat date with for loop.
I'll help with the above. First of all I will just say I have a huge personal preference towards the DateTime object over simply using date it's more flexible and a hell of a lot more readable in my opinion, so when working with dates I would always suggest using that over date()
So here is some Code:
$date = new DateTime(); // Pretend this is what the User entered. We got it via $_POST or something.
$interval = 2; // Repeat x times at y day intervals. (Not including the initial)
$repeatAmount = 2; // Repeat the reminder x times
for ($i = 0; $i <= $repeatAmount; ++$i) {
echo $date->format('d/m/Y');
$date->modify('+'. $interval .' day');
}
$date = new DateTime()Imagine this is the date the user entered, this is our starting point, our first reminder will at this time.
$interval and $repeatAmount are the interval in days, i.e. I want this to every 2 days and the amount of times you want it to repeat, in our example 2.
for ($i = 0; $i <= $repeatAmount; ++$i) { We want to loop as many times as the user says they want to repeat. Little note ++$i tends to be a very minor performance boost over $i++ in some scenarios, so it is usually better to default to that unless you specifically need to use $i++
echo $date->format('d/m/Y'); Simply print out the date, i'll let you handle the reminder logic.
$date->modify('+' . $interval . ' day'); Increment the dateTime object by the interval that the user has asked for, in our case increment by 2 days.
Any questions let me know.

php days between two dates list

Do you know what the problem is by looking at the code?
I would be happy if you helped me:
list($from_day,$from_month,$from_year) = explode(".","27.09.2012");
list($until_day,$until_month,$until_year) = explode(".","31.10.2012");
$iDateFrom = mktime(0,0,0,$from_month,$from_day,$from_year);
$iDateTo = mktime(0,0,0,$until_month,$until_day,$until_year);
while ($iDateFrom <= $iDateTo) {
print date('d.m.Y',$iDateFrom)."<br><br>";
$iDateFrom += 86400;
}
Date of writing the same problem 2 times
October (31) for writing 2 times in history draws the ends October 30th: (
27.09.2012
28.09.2012
...
26.10.2012
27.10.2012
[[28.10.2012]]
[[28.10.2012]]
29.10.2012
30.10.2012
Your problem is because you have set time to 00:00:00, set it to 12:00:00. That is because the Daylight saving time.
Stop using date() function, use Date and Time classes.
Solution (PHP >= 5.4):
$p = new DatePeriod(
new DateTime('2012-09-27'),
new DateInterval('P1D'),
(new DateTime('2012-10-31'))->modify('+1 day')
);
foreach ($p as $d) {
echo $d->format('d.m.Y') . "\n";
}
Solution (PHP < 5.4)
$end = new DateTime('2012-10-31');
$end->modify('+1 day');
$p = new DatePeriod(
new DateTime('2012-09-27'),
new DateInterval('P1D'),
$end
);
foreach ($p as $d) {
echo $d->format('d.m.Y') . "\n";
}
You have daylight savings time issues. Adding seconds from one timestamp to another is prone to problems around these sorts of edge conditions (leap days can be problematic is well), You should get in the habit of using PHP's DateTime and DateInterval objects. It makes working with dates a snap.
$start_date = new DateTime('2012-09-27');
$end_date = new DateTime('2012-10-31');
$current_date = clone $start_date;
$date_interval = new DateInterval('P1D');
while ($current_date < $end_date) {
// your logic here
$current_date->add($date_interval);
}
My idea for solving this would be something like this;
$firstDate = "27.09.2012";
$secondDate = "31.10.2012";
$daysDifference = (strtotime($secondDate) - strtotime($firstDate)) / (60 * 60 * 24);
$daysDifference = round($daysDifference);
for ($i = 0; $i <= $daysDifference; $i++)
{
echo date("d.m.Y", strtotime('+'.$i.' day', strtotime($firstDate))) . "<BR>";
}
This should solve your problem and be much easier to read (imho). I've just tested the code, and it outputs all dates and no doubles. It also saves you from all the daylight savings inconsistencies.
I don't know where you're from, but it's likely you're hitting daylight saving changeover in your timezone (it's Nov 4th where I live - exactly one week after Oct 28th). You can not rely on a day being exactly 86400 seconds long.
If you loop incrementing with mktime, you should be fine:
list($from_day,$from_month,$from_year) = explode(".","27.09.2012");
list($until_day,$until_month,$until_year) = explode(".","31.10.2012");
$iDateFrom = mktime(0,0,0,$from_month,$from_day,$from_year);
$iDateTo = mktime(0,0,0,$until_month,$until_day,$until_year);
while ($iDateFrom <= $iDateTo)
{
print date('d.m.Y',$iDateFrom)."<br><br>";
$from_day = $from_day + 1;
$iDateFrom = mktime(0,0,0,$from_month,$from_day,$from_year);
}
Even though $from_day will likely be going well over 31, mktime will make the math conversion for you. (ie 32 days in a 31 day month = day 1 of the next month)
EDIT: sorry, I had the incrementation in the wrong place.

Fill Out The Gaps Between Two Times With PHP

I've got to write a loop that should start and end between two times. I know there are many ways to skin this cat, but I'd like to see a real programmers approach to this function.
Essentially I have Wednesday, for instance, that opens at 6:00pm and closes at 10:30pm.
I'm looking to write a loop that will give me a table with all of the times in between those two in 15 minute intervals.
So, I basically want to build a one column table where each row is
6:00pm
6:15pm
7:15pm
etc...
My two variables to feed this function will be the open time and the close time.
Now don't accuse me of "write my code for me" posting. I'll happily give you my hacked solution on request, I'd just like to see how someone with real experience would create this function.
Thanks :)
$start = new DateTime("2011-08-18 18:00:00");
$end = new DateTime("2011-08-18 22:30:00");
$current = clone $start;
while ($current <= $end) {
echo $current->format("g:ia"), "\n";
$current->modify("+15 minutes");
}
Try it on Codepad: http://codepad.org/JwBDOQQE
PHP 5.3 introduced a class precisely for this purpose, DatePeriod.
$start = new DateTime("6:00pm");
$end = new DateTime("10:30pm");
$interval = new DateInterval('PT15M');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $time) {
echo $time->format('g:ia'), PHP_EOL;
}
echo $end->format('g:ia'); // end time is not part of the period
$start = strtotime('2011-08-11 18:00:00');
for ($i = 0; $i < 20; $i++) {
echo date('g:ia', $start + ($i * (15 * 60))), '<br>';
}
I would go with the DateTime functions and increase the time by 15 minutes every loop-turn as long as the current time is lower then the end-time.
EDIT: as user576875 has posted
$start_date = '2019-07-30 08:00:00';
$end_date = '2019-09-31 08:00:00';
while (strtotime($start_date) <= strtotime($end_date)) {
echo "$start_date<br>";
$start_date = date ("Y-m-d H:i:s", strtotime("+1 hours", strtotime($start_date)));
}

Categories