How to make a period with all months between two random dates?
I tried:
$startDate = \Carbon\Carbon::parse('2021-11-17 23:59:59');
$endDate = \Carbon\Carbon::parse('2022-01-10 00:00:00');
$period = \Carbon\CarbonPeriod::create($startDate, '1 month', $endDate);
foreach($period as $month)
{
echo '<pre>'.$month->format('Y-m-d').'</pre>';
}
but it doesn't include January.
I also tried to use floor():
$startDate = \Carbon\Carbon::parse('2021-11-17 23:59:59');
$endDate = \Carbon\Carbon::parse('2022-01-31 00:00:00');
$period = \Carbon\CarbonPeriod::create($startDate, '1 month', $endDate)->floor();
foreach($period as $month)
{
echo '<pre>'.$month->format('Y-m-d').'</pre>';
}
but it includes February that don't even need.
How to get pure "unical" months between two dates using CarbonPeriod?
For example: start_date: 2021-11-17 23:59:59 & end_date: 2022-01-10 00:00:00 -> 11, 12, 01
Also: start_date: 2021-11-17 23:59:59 & end_date: 2022-01-31 00:00:00 -> 11, 12, 01
Thank you.
use startOfMonth() and endOfMonth() as below.
$startDate = Carbon::parse('2021-11-17 23:59:59')->startOfMonth();
$endDate = Carbon::parse('2022-01-10 00:00:00')->endOfMonth();
foreach (CarbonPeriod::create( $startDate, '1 month', $endDate) as $month) {
echo $month->format('m') . PHP_EOL;
}
Output will be:
11
12
01
Related
I'm trying to get a week range for the month, I've somewhat accomplished what I'm looking for but I'd like the code to be more reliable. The data ranges are going to be used to some MySQL queries where I can filter out data by data range.
What I'd like to achieve is to get something like the Windows 10 calendar. So the result is
2020-03-01 to 2020-03-01
2020-03-02 to 2020-03-08
2020-03-09 to 2020-03-15
2020-03-16 to 2020-03-22
2020-03-23 to 2020-03-29
2020-03-30 to 2020-03-31
CODE
$start_date = date("Y-m-d", strtotime("first day of this month"));
$end_date = date("Y-m-d", strtotime("last day of this month"));
function getWeekDates($date, $start_date, $end_date) {
$week = date('W', strtotime($date));
$year = date('Y', strtotime($date));
$from = date("Y-m-d", strtotime("{$year}-W{$week}+1"));
if($from <= $start_date){
$from = $start_date;
}
$to = date("Y-m-d", strtotime("{$year}-W{$week}-7"));
if($to >= $end_date){
$to = $end_date;
}
echo $from." to ".$to.'<br>';
}
for($date = $start_date; $date <= $end_date; $date = date('Y-m-d', strtotime($date. ' + 7 day'))){
echo getWeekDates($date, $start_date, $end_date);
echo "\n";
}
Which results in
It's missing the last two days of the month (30 and 31).
2020-03-01 to 2020-03-01
2020-03-02 to 2020-03-08
2020-03-09 to 2020-03-15
2020-03-16 to 2020-03-22
2020-03-23 to 2020-03-29
You can use DateTime objects to do this more readily, setting a start time as the first Monday on or before the start of the month, and then adding a week at a time until it is past the end of the month:
$month_start = new DateTime("first day of this month");
$month_end = new DateTime("last day of this month");
// find the Monday on/before the start of the month
$start_date = clone $month_start;
$start_date->modify((1 - $start_date->format('N')) . ' days');
while ($start_date <= $month_end) {
echo max($month_start, $start_date)->format('Y-m-d') . ' to ' . min($start_date->modify('+6 days'), $month_end)->format('Y-m-d') . "\n";
$start_date->modify('+1 day');
}
Output:
2020-03-01 to 2020-03-01
2020-03-02 to 2020-03-08
2020-03-09 to 2020-03-15
2020-03-16 to 2020-03-22
2020-03-23 to 2020-03-29
2020-03-30 to 2020-03-31
Demo on 3v4l.org
I want to render dates period base on start date and end date, for example:
Input:
Start date: 30/12/2017
End date: 31/03/2017
Interval: every month
Output I want:
30/12/2017
30/01/2018
30/03/2018 (February is missing because it not have 30th)
There my code:
function period_days($start_date, $int, $end_date){
$begin = new DateTime( $start_date );
$end = new DateTime( $end_date );
$interval = DateInterval::createFromDateString($int);
$period = new DatePeriod($begin, $interval, $end->modify( '+1 day' ));
return $period;
}
echo period_days('30-12-2017', '1 month', '31-03-2018');
Result return wrong (3rd should be "2018-03-30"):
"2017-12-30 00:00:00"
"2018-01-30 00:00:00"
"2018-03-02 00:00:00"
Edit: Explain about Input:
Start date format can be '31/12/2017' or 'first Monday of January 2018' or 'third Tuesday of December 2017' or '28 December 2017' ...
Interval can be '1 day', '1 month', '2 months', '1 year' ...
End date format is d-m-Y '01/12/2018'
I use this function to add schedule recurring event, something like plugin The Event Calendar, you guys can see example on https://wpshindig.com/events/community/add
I could suggest you a work around.
Since DatePeriod breaks for February, we could get Year and month and append date separately. But this will only be working for one year.
Example :
function periodDays($start_date, $int, $end_date){
$begin = new DateTime($start_date);
$end = new DateTime($end_date);
$startDay = $begin->format("d");
$interval = DateInterval::createFromDateString($int);
$period = new DatePeriod($begin, $interval, $end);
foreach($period as $date){
echo $date->format("Y-m-") .$startDay. "<br>";
}
}
How can we split dates using PHP? Is there any built in function in PHP?
2016-11-01 10:00:00 till 2016-11-03 18:00:00
I need to split above date in to required dates:-
2016-11-01 10:00:00 till 23:59:59
2016-11-02 00:00:00 till 23:59:59
2016-11-03 00:00:00 till 18:00:00
To my knowledge PHP does not provide such built-in feature.
But you can easily achieve this with th DateTime object :
$interval = '2016-11-01 10:00:00 till 2016-11-03 18:00:00';
$dates = explode(' till ', $interval);
if(count($dates) == 2) {
$current = $begin = new DateTime($dates[0]);
$end = new DateTime($dates[1]);
$intervals = [];
// While more than 1 day remains
while($current->diff($end)->format('%a') >= 1) {
$nextDay = clone $current;
$nextDay->setTime(23,59,59);
$intervals []= [
'begin' => $current->format('Y-m-d H:i:s'),
'end' => $nextDay->format('Y-m-d H:i:s'),
];
$current = clone $nextDay;
$current->setTime(0,0,0);
$current->modify('+1 day');
}
// Last interval : from $current to $end
$intervals []= [
'begin' => $current->format('Y-m-d H:i:s'),
'end' => $end->format('Y-m-d H:i:s'),
];
print_r($intervals);
}
You can use for loop to achieve such type of result. Your requirement is to print date in one day difference between start and end date. I have write code for this .
<?php
$startDate = strtotime('2016-11-01 10:00:00');
$endDate = strtotime('2016-11-03 18:00:00');
for ($loopStart = $startDate; $loopStart <= $endDate; $loopStart = strtotime('+1 day', $loopStart)) {
// check last date
if($endDate >= strtotime('+1 day', $loopStart)){
echo date('Y-m-d', $loopStart).' 23:59:59';
}
else{
echo date('Y-m-d', $loopStart).' '.date('H:i:s',$endDate);
}
echo "<br>";
}
?>
The output of the code is -
2016-11-01 23:59:59
2016-11-02 23:59:59
2016-11-03 18:00:00
Today is 2015-05-22 (to understand the example)
I have to see some statistics taking values from a database. Initially I had to do these comparisons
this week compared with the previous week. [2015-05-18 00:00:00 # 2015-05-24 23:59:59] - [2015-05-11 00:00:00 # 2015-05-17 00:00:00]
this month compared with the previous month. [2015-05-01 00:00:00 # 2015-05-31 23:59:59] - [2015-04-01 00:00:00 # 2015-04-30 23:59:59]
this year compared with the previous year. [2015-01-01 00:00:00 # 2015-12-31 23:59:59] - [2014-01-01 00:00:00 # 2014-12-31 23:59:59]
For all these controls i do this function that calculated all the various date intervals.
function getIntervalDate(){
$today = new DateTime();
$appToday = new DateTime();
$numDay = date("w");
$numYear = (int)date("Y");
switch($numDay){
//monday
case 1 :
$startWeek = $today->format('Y-m-d 00:00:00');
$endWeek = $today->modify('next sunday')->format('Y-m-d 23:59:59');
$startWeek2 = $today->modify('last monday -1 week')->format('Y-m-d 00:00:00');
$endWeek2 = $today->modify('next sunday')->format('Y-m-d 00:00:00');
break;
default:
$startWeek = $today->modify('last monday')->format('Y-m-d 00:00:00');
$endWeek = $today->modify('next sunday')->format('Y-m-d 23:59:59');
$startWeek2 = $today->modify('last monday -1 week')->format('Y-m-d 00:00:00');
$endWeek2 = $today->modify('next sunday')->format('Y-m-d 00:00:00');
break;
}
$startMonth = $today->modify('first day of this month')->format('Y-m-d H:i:s');
$endMonth = $today->modify('last day of this month')->format('Y-m-d 23:59:59');
$today1 = $appToday;
$startMonth2 = $today1->modify('first day of previous month')->format('Y-m-d H:i:s');
$endMonth2 = $today1->modify('last day of this month')->format('Y-m-d 23:59:59');
$today2 = $appToday;
$startYear = $today2->modify('first day of January '.$numYear)->format('Y-m-d 00:00:00');
$endYear = $today2->modify('last day of December '.$numYear)->format('Y-m-d 23:59:59');
$today3 = $appToday;
$startYear2 = $today3->modify('first day of January '.($numYear-1))->format('Y-m-d 00:00:00');
$endYear2 = $today3->modify('last day of December '.($numYear-1))->format('Y-m-d 23:59:59');
return array(
"startWeek" => $startWeek,
"endWeek" => $endWeek,
"startWeek2" => $startWeek2,
"endWeek2" => $endWeek2,
"startMonth" => $startMonth,
"endMonth" => $endMonth,
"startMonth2" => $startMonth2,
"endMonth2" => $endMonth2,
"startYear" => $startYear,
"endYear" => $endYear,
"startYear2" => $startYear2,
"endYear2" => $endYear2
);
}
Everything works perfectly. But now i have to change the various comparisons. I have to always compare the current week / month / year interval but with the week / month / year in the previous year (in the case of the year there are no problems, the code remains the same)
I did some tests but i failed. I used mostly the ->modify('-1 year') but with not a perfect result.
Based on your discussion above here is the solution of your problem:
$startWeek->modify("-1 year")->modify('monday')->format('Y-m-d H:i:s');
Here is the test.
$today = DateTime::createFromFormat('Y-m-d H:i:s', '2015-05-18 00:00:00');
$startWeekPrevYear=$today->modify('-1 year')->modify('monday');
echo $startWeekPrevYear->format('Y-m-d H:i:s');//outputs 2014-05-19 00:00:00
How can I get the date for monday and friday for the current week?
I have the following code, but it fails if current day is sunday or saturday.
$current_day = date("N");
$days_to_friday = 5 - $current_day;
$days_from_monday = $current_day - 1;
$monday = date("Y-m-d", strtotime("- {$days_from_monday} Days"));
$friday = date("Y-m-d", strtotime("+ {$days_to_friday} Days"));
Best solution would be:
$monday = date( 'Y-m-d', strtotime( 'monday this week' ) );
$friday = date( 'Y-m-d', strtotime( 'friday this week' ) );
These strtotime inputs work very well:
strtotime( "next monday" );
strtotime( "previous monday" );
strtotime( "today" );
strtotime( "next friday" );
strtotime( "previous friday" );
All you need to do is to wrap the logic inside some if statements.
This question needs a DateTime answer:-
/**
* #param String $day
* #return DateTime
*/
function getDay($day)
{
$days = ['Monday' => 1, 'Tuesday' => 2, 'Wednesday' => 3, 'Thursday' => 4, 'Friday' => 5, 'Saturday' => 6, 'Sunday' => 7];
$today = new \DateTime();
$today->setISODate((int)$today->format('o'), (int)$today->format('W'), $days[ucfirst($day)]);
return $today;
}
Usage:
var_dump(getDay('Monday')->format('l dS F Y'));
var_dump(getDay('Friday')->format('l dS F Y'));
Output:
string 'Monday 30th September 2013' (length=26)
string 'Friday 04th October 2013' (length=24)
See it working
i use :
$first_week_date = date('d F Y', strtotime('next Monday -1 week', strtotime('this sunday')));
$last_week_date = date('d F Y', strtotime('next Monday -1 week + 4 days', strtotime('this sunday')));
This really depends on how you define a week but I came up with this function that will give you the date for the nearest "monday" or "friday" (or any day for that matter):
function closestDate($day){
$day = ucfirst($day);
if(date('l', time()) == $day)
return date("Y-m-d", time());
else if(abs(time()-strtotime('next '.$day)) < abs(time()-strtotime('last '.$day)))
return date("Y-m-d", strtotime('next '.$day));
else
return date("Y-m-d", strtotime('last '.$day));
}
Input: a day of the week ("sunday", "Monday", etc.)
Output: If I asked for the nearest "sunday" and today is:
"Sunday": I will get today's date
"Monday": I will get yesterday's date
"Saturday: I will get tomorrow's date
Hope this helps :)
As the top answer suggests, using PHP's strtotime() function is the easiest way.
However, instead of using if statements as he suggests, you could simply reset back to the previous Sunday and grab the dates you require from there.
$monday = strtotime('next monday', strtotime('previous sunday'));
$friday = strtotime('next friday', strtotime('previous sunday'));
I needed a definition of the current week per ISO 8601. I want Monday to always be defined as the Monday that started this current week.
The following solution works excellent for me:
$monday = strtotime(date('o-\WW'));
$friday = strtotime("next friday",$monday);
For $monday, this method will always return the Monday that started this calendar week. unfortunately, this method relies on PHP 5.1 to parse the o date format.
To get any day of the week, you could try:
function time_for_week_day($day_name, $ref_time=null){
$monday = strtotime(date('o-\WW',$ref_time));
if(substr(strtoupper($day_name),0,3) === "MON")
return $monday;
else
return strtotime("next $day_name",$monday);
}
Usage:
time_for_week_day('wednesday');
time_for_week_day('friday',strtotime('2014-12-25'));
I was looking for a similar thing, except I wanted any Monday, not just this week. This is what I came up with:
function getSunday(DateTime $date){
$outdate = clone($date);
$day = $date->format("w"); // get the weekday (sunday is 0)
$outdate->sub(new DateInterval("P".$day."D")); // subtracting the weekday from the date always gives Sunday
return $outdate;
}
It accepts an arbitrary date and gives the Sunday. Then you can easily add back days to get Monday through Saturday.
get the current week
$week = [];
$saturday = strtotime('saturday this week');
foreach (range(0, 6) as $day) {
$week[] = date("Y-m-d", (($day * 86400) + $saturday));
}