Add multiple of interval to date until date is in current year - php

suppose I have an initial date whose year was prior to that of the current year and I want to repeat the event every 7 days but only in the current year.
How would I find the first occurrence in the current year?
I realize I can do it with a loop like this:
$reOccurringEvent =new DateTime('2013-12-01');
$interval = new DateInterval('P7D');
while($reOccurringEvent->format('Y') < date('Y') ){
$reOccurringEvent->add($interval);
}
echo $reOccurringEvent->format('d m Y'); //05 01 2014
But it strikes me there should be a more efficient way to achieve this rather than repeatedly adding an interval to the date (it would happen many times if the initial date was some years ago).
I was hoping to be able to calculate the number of times the interval should be added and just do it a single time.
I was thinking something like:
$date = new DateTime();
$diff = $date->diff($reOccurringEvent)->days%7;
But obviously that doesn't work and I can't quite figure out the logic of how to do it.

More generically, the algorithm would be to find the number of intervals between the given date and the last day of last year. Then multiplying the interval by the number of intervals + 1 to get the first interval of the current year.
$date1="12/9/2013";
$ts1 = strtotime($date1);
$ts2 = strtotime("12/31/" . Date("Y")-1);
//get the number of seconds between the date and first of the year
$seconds_diff = $ts2 - $ts1;
echo "$seconds_diff <br>";
//get the number of days
$dayDiff=$seconds_diff/86400;
//how many intervals?
$intervalDays = "10";
//get the number of intervals from start date to last day of last year
$numIntervals = floor($dayDiff/$intervalDays);
echo $numIntervals."<br>";
//now the total intervals to get into the current year is one more interval, turn this into days
$totIntervals= ($numIntervals* $intervalDays)+$intervalDays;
//Date Time date in question
$theDt = new DateTime($date1);
//Add the intervals we calculated to the date in question, and we have the first date of the interval for the current year...
$theDt->add(new DateInterval('P' . $totIntervals. 'D'));
echo "The first date of the intreval is: " . $theDt->format('Y-m-d');

I think, if you are doing 7 day intervals, you can find out the Day of week of your initial date, and then get the first date of the current year with that day of week...
Find out day of week: How to find the day of week from a date using PHP?
Find out date with that day of week for this year: Getting first weekday in a month with strtotime
Putting it together:
$date=Date("2/8/2012");
//Get the day of week for the date in question
$dayOfWeek = date('l', strtotime($date));
echo "The day of week for the given date is: $dayOfWeek <br>";
//Get the current year
$thisYear = date("Y");
echo "This year: $thisYear <br>";
//Create a date with the first occurence of the day of week of the given date for the current year
$firstOccurenceThisYear = date("m/d/y", strtotime("January " .$thisYear ." " . $dayOfWeek));
echo "The first interval of the year is: $firstOccurenceThisYear";
/*
Output:
This year: 2014
The day of week for the given date is: Wednesday
The first interval of the year is: 01/01/14
*/

Here is a slightly modified version of #Dan's second answer which worked well for me.
Benchmarks shown below.
$date="1985-02-18";
$intervalDays = "5";
//original version
$benchMark = microtime(true);
$dt1 = new DateTime($date);
$interval = new DateInterval("P{$intervalDays}D");
while ($dt1->format('Y') < date('Y')) {
$dt1->add($interval);
}
echo $dt1->format('d m Y') . '<br>';
echo microtime(true)-$benchMark.'<br>';
//new version
$benchMark = microtime(true);
$dt1 = new DateTime($date);
$dt2 = new DateTime("12/31/" . ((int) Date("Y") - 1));
$dayDiff = $dt1->diff($dt2)->days;
$numIntervals = floor($dayDiff / $intervalDays);
$totIntervals = ($numIntervals * $intervalDays) + $intervalDays;
$dt1->add(new DateInterval('P' . $totIntervals . 'D'));
echo $dt1->format('d m Y').'<br>';
echo microtime(true)-$benchMark.'<br>';
exit;
output
02 01 2014
0.0145111083984
02 01 2014
0.000123977661133

