I am trying to get the number of sat&sun for each month between two given dates.
eg: For start_date as 5-Jul-2015 and end_date as 29-Aug-2015 I need to get 7 sat&sun in Jul and 9 in Aug.
So far I am getting values till the second last month ie: not getting Aug.
What to do?
Code
$countSat = 0;
$countSun = 0;
$start = new DateTime('05-07-2015');
$month = $start->format('n');
$end = new DateTime('29-08-2015');
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
$i = 0;
foreach ($period as $dt) {
if ($month != $dt->format('n')) {
$results[$i] = $countSun + $countSat;
$i++;
$countSun = 0;
$countSat = 0;
}
if ($dt->format('N') == 7) {
$countSun++;
}
if ($dt->format('N') == 6) {
$countSat++;
}
$month = $dt->format('n');
}
echo '<pre>';
print_r($results);
You are forgetting to add the results after the loop is done. The month will only change from 7 to 8 inside the loop.
Thus the days of the last month are being counted but never added.
$countSat = 0;
$countSun = 0;
$start = new DateTime('05-07-2015');
$month = $start->format('n');
$end = new DateTime('29-08-2015');
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
$i = 0;
foreach ($period as $dt) {
if ($month != $dt->format('n')) {
$results[$i] = $countSun + $countSat;
$i++;
$countSun = 0;
$countSat = 0;
}
if ($dt->format('N') == 7) {
$countSun++;
}
if ($dt->format('N') == 6) {
$countSat++;
}
$month = $dt->format('n');
}
$results[$i] = $countSun + $countSat;
echo '<pre>';
print_r($results);
Related
Suppose that i have
$time1 = 1492894800 //23/04/2017
$time2 = 1503521999 //23/08/2017
I would like to get timestamps grouped by months such that
get timestamp with rangess between months preserving first and last month of $time1 and $time2 such that i should have
1 23/04/2017 to 30/04/2017
2 01/05/2017 - 31/05/2017
....... //continue full months and lastly
01/08/2017 - 23/08/2017
i have tried
$timearrays = $this->getMontTimestampRanges($time1, $time2);
public function getMontTimestampRanges($ts1, $ts2){
$start = (new DateTime(date("Y-m-d", $ts1)));
$end = (new DateTime(date("Y-m-d", $ts2)));
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
$timestamps = [];
foreach ($period as $dt) {
//am stuck here on how to group based on the months
..push to array
}
return $timestamps;
}
so the final array i would like it to be of the form:
$timestamps = [
0=>["from":, "to": ] //first month(april)
1=>[ ] //second month may
]
How do i go about this?
After clarifying your query on my last answer, I have decided to delete my answer and post a new answer.
$start = 1492894800; //23/04/2017
$end = 1503521999; //23/08/2017
$steps = date('Ym', $end) - date('Ym', $start);
$timestamps = array();
for($i = 0; $i <= $steps; $i++) {
$base = strtotime("+{$i} months", $start);
$timestamps[] = array(
'from' => $i == 0 ? date('Y-m-d', $start) : date('Y-m-01', $base),
'to' => $i == $steps ? date('Y-m-d', $end) : date('Y-m-t', $base)
);
// If we want timestamps
// $timestamps[] = array(
// 'from' => strtotime(date('Y-m-01', $base)),
// 'to' => strtotime(date('Y-m-t', $base))
// );
}
print_r($timestamps);
Ideone link
I edited your code
Try this:
<?php
$time1 = 1492894800 ;//23/04/2017
$time2 = 1503521999; //23/08/2017
$timearrays = getMontTimestampRanges($time1, $time2);
var_dump( $timearrays);
function getMontTimestampRanges($ts1, $ts2){
$start = new DateTime(date("Y-m-d", $ts1));
$end = new DateTime(date("Y-m-d", $ts2));
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
$timestamps = [];
$startM = $period->getStartDate()->format('m');
$endM = $period->getEndDate()->format('m');
foreach ($period as $dt) {
//am stuck here on how to group based on the months
//start
if($startM == $dt->format('m'))
{
$timestamps[] = array('start'=>$start->format('Y-m-d'),'end'=>$dt->format('Y-m-t'));
}
elseif($endM == $dt->format('m'))
{
$timestamps[] = array('start'=>$dt->format('Y-m').'-01','end'=>$end->format('Y-m-d') );
}
else
{
$timestamps[] = array('start'=>$dt->format('Y-m').'-01','end'=>$dt->format('Y-m-t'));
}
}
return $timestamps;
}
http://sandbox.onlinephpfunctions.com/code/8527e45427fd0114f1e058fffc1885e460807a0a
Hope it helps.
What I am Trying
I am able to get the number of sat&sun between two dates. What I want is to get the number of sat&sun for each month between those dates.
Suppose start_date is 4-Jul-2015 and end_date is 30-Aug-2015. Then there is 8 sat&sun in Jul and 10 in Aug.
From what I did I'm getting 18. But I need to get 8 and 10. How can I get this
?
Code
$countSat = 0;
$countSun = 0;
$start = new DateTime($_POST['start']);
$end = new DateTime($_POST['end']);
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt)
{
if ($dt->format('N') == 7)
{
$countSun++;
}
if ($dt->format('N') == 6)
{
$countSat++;
}
}
$count = $countSat + $countSun;
try this option:
$countSat = 0;
$countSun = 0;
$i = 0;
$start = new DateTime($_POST['start']);
$month = $start->format('n');
$end = new DateTime($_POST['end']);
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt)
{
if($month != $dt->format('n'))
{
$results[$i]=$countSun+$countSat;
$i++;
$countSun=0;
$countSat=0;
}
if ($dt->format('N') == 7)
{
$countSun++;
}
if ($dt->format('N') == 6)
{
$countSat++;
}
$month = $dt->format('n');
}
I'm trying to list all months between two dates.
For example; start date is: 2010-12-02 and last date is: 2012-05-06
I want to list something like this:
2010-12
2011-01
2011-02
2011-03
2011-04
.
.
.
2012-04
2012-05
This is what I have tried and it is not working at all:
$year_min = 2010;
$year_max = 2012;
$month_min = 12;
$month_max = 5;
for($y=$year_min; $y<=$year_max; $y++)
{
for($m=$month_min; $m<=$month_max; $m++)
{
$period[] = $y.$m;
}
}
PHP 5.3
$start = new DateTime('2010-12-02');
$start->modify('first day of this month');
$end = new DateTime('2012-05-06');
$end->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
See it in action
PHP 5.4 or newer
$start = (new DateTime('2010-12-02'))->modify('first day of this month');
$end = (new DateTime('2012-05-06'))->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
The part where we modify the start and end dates to the first of the month is important. If we didn't, and the current day higher then the last day in February (i.e. 28 in non-leap years, 29 in leap years) this would skip February.
function getMonthsInRange($startDate, $endDate)
{
$months = array();
while (strtotime($startDate) <= strtotime($endDate)) {
$months[] = array(
'year' => date('Y', strtotime($startDate)),
'month' => date('m', strtotime($startDate)),
);
// Set date to 1 so that new month is returned as the month changes.
$startDate = date('01 M Y', strtotime($startDate . '+ 1 month'));
}
return $months;
}
You must make a difference between two months of the same year and two months of different years.
$year_min = substr($row['contractStart'], 0, 4);
$year_max = substr($row['contractEnd'], 0, 4);
$month_min = substr($row['contractStart'], 5, 2);
$month_min = substr($row['contractEnd'], 5, 2);
$period = array();
try {
if ($year_min > $year_max)
throw new Exception();
else if ($year_min == $year_max)
if ($month_min > $month_max)
throw new Exception();
for ($month = $month_min; $month <= $month_max; $month++) {
$period[] = $month . '-' . $year;
}
else {
for ($month = $month_min; $month <= 12; $month++) {
$period[] = $month . '-' . $year_min;
}
for ($year = $year_min + 1; $year < $year_max; $year++) {
for ($month = $month_min; $month <= $month_max; $month++) {
$period[] = $month . '-' . $year;
}
}
for ($month = 1; $month <= $month_max; $month++) {
$period[] = $month . '-' . $year_max;
}
}
implode("<br />\r\n", $period);
}
catch (Exception $e) {
echo 'Start date occurs after end date.'
}
That's for the hard way. Now there is a quick and easy way that is already given as an answer which I recommend you to choose.
This was my solution since DateTime is not available in my server environment.
$a = "2007-01-01";
$b = "2008-02-15";
$i = date("Ym", strtotime($a));
while($i <= date("Ym", strtotime($b))){
echo $i."\n";
if(substr($i, 4, 2) == "12")
$i = (date("Y", strtotime($i."01")) + 1)."01";
else
$i++;
}
Try it out: http://3v4l.org/BZOmb
In Laravel,
$period = \Carbon\CarbonPeriod::create('2017-06-28', '1 month', '2019-06-01');
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
October 2021 Update
If you have dates selected by the user, here's a solution
$from = date('Y-m-d', strtotime($_POST['from']));
$to = date('Y-m-d', strtotime($_POST['to']));
$counter = 1;
$max_date = strtotime($to);
$current_date = strtotime($from);
$dates = [];
$months = [];
$loop = true;
while($loop) {
if(strtotime(date('Y-m-d',$current_date)." +".$counter."days") >= $max_date) $loop = false;
else {
$current_date = strtotime(date('Y-m-d', $current_date)." +".$counter."days");
$date = date('Y-m-d', $current_date);
$dates[] = $date;
$months[] = date('Y-m', $current_date);
$counter++;
}
}
$months = array_unique($months);
echo '<pre>';
print_r($dates);
echo '<br>';
print_r($months);
echo '</pre>';
I'm trying to list all months between two dates.
For example; start date is: 2010-12-02 and last date is: 2012-05-06
I want to list something like this:
2010-12
2011-01
2011-02
2011-03
2011-04
.
.
.
2012-04
2012-05
This is what I have tried and it is not working at all:
$year_min = 2010;
$year_max = 2012;
$month_min = 12;
$month_max = 5;
for($y=$year_min; $y<=$year_max; $y++)
{
for($m=$month_min; $m<=$month_max; $m++)
{
$period[] = $y.$m;
}
}
PHP 5.3
$start = new DateTime('2010-12-02');
$start->modify('first day of this month');
$end = new DateTime('2012-05-06');
$end->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
See it in action
PHP 5.4 or newer
$start = (new DateTime('2010-12-02'))->modify('first day of this month');
$end = (new DateTime('2012-05-06'))->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
The part where we modify the start and end dates to the first of the month is important. If we didn't, and the current day higher then the last day in February (i.e. 28 in non-leap years, 29 in leap years) this would skip February.
function getMonthsInRange($startDate, $endDate)
{
$months = array();
while (strtotime($startDate) <= strtotime($endDate)) {
$months[] = array(
'year' => date('Y', strtotime($startDate)),
'month' => date('m', strtotime($startDate)),
);
// Set date to 1 so that new month is returned as the month changes.
$startDate = date('01 M Y', strtotime($startDate . '+ 1 month'));
}
return $months;
}
You must make a difference between two months of the same year and two months of different years.
$year_min = substr($row['contractStart'], 0, 4);
$year_max = substr($row['contractEnd'], 0, 4);
$month_min = substr($row['contractStart'], 5, 2);
$month_min = substr($row['contractEnd'], 5, 2);
$period = array();
try {
if ($year_min > $year_max)
throw new Exception();
else if ($year_min == $year_max)
if ($month_min > $month_max)
throw new Exception();
for ($month = $month_min; $month <= $month_max; $month++) {
$period[] = $month . '-' . $year;
}
else {
for ($month = $month_min; $month <= 12; $month++) {
$period[] = $month . '-' . $year_min;
}
for ($year = $year_min + 1; $year < $year_max; $year++) {
for ($month = $month_min; $month <= $month_max; $month++) {
$period[] = $month . '-' . $year;
}
}
for ($month = 1; $month <= $month_max; $month++) {
$period[] = $month . '-' . $year_max;
}
}
implode("<br />\r\n", $period);
}
catch (Exception $e) {
echo 'Start date occurs after end date.'
}
That's for the hard way. Now there is a quick and easy way that is already given as an answer which I recommend you to choose.
This was my solution since DateTime is not available in my server environment.
$a = "2007-01-01";
$b = "2008-02-15";
$i = date("Ym", strtotime($a));
while($i <= date("Ym", strtotime($b))){
echo $i."\n";
if(substr($i, 4, 2) == "12")
$i = (date("Y", strtotime($i."01")) + 1)."01";
else
$i++;
}
Try it out: http://3v4l.org/BZOmb
In Laravel,
$period = \Carbon\CarbonPeriod::create('2017-06-28', '1 month', '2019-06-01');
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
October 2021 Update
If you have dates selected by the user, here's a solution
$from = date('Y-m-d', strtotime($_POST['from']));
$to = date('Y-m-d', strtotime($_POST['to']));
$counter = 1;
$max_date = strtotime($to);
$current_date = strtotime($from);
$dates = [];
$months = [];
$loop = true;
while($loop) {
if(strtotime(date('Y-m-d',$current_date)." +".$counter."days") >= $max_date) $loop = false;
else {
$current_date = strtotime(date('Y-m-d', $current_date)." +".$counter."days");
$date = date('Y-m-d', $current_date);
$dates[] = $date;
$months[] = date('Y-m', $current_date);
$counter++;
}
}
$months = array_unique($months);
echo '<pre>';
print_r($dates);
echo '<br>';
print_r($months);
echo '</pre>';
I'm trying to list all months between two dates.
For example; start date is: 2010-12-02 and last date is: 2012-05-06
I want to list something like this:
2010-12
2011-01
2011-02
2011-03
2011-04
.
.
.
2012-04
2012-05
This is what I have tried and it is not working at all:
$year_min = 2010;
$year_max = 2012;
$month_min = 12;
$month_max = 5;
for($y=$year_min; $y<=$year_max; $y++)
{
for($m=$month_min; $m<=$month_max; $m++)
{
$period[] = $y.$m;
}
}
PHP 5.3
$start = new DateTime('2010-12-02');
$start->modify('first day of this month');
$end = new DateTime('2012-05-06');
$end->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
See it in action
PHP 5.4 or newer
$start = (new DateTime('2010-12-02'))->modify('first day of this month');
$end = (new DateTime('2012-05-06'))->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
The part where we modify the start and end dates to the first of the month is important. If we didn't, and the current day higher then the last day in February (i.e. 28 in non-leap years, 29 in leap years) this would skip February.
function getMonthsInRange($startDate, $endDate)
{
$months = array();
while (strtotime($startDate) <= strtotime($endDate)) {
$months[] = array(
'year' => date('Y', strtotime($startDate)),
'month' => date('m', strtotime($startDate)),
);
// Set date to 1 so that new month is returned as the month changes.
$startDate = date('01 M Y', strtotime($startDate . '+ 1 month'));
}
return $months;
}
You must make a difference between two months of the same year and two months of different years.
$year_min = substr($row['contractStart'], 0, 4);
$year_max = substr($row['contractEnd'], 0, 4);
$month_min = substr($row['contractStart'], 5, 2);
$month_min = substr($row['contractEnd'], 5, 2);
$period = array();
try {
if ($year_min > $year_max)
throw new Exception();
else if ($year_min == $year_max)
if ($month_min > $month_max)
throw new Exception();
for ($month = $month_min; $month <= $month_max; $month++) {
$period[] = $month . '-' . $year;
}
else {
for ($month = $month_min; $month <= 12; $month++) {
$period[] = $month . '-' . $year_min;
}
for ($year = $year_min + 1; $year < $year_max; $year++) {
for ($month = $month_min; $month <= $month_max; $month++) {
$period[] = $month . '-' . $year;
}
}
for ($month = 1; $month <= $month_max; $month++) {
$period[] = $month . '-' . $year_max;
}
}
implode("<br />\r\n", $period);
}
catch (Exception $e) {
echo 'Start date occurs after end date.'
}
That's for the hard way. Now there is a quick and easy way that is already given as an answer which I recommend you to choose.
This was my solution since DateTime is not available in my server environment.
$a = "2007-01-01";
$b = "2008-02-15";
$i = date("Ym", strtotime($a));
while($i <= date("Ym", strtotime($b))){
echo $i."\n";
if(substr($i, 4, 2) == "12")
$i = (date("Y", strtotime($i."01")) + 1)."01";
else
$i++;
}
Try it out: http://3v4l.org/BZOmb
In Laravel,
$period = \Carbon\CarbonPeriod::create('2017-06-28', '1 month', '2019-06-01');
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
October 2021 Update
If you have dates selected by the user, here's a solution
$from = date('Y-m-d', strtotime($_POST['from']));
$to = date('Y-m-d', strtotime($_POST['to']));
$counter = 1;
$max_date = strtotime($to);
$current_date = strtotime($from);
$dates = [];
$months = [];
$loop = true;
while($loop) {
if(strtotime(date('Y-m-d',$current_date)." +".$counter."days") >= $max_date) $loop = false;
else {
$current_date = strtotime(date('Y-m-d', $current_date)." +".$counter."days");
$date = date('Y-m-d', $current_date);
$dates[] = $date;
$months[] = date('Y-m', $current_date);
$counter++;
}
}
$months = array_unique($months);
echo '<pre>';
print_r($dates);
echo '<br>';
print_r($months);
echo '</pre>';