PHP DateInterval Jan - June and July - Dec - php

Trying to create a list or date interval for the past 2 years, divided into ranges of 6 months, i.e. Jan - June 2015, July - Dec 2015, Jan - June 2016 ... until today.
I have looked into DateTime and DateInterval, something like this
$begin = new DateTime( '2015-01-01' );
$end = new DateTime( '2017-12-26' );
$interval = new DateInterval('P6M');
$period = new DatePeriod($begin, $interval, $end);
foreach ( $period as $dt )
echo sprintf("%s\n", $dt->format("Y-m-d"));
Which gives me
2015-01-01
2015-07-01
2016-01-01
2016-07-01
2017-01-01
2017-07-01
Can't figure out how to get start and end (Jan 1 - June 30 and July 1 - Dec 31) for each period.

After adding an interval, subtract one day from it. Use sub() and new DateInterval('P1D'), which indicates subtraction of one day.
foreach ( $period as $dt )
echo sprintf(
"%s %s\n",
$dt->format("Y-m-d"),
$dt->add($interval)
->sub(new DateInterval('P1D'))
->format("Y-m-d"));
This outputs:
2015-01-01 2015-06-30
2015-07-01 2015-12-31
2016-01-01 2016-06-30
2016-07-01 2016-12-31
2017-01-01 2017-06-30
2017-07-01 2017-12-31
Update: In the comments you also asked how to indicate what half of the year the date represents. The answer is too obvious:
sprintf(
"%s %s %d\n",
$dt->format("Y-m-d"),
$dt->add($interval)
->sub(new DateInterval('P1D'))
->format("Y-m-d"),
$dt->format("n")/6
);
Note %d and corresponding $dt->format("n")/6.
Output for me:
2015-01-01 2015-06-30 1
2015-07-01 2015-12-31 2
2016-01-01 2016-06-30 1
2016-07-01 2016-12-31 2
2017-01-01 2017-06-30 1
2017-07-01 2017-12-31 2

you can just add the interval size '-1' for each start like this:
$begin = new DateTime( '2015-01-01' );
$end = new DateTime( '2017-12-26' );
$interval = new DateInterval('P6M');
$period = new DatePeriod($begin, $interval, $end);
$oneDay = new DateInterval("P1D");
$oneDay->invert=1; #just get the previous day as if("P-1D")
foreach ( $period as $dt ){
echo $dt->format("Y-m-d"); #interval start
$dt->add($interval); #adding the interval size
$dt->add($oneDay); #get the last day of the cur interval
echo "<br>";
echo $dt->format("Y-m-d"); #interval end
echo "<br>";
}

Related

Return Iterative Datetime between Two Datetimes for Adding Records in Laravel

Input:
$start = new DateTime('2021-09-13 06:00:00');
$end = new DateTime('2021-09-17 15:00:00');
Expected Output:
Start
End
Hours
2021-09-13 06:00:00
2021-09-13 15:00:00
9 hours
2021-09-14 06:00:00
2021-09-14 15:00:00
9 hours
2021-09-15 06:00:00
2021-09-15 15:00:00
9 hours
2021-09-16 06:00:00
2021-09-16 15:00:00
9 hours
2021-09-17 06:00:00
2021-09-17 15:00:00
9 hours
I have tried this as foundation, but not pretty sure it this would meet my expected output.
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
Log::info($dt->format("Y-m-d H:i:s \n"));
}

time relative formats : get the date of the first Sunday of last year

I want to retrieve the date of the first Sunday of last year,
but i have a problem
$date = new DateTime('first sunday of august last year');
gives me as a result :
DateTime Object ( [date] => 2020-08-01 00:00:00.000000 [timezone_type] => 3 [timezone] => Europe/Berlin )
// saturday
but I want :
DateTime Object ( [date] => 2020-08-02 00:00:00.000000 [timezone_type] => 3 [timezone] => Europe/Berlin )
// sunday
is this a bug or am I at fault ?
It seem that last year fail to get the right date.
Seem confused between first sunday of august 2021 (08-01) and 2020 (08-02).
Using "hard coded" year, give the right date.
new DateTime('first sunday of august 2020', new DateTimeZone('Europe/Berlin'));
// "2020-08-02 00:00:00.000000"
A quick workaround could be :
$year = date('Y', strtotime('-1 year'));
$date = new DateTime('first sunday of august ' . $year, new DateTimeZone('Europe/Berlin'));
// "2020-08-02 00:00:00.000000"
The reason is
"ordinal dayname 'of' " does not advance to another day. (Example: "first wednesday of july 23rd, 2008" means "2008-07-02" because the specific phrase with 'of' resets the day-of-month to '1' and the '23rd' is ignored here).
You get the right answer if you specify the year:
$date = new DateTime('first sunday of august 2020');