Related

PHP | Calculate remaining days but taking leap years into account

small problem to calculate the remaining days of the month starting today just I write:
$today = date('Y/m/d');
$timestamp = strtotime($today);
$daysRemaining = (int)date('t', $timestamp) - (int)date('j', $timestamp);
echo $daysRemaining;
and I get the remaining days
to do a test I entered a static date for the month of February
$timestamp = strtotime('2020-02-01');
$daysRemaining = (int)date('t', $timestamp) - (int)date('j', $timestamp);
echo $daysRemaining;
the question is here how do I calculate the remaining days in the month taking into account leap years, for example in February 2020 it will have 29 days and in this way I get out of it that remain 28
Stop using the functions and start using the DateTime class!!!
This code should explain itself.
<?php
$x = new DateTime('2020-02-17'); // create your date
$y = clone $x; // copy the date
$y->modify('last day of this month'); // alter the copy to the last day
echo $x->format('d') . "\n"; // show the day of the first date
echo $y->format('d') . "\n"; // show the day of the second date
echo $y->format('d') - $x->format('d'); // show the difference between the two
Output:
17
29
12
Check it here https://3v4l.org/8ZhOb
Check the DateTime class docs here https://www.php.net/manual/en/class.datetime.php

Comparing current date to a repeating day of the month

How would I compare the current day, in any format to a static repeating day of the month.
For example I have due date of 5 which is when my rent is due and I want compare the current date every day so that on the 5th of each month I can then know how many days till the 5th or since the 5th
Is there a way to do this without setting my due date to a timestamp or similar that I then update as it is reached?
You could do something like this:
function date_diff_in_days($date1, $date2) {
$date1 = strtotime($date1);
$date2 = strtotime($date2);
$diff = $date2 - $date1;
return floor($diff/86400); // 86400 is one day in seconds
}
// compare the due date to the current date
$days = date_diff_in_days($due_date, time());
$past_due = $days < 0;
$days = abs($days);
// show your result
echo 'Your bill is '.($past_due
? 'past due by '.$days.' days.'
: 'due in '.$days.' days.');

Is current date within specified date/time range in PHP

I am creating a website that allow deliveries only within certain delivery time frames.
Here is an example of exactly what I'm looking for:
FakeCompany delivers on Wednesday and allows customers to place orders between Friday and Tuesday with a cutoff time of 11 PM on Tuesday night.
I need to figure out when the customer logs in if ordering is allowed (between Friday - Tuesday 11 PM). I also need to know how much longer they have to order.
I know the PHP date('N') function that Friday is 5:
date('N', strtotime('Friday'));
and Tuesday is 1:
date('N', strtotime('Tuesday'));
These time ranges may change, so I need a simple solution.
Here is what I started with, and now I'm lost on how to do this.
//Set today and get from database start / end days and end time
$today = (int)date('N');
$startDay = (int)date('N', strtotime('Friday'));
$endDay = (int)date('N', strtotime('Tuesday'));
$endDayTime = '11:00:00';
//If today is before start date
if($today >= $startDay && $today <= $endDay){
//This works only if the end date is not the following week
//It also needs to be before end day time!
}
I think I need to get the date of the week based on the DAY (Friday) and convert that to this weeks Friday if Friday has not passed or next weeks Friday and do the same with end date.
Then I need to know if today is between those dates / times.
$now = new DateTime();
$tuesday = new DateTime('last Tuesday');
$friday = new DateTime('Friday 11pm');
if ($tuesday < $now && $now < $friday) {
$interval = $friday->diff($now);
echo $interval->format('%d day %h hours %i minutes left to order');
}
else {
echo "you can't order now";
}
See it in action
Here is a function to check that today is an approved day then if its tuesday also make sure it is before 11pm:
/*
Acceptable days:
5 - friday
6 - saturday
7 - sunday
1 - monday
2 - tuesday
*/
//Can they order today?
if(in_array(date('N'),array(1,2,5,6,7))){
//if today is tuesday is it before 11pm?
if(date('N') == 2){
if(date('H')<23){
//23 = 11pm in 24 hour time
//Then can order
}
else{
//Then CANT order
}
}
//Its not tuesday so we dont care what time it is they can order
}
for the end day I think you could do it like this:
$endDay = (int)date('N', strtotime('Friday') + 3 * 24 * 3600 + 23 * 3600);
strtotime('Friday') to get friday and add 3 days of 24 hours to it, and it'll be Tuesday 0 am. Then you add 23 hours time to it as it finish at 11pm.
$today = (int)date('N');
$startDay = (int)date('N', strtotime('Friday'));
$endDay = (int)date('N', strtotime('Friday') + 3 * 24 * 3600 + 23 * 3600);
//If today is before start date
if($today >= $startDay && $today <= $endDay){
//now it works
}
Here is exactly what I am looking for.
The dates provided may not be this week or even this month, so we need to figure out based on the date what the day of the week was and set the date on this week or next week to same day depending on today (kinda confusing).
See It In Action
//IF USING A DATABASE TO STORE DATE/TIME
//Get route times
//When Using Database: $query = "SELECT * FROM routes WHERE id = '".$user['route_one']."'";
//When Using Database: $result = $this->query($query);
//When Using Database: $route = $this->fetchArray($result);
//Set date vaiables
$thisWeek = new DateTime();
$routeStart = new DateTime(date('Y-m-d H:i:s', strtotime('2013-04-21 00:00:00')));
//When Using Database: $routeStart = new DateTime(date('Y-m-d H:i:s', strtotime($route['start_time'])));
$routeEnd = new DateTime(date('Y-m-d H:i:s', strtotime('2013-04-24 00:00:00')));
//When Using Database: $routeEnd = new DateTime(date('Y-m-d H:i:s', strtotime($route['end_time'])));
$interval = $routeStart->diff($routeEnd);
$numDays = abs($interval->format('%d'));
//Check if today is past or on the start date, else start date is next week, and set day of week
if($thisWeek->format('N') >= $routeStart->format('N')){
$startDate = $thisWeek->modify('last '.$routeStart->format('l'));
}
else{
$startDate = $thisWeek->modify($routeStart->format('l'));
}
//Now that we know the start date add the amount of days to the start date to create the end date
$endDate = new DateTime($startDate->format('Y-m-d H:s:i'));
$endDate->modify('+'.$numDays.' days '.$routeEnd->format('H').' hours');
//Check to see if user is within the time range to order or not
$today = new DateTime();
if($startDate <= $today && $today <= $endDate){
//Find out how much longer ordering can take place
$interval = $endDate->diff($today);
$output = 'Allowed to order!<br>';
$output .= '<div id="orderTimeCounter">'.$interval->format('%d days %h hours %i minutes left to order').'</div>';
}
else{
//If today is before start date set start date to THIS week otherwise NEXT week
if($startDate >= $today){
$startDate = $startDate->modify('this '.$routeStart->format('l'));
}
else{
$startDate = $startDate->modify('next '.$routeStart->format('l'));
}
//Find out how much longer until ordering is allowed
$interval = $today->diff($startDate);
$output = 'Not allowed to order!';
$output .= '<div id="orderTimeCounter">'.$interval->format('%d days %h hours %i minutes until you can order').'</div>';
}
echo $output;

php week interval from date ("W")

