2

I have a period with startdate of 2016-12-26 and end date 2017-03-04.

Now I would like to find out how many days in each months there is, from a given period. Expected output from the above period dates (array):

2016-12: 5
2017-01: 31
2017-02: 28
2017-03: 4

How can I accomplish this cleanest way? I have tried to:

  1. first looking at the period_start, get the days = 26 and
  2. find out the start/end dates of the months between 2016-12 and 2017-03, to then calculate the days here (31 respectively 28 in february)
  3. then finally calculating the 4 days in 2017-03.

But is there any cleaner/better way?

Karem
  • 17,615
  • 72
  • 178
  • 278

5 Answers5

2

This can be achieved easily using the DateTime class. Create the objects, and use DateTime::diff() on them, then use the days property.

$start = new DateTime("2016-12-26");
$end = new DateTime("2017-03-04");

echo $start->diff($end)->days; // Output: 68

Live demo

Qirel
  • 25,449
  • 7
  • 45
  • 62
  • Thanks, but I look for a solution that breaks down the days into months rather than the sum for the whole period. – Karem Apr 24 '17 at 10:42
1

@Karem hope this logic will help you, this is working case for all your conditions please try this below one:

<?php
$startDate = '2016-12-26';
$endDate = '2017-03-04';
$varDate = $startDate;
while($varDate < $endDate){
    $d = date('d', strtotime($varDate));
    $Y = date('Y', strtotime($varDate));
    $m = date('m', strtotime($varDate));
    $days = cal_days_in_month(CAL_GREGORIAN,$m,$Y);
    $time = strtotime($varDate);
    if($varDate == $startDate){
        $time = strtotime(date('Y-m-01', $time));
        $days = $days - $d;
    }
    else if(date("Y-m", strtotime($varDate)) == date("Y-m", strtotime($endDate))){
        $days = date("j", strtotime($endDate));
    }
    echo date('Y-m', strtotime($varDate)). ": ".$days."<br>";
    $varDate = date('Y-m-d', strtotime("+1 month", $time));
}
lazyCoder
  • 2,544
  • 3
  • 22
  • 41
  • Thanks your for this! The per month is correct, but amount of days is wrong (26 should be 5, sorry for the mistake in question). So it should calculate how many days in there is in the month from 26th december (5). Also the static if($startDate == '2016-12-26' || $startDate == '2017-03-01') seems like a "quickfix" more than a proper solution that would work for any date periods – Karem Apr 24 '17 at 10:52
  • @Karem i have asked in the comment box, i thought it should be 26 ok let me update my answer – lazyCoder Apr 24 '17 at 10:54
  • 1
    @Karem please check my updated answer, this is according to you – lazyCoder Apr 24 '17 at 11:02
  • @ Niklesh i ll remember (y) – lazyCoder Apr 24 '17 at 12:48
1

This is long but easy to understand that how to achieve you your goal

<?php
  function getMonthDays($start,$end){
    if($start < $end){
      $start_time = strtotime($start);
      $last_day_of_start = strtotime(date("Y-m-t",$start_time));
      $start_month_days = ($last_day_of_start - $start_time)/(60*60*24);
      echo date("Y-m",$start_time).": ".$start_month_days."\n";
      $days = "";
      $start = date("Y-m-d", strtotime("+1 month", $start_time));
      $start_time = strtotime($start);
      while($start < $end){
        $month = date("m",$start_time);
        $year = date("Y",$start_time);
        $days = date('t', mktime(0, 0, 0, $month, 1, $year));
        echo date("Y-m",$start_time).": ".$days."\n";
        $start = date("Y-m-d", strtotime("+1 month", $start_time));
        $start_time = strtotime($start);
      }
      echo date("Y-m",strtotime($end)).": ".date("d",strtotime($end))."\n";

    }else{
      echo "Wrong Input";
    }
  }
  getMonthDays('2016-12-26','2017-03-04');
?>

live demo : https://eval.in/781724

Function returns array : https://eval.in/781741

Niklesh Raut
  • 34,013
  • 16
  • 75
  • 109
  • I like this solution. Thank you for contribution. But why +1 month? Case: if period_start is the same as period_end, it should be 0 days. Case 2: getMonthDays('2016-12-26','2016-12-27'); fails – Karem Apr 25 '17 at 09:09
  • Great, thanks for this! Makes sense. Any way the day can be counted aswell? getMonthDays('2016-12-26','2016-12-27'); should return 2, not 1. – Karem Apr 25 '17 at 11:44
0
<?php
$d1 = strtotime('2016-12-26');
$d2 = strtotime('2017-03-04');
echo floor(($d2 - $d1)/(60*60*24));
?>
Gopi Chand
  • 164
  • 6
  • Whilst this code snippet is welcome, and may provide some help, it would be [greatly improved if it included an explanation](//meta.stackexchange.com/q/114762) of *how* it addresses the question. Without that, your answer has much less educational value - remember that you are answering the question for readers in the future, not just the person asking now! Please [edit] your answer to add explanation, and give an indication of what limitations and assumptions apply. In particular, how does this code produce a line for each month? – Toby Speight Apr 24 '17 at 11:48
0

i used Carbon (https://carbon.nesbot.com/docs/) but you can do it with any other time lib.

$startDate = Carbon::createFromFormat('!Y-m-d', '2017-01-11');;
$endDate = Carbon::createFromFormat('!Y-m-d', '2018-11-13');;

$diffInMonths = $endDate->diffInMonths($startDate);

for ($i = 0; $i <= $diffInMonths; $i++) {
    $start = $i == 0 ? $startDate->copy()->addMonth($i) : $startDate->copy()->addMonth($i)->firstOfMonth();
    $end = $diffInMonths == $i ? $endDate->copy() : $start->copy()->endOfMonth();

    echo $end->format('Y-m') . ' ' . ($end->diffInDays($start) + 1) . PHP_EOL;
}