PHP calculate number of full months between two dates

I am trying to calculate the difference in months between two dates, but in a more specific way.
For example, I have two dates: 2017-11-01 and 2018-01-31
What I need as a result is 3 months. Meaning, there are 3 full billing months between these two dates.
Here is how it's supposed to work:
Month 1: 2017-11-01 until 2017-11-30
Month 2: 2017-12-01 until 2017-12-31
Month 3: 2018-01-01 until 2018-01-31
I have tried the diff method in the DateTime class, it produces something that doesn't help much. Here is an example
<?php
$date1 = DateTime::createFromFormat('Y-m-d H:i:s', '2017-11-01 00:00:00');
$date2 = DateTime::createFromFormat('Y-m-d H:i:s', '2018-01-31 00:00:00');
$diff = $date1->diff($date2);
print_r($diff)
result:
DateInterval Object
(
[y] => 0
[m] => 2
[d] => 30
[h] => 0
[i] => 0
[s] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 91
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
It shows 2 months and 30 days.
However, in a slightly different scenario
$date1 = DateTime::createFromFormat('Y-m-d H:i:s', '2017-11-01 00:00:00');
$date2 = DateTime::createFromFormat('Y-m-d H:i:s', '2018-01-30 00:00:00');
The diff between these two dates should show 2 months and 30 days, not 3 months.
Any help or ideas would be greatly appreciated.
Add one day to your ending date before doing the comparison. If the original ending date was the last day of the month, then the new ending date will roll over to the next month and you'll get the correct number of "full" months in the diff object. If the original was any day but the last day of the month, it won't change the result.
$start = '2017-11-01';
$end = '2018-01-31';
$date1 = DateTime::createFromFormat('Y-m-d', $start);
$date2 = DateTime::createFromFormat('Y-m-d', $end)->add(new DateInterval('P1D'));
echo $date1->diff($date2)->m, "\n";
Seems you lost one day during your calculation. Cause you need interval in months including first/last day - then you should add this day to interval.
So, the solution in this case will be:
$date1 = DateTime::createFromFormat('Y-m-d H:i:s', '2017-11-01 00:00:00');
$date2 = DateTime::createFromFormat('Y-m-d H:i:s', '2018-01-31 23:59:59');
$diff = $date1->diff($date2);
or:
$date1 = DateTime::createFromFormat('Y-m-d H:i:s', '2017-10-31 00:00:00');
$date2 = DateTime::createFromFormat('Y-m-d H:i:s', '2018-01-31 00:00:00');
$diff = $date1->diff($date2);
or even:
$date1 = DateTime::createFromFormat('Y-m-d H:i:s', '2017-11-01 00:00:00');
$date2 = DateTime::createFromFormat('Y-m-d H:i:s', '2018-02-01 00:00:00');
$diff = $date1->diff($date2);
Using Carbon:
Carbon::parse('2017-10-31')->diffInMonths(Carbon::now());

Get end of week using PHP [duplicate]

This question already has answers here:
Get date for monday and friday for the current week (PHP)
(9 answers)
Closed 7 years ago.
How can I return the end of the week using PHP? I wanted to return an array of dates in the following format:-
Array
(
[0] => Friday 17 April 2015
[1] => Friday 24 April 2015
[2] => Friday 1 May 2015
[3] => Friday 8 May 2015
)
This should work for you:
(Here I simply create a DatePeriod starting from the next Friday from today. With a DateInterval of 7 days and until the next month)
<?php
$today = (new DateTime())->modify("next Friday");
$interval = new DateInterval("P7D");
$end = (new DateTime())->modify("next month");
$period = new DatePeriod($today, $interval, $end);
foreach($period as $date)
echo $date->format("l j F Y") . "<br />";
?>
output:
Friday 17 April 2015
Friday 24 April 2015
Friday 1 May 2015
Friday 8 May 2015
And for next time if you need todo something with dates see this: http://php.net/manual/en/book.datetime.php
Similar to Rizier's answer, but using PHP generators:
function fridays() {
$begin = new DateTime('First friday of this month');
$end = new DateTime('First friday of next month');
$interval = new DateInterval( 'P1W' );
$daterange = new DatePeriod( $begin, $interval ,$end );
foreach($daterange as $date){
yield $date;
}
}
foreach(fridays() as $date){
echo $date->format("l j F Y"), PHP_EOL;
}

Monthly recur with PHP

I have a two dates. start date and end date. Using those dates i have to find recur dates.
example:
(1) start date = 2014-01-01
end date = 2014-05-01
expected output:
2014-01-01
2014-02-01
2014-03-01
2014-04-01
2014-05-01
(2) start date = 2014-01-31
end date = 2014-05-01
expected output:
2014-01-31
2014-02-28
2014-03-31
2014-04-30
means do not skip month, if month is skip in that case use last day of month. how to achive this thing?
I am using following code but i added 1 month in date so it skip the month:
$start = strtotime($start_date);
$end = strtotime($end_date);
$total_dates = array();
for($i=$start; $i<=$end;)
{
$date = date('Y-m-d',$start);
if($i>$start)
{
$next_date = date('Y-m-d',strtotime($date . "+1 month"));
$start = strtotime($next_date);
}
else
{
$next_date = date('Y-m-d',$start);
}
$total_dates[] = $next_date;
$date1 = new DateTime($date);
$newdate = date('Y-m-d',strtotime($date . "+1 month"));
$date2 = new DateTime($newdate);
$diff = $date2->diff($date1)->format("%a");
/* Find diff between two dates */
$i = (($i*1)+(86400*$diff)); //seconds in 1month
}
print_r($total_dates);
so in short:
start date = 2014-01-01
end date = 2014-05-01
expected output:
2014-01-31
2014-02-28
2014-03-31
2014-04-30
current output:
2014-01-31
2015-03-03
2015-04-03
check this
$start_date = '2015-01-31';
$end_date = '2016-06-01';
$start_date=date('Y-m-1', strtotime($start_date));
$diff = abs(strtotime($end_date) - strtotime($start_date));
$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
if($years>0){$loop=$years*12+$months;}else{$loop=$months;}
for($i=1; $i<=$loop+1;$i++)
{
$total_dates[] =$a= date('Y-m-t', strtotime($start_date));
$start_date = date('Y-m-d',strtotime($start_date . "+1 month"));
}
print_r($total_dates);
//output Array ( [0] => 2015-01-31 [1] => 2015-02-28 [2] => 2015-03-31 [3] => 2015-04-30 [4] => 2015-05-31 [5] => 2015-06-30 [6] => 2015-07-31 [7] => 2015-08-31 [8] => 2015-09-30 [9] => 2015-10-31 [10] => 2015-11-30 [11] => 2015-12-31 [12] => 2016-01-31 [13] => 2016-02-29 [14] => 2016-03-31 [15] => 2016-04-30 [16] => 2016-05-31 [17] => 2016-06-30 )
Try this...
<?php
$start_date = "2014-01-01";
$end_date = "2014-05-01";
$d = date_parse_from_format("Y-m-d", $start_date);
$start= $d["month"];
$d1 = date_parse_from_format("Y-m-d", $end_date);
$end= $d1["month"];
$array=array();
$array[]=date('Y-m-t', strtotime($start_date));
for($i=$start;$i<$end;$i++)
{
$str=explode("-",$start_date);
$mon=$str[1]+$i;
$newdate=$str[0]."-".$mon."-".$str[2];
$array[]=date('Y-m-t', strtotime($newdate));
}
print_r($array);
output:
2014-01-31
2014-02-28
2014-03-31
2014-04-30
2014-05-31
Use PHP date/time functions with relative interval formats:
http://php.net/manual/en/datetime.formats.relative.php
You can provide intervals like "last day of next month" or "last sat of July 2008", adding/subtracting this interval from the referenced date.

Categories