Hy, I have in database number of the week date ("W") and I want to display week interval like 28 Jan -> 3 Feb in this format, and I don't know if it's possible. Can you help?
Thanks!
Try this
$year = 2013;
$week_no = 6;
$week_start = new DateTime();
$week_start->setISODate($year,$week_no);
$week_end = clone $week_start;
$week_end = $week_end->add(new DateInterval("P1W"));
echo $week_start->format('d-M-Y') . " - ".$week_end->format('d-M-Y');
Transform your intervals into timestamps.
If its not the first day of the week get the first day of that week with strtotime "last sunday" (or monday) for the first date.
Do the same for the second date this time geting the last day of the week with "next saturday" (or sunday);
Get both dates W and make a mysql comparison between the weeks.

Getting the date for current day in PHP

I want to get the date for current day in php. what i tried is here...
echo $x."<br>";
echo date("D",$x)."<br>";
But the output was
21-02-10
Thu
It is giving correct date but not the correct day value.Why..?
What I want day is the date for monday for the current week which can be generated on any day of the week. so what I did was, I'm taking the today's day and comparing with (Mon,Tue.... Sun) and respectively creating a timestamp using
case "Mon":
$startdate1=date("d-m-y");
$parts = explode('-',$startdate1);
$startdate2 = date('d-m-Y',mktime(0,0,0,$parts[1],($parts[0]+1),$parts[2]));
$startdate3 = date('d-m-Y',mktime(0,0,0,$parts[1],($parts[0]+2),$parts[2]));
$startdate4 = date('d-m-Y',mktime(0,0,0,$parts[1],($parts[0]+3),$parts[2]));
$startdate5 = date('d-m-Y',mktime(0,0,0,$parts[1],($parts[0]+4),$parts[2]));
$startdate6 = date('d-m-Y',mktime(0,0,0,$parts[1],($parts[0]+5),$parts[2]));
$startdate7 = date('d-m-Y',mktime(0,0,0,$parts[1],($parts[0]+6),$parts[2]));
$dates=array(1 => $startdate1,$startdate2,$startdate3,$startdate4,$startdate5,$startdate6,$startdate7);
$i=1;
while( $i <= 7 )
{
echo $dates[$i];
$i++;
}
break;
$date is the final array respective to today that has to be returned. Is there any other better method to do this operation.
I tried this to get current day.
echo date('l'); // output: current day.
How about this:
//today is monday
if (1 == date('N')){
$monday = time();
}else{
$monday = strtotime('last Monday');
}
for ($i = 0; $i < 7; $i++){
echo date('d-m-Y', $monday) . '<br>';
$monday = strtotime('tomorrow', $monday);
}
First find Monday, if it is not today, then print 7 dates
What I want day is the date for monday
for the current week which can be
generated on any day of the week.
That's what you want. $mday is the month day of this week's Monday. Nevermind if it's not positive, mktime will handle that right. $monday has the timestamp of the Monday's midnight.
$now = getdate();
$mday = $now['mday'] - ($now['wday'] + 6) % 7;
$monday = mktime(0, 0, 0, $now['mon'], $mday, $now['year']);
echo(date('d-m-y', $monday));
What i did to resolve it is used the date format ('d-m-Y') instead of ('d-m-y') in date function, which was causing the problem. Hence strtotime accepted the format and gave the correct result for
$t=date('d-m-Y');
echo date("D",strtotime($t));
I use the function date and path to it the "D" that refere to the current day , and it works with me
$today = date("D");
and to get the full info about the current date
$today = date("D M j G:i:s T Y"); // Sat Mar 10 17:16:18 MST 2001
what i tried is here...
echo date("D",$x)."<br>";
date expects a timestamp (int) value as the second parameter. Your $x is a string containing an ambiguous date format. Convert that date into a timestamp first, using strptime or strtotime and use the date function correctly to get the correct day value.
Regarding your second part, you don't need to (and shouldn't) check the day name to calculate the correct Monday, Tuesday etc. A more efficient approach is for example using strtotime to get last Monday etc.
You are likely passing a string as timestamp
echo $x."<br>";
echo date("D",$x)."<br>";
Remove $x and it will output the correct day or change it to
$x = '21-02-2010';
echo date('D', strtotime($x));

Categories