Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 12 of 12
  1. #1
    New Coder
    Join Date
    Apr 2012
    Posts
    22
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Add the correct number of days for each month to this function

    Using the following function I can display the years and months between two dates, but how can I add the correct days for each month as another array within each month? I can't just add the days manually as I need it to account for leap years etc.
    PHP Code:
    function yearMonth($start_date$end_date)
    {
        
    $begin = new DateTime$start_date );
        
    $end = new DateTime$end_date);
        
    $interval = new DateInterval('P1M'); // 1 month interval

        
    $period = new DatePeriod($begin$interval$end);

        foreach ( 
    $period as $dt )
            
    $years[$dt->format"Y" )][] = $dt->format"F" );

        return 
    $years;
    }

    $list  =  yearMonth("2007-03-24""2009-06-26");
    var_dump($list); 

  • #2
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    I'm not sure I understand the question. Are you just wanting the absolute number of days different? If so, the dateInterval contains that:
    PHP Code:
    $start '2007-03-24';
    $end '2009-06-26';
    $dtStart = new DateTime($start);
    $dtEnd = new DateTime($end);
    $diDiff $dtStart->diff($dtEnd);
    printf($diDiff->format('%a days')); 
    Also retrievable from the $diDiff->days attribute.

    Edit:
    Or wait, do you want to actually create an array of days below the months?
    PHP Code:
    function yearMonth($start_date$end_date)
    {
        
    $begin = new DateTime$start_date );
        
    $end = new DateTime$end_date);
        
    $interval = new DateInterval('P1D'); // 1 month interval

        
    $period = new DatePeriod($begin$interval$end);

        
    $lastMonth null;
        
    $lastYear null;
        
    $aResult = array();
        foreach ( 
    $period as $dt )
        {
            if (
    $dt->format('Y') != $lastYear)
            {
                
    $lastYear $dt->format('Y');
            }
            if (
    $dt->format('F') != $lastMonth)
            {
                
    $lastMonth $dt->format('F');
            }
            if (!isset(
    $aResult[$lastYear]))
            {
                
    $aResult[$lastYear] = array();
            }
            if (!isset(
    $aResult[$lastYear][$lastMonth]))
            {
                
    $aResult[$lastYear][$lastMonth] = array();
            }
            
    $aResult[$lastYear][$lastMonth][] = $dt->format('d');
        }

        return 
    $aResult;

    Like that?

    Also, manual isn't hard. Days in the month don't change except for february which can be calculated based off of the modulus % 4 and ! %100 unless %400 applies.
    Last edited by Fou-Lu; 10-08-2013 at 07:50 PM.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)

  • #3
    New Coder
    Join Date
    Apr 2012
    Posts
    22
    Thanks
    1
    Thanked 0 Times in 0 Posts
    No I need correct amount of days as an array inside the months. for example the output of the current code is as follows:

    Code:
    array (size=3)
      2007 => 
        array (size=10)
          0 => string 'March' (length=5)
          1 => string 'April' (length=5)
          2 => string 'May' (length=3)
          3 => string 'June' (length=4)
          4 => string 'July' (length=4)
          5 => string 'August' (length=6)
          6 => string 'September' (length=9)
          7 => string 'October' (length=7)
          8 => string 'November' (length=8)
          9 => string 'December' (length=8)
      2008 => 
        array (size=12)
          0 => string 'January' (length=7)
          1 => string 'February' (length=8)
          2 => string 'March' (length=5)
          3 => string 'April' (length=5)
          4 => string 'May' (length=3)
          5 => string 'June' (length=4)
          6 => string 'July' (length=4)
          7 => string 'August' (length=6)
          8 => string 'September' (length=9)
          9 => string 'October' (length=7)
          10 => string 'November' (length=8)
          11 => string 'December' (length=8)
      2009 => 
        array (size=6)
          0 => string 'January' (length=7)
          1 => string 'February' (length=8)
          2 => string 'March' (length=5)
          3 => string 'April' (length=5)
          4 => string 'May' (length=3)
          5 => string 'June' (length=4)
    I would like :

    Code:
     2009 => 
        array (size=6)
        0 =>  'January' =>
                      array
                            0 => 1
                            2 => 2 
                           ... and so on
    the amount of days in the months has to be correct for that year as some years are leap years.

    Make sense now?

  • #4
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    Yep, see my above edit.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)

  • #5
    New Coder
    Join Date
    Apr 2012
    Posts
    22
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Thanks that appears to be exactly what I was looking for. I know the manual aint hard, I was just kinda having a mental block with this one plus iv never really tried to do something with dates like that before.

    On a side note I am planing to create a sort of Gantt chart style flat layout in table format of the years, months and days between dates. Do you think this is a suitable way of generating that? Or is there a better way?

  • #6
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    I don't. Not with the capturing of data that is.
    The DatePeriod itself is probably the most useful part of what you want to use. Coupled with being a traversable type, it is exceedingly powerful.
    You needn't really pick out the numbers and put them in arrays. You can use standard mathematical functions with the datetime types. Its super nice.
    For a gantt chart, effectively you have two major things to look at: the first being the range to display, and the second being a record to render on it. Lets just use a week for an example.

    PHP Code:
    $dtStart = new DateTime('October 6, 2013');
    $dtEnd = new DateTime('October 12, 2013 23:59:59');

    $dtItemStart = new DateTime('October 8, 2013');
    $dtItemEnd = new DateTime('October 10, 2013');

    $di = new DateInterval('PT1H');
    $dp = new DatePeriod($dtStart$di$dtEnd);
    // we'll just make a happy table.
    printf('<table border="1"><tr>');
    foreach (
    $dp AS $p)
    {
        if ((
    $p >= $dtItemStart && $p <= $dtItemEnd) || ($p <= $dtItemStart && $p >= $dtItemEnd))
        {
            
    // this time falls within this range.
            
    printf('<td style="background-color: red;">%s</td>'$p->format('m/j h:i'));
        }
        else
        {
            
    printf('<td>%s</td>'$p->format('m/j h:i'));
        }
        
    $prev $p;
    }
    printf('</tr></table>'); 
    Pretty crude example (and not heavily tested except for codepad ), but that looks to overlap properly.
    What you would do is make an array of events or records, and then you would probably keep track of the smallest and largest numbers. That would be your start and end parameters.
    Make a for loop of the number of records you have to show, and drop the foreach for the dateperiod within that. Use array_shift to get the record and colour it, and eventually it should cycle down to nothing.
    It should give the exact behaviour you want, and take pretty much the exact time as capturing. The difference is you don't waste memory with the captures, so it should ultimately be faster to do this.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)

  • Users who have thanked Fou-Lu for this post:

    recci (10-09-2013)

  • #7
    New Coder
    Join Date
    Apr 2012
    Posts
    22
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Thanks for the advice man. My plan was just to use the first array to generate the grid between the start and end of the project plan. I was then going to use jquery/javascript to plot the actual event onto the background grid. I haven't figured out how I would do that as yet although the chart will be manually editable using jquery in the browser and use hidden fields to save the resulting chart back to the database.

    Its little pet project of mine, it may take me months to finish it.

  • #8
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    If you have a JQuery library to do the gantt, than you may indeed need to capture and provide a json compatible array.
    It really comes down to what you have, and what you want. If you want it serverside, than I'd say stick with an iteration of just what you need to do instead of capturing. If you want the clientside, and have a suitable library (or know what you want to do), than sending the data in json makes more sense, but requires it to be captured.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)

  • #9
    New Coder
    Join Date
    Apr 2012
    Posts
    22
    Thanks
    1
    Thanked 0 Times in 0 Posts
    I'm not using a jquery library, I just want to be able to plot the task durations using jquery onto a server side generated grid. This is so the task durations can be updated in real time and the user will see the duration bar animate etc..

    Also I'm having a bit of trouble understanding the array short hand, in this line:

    PHP Code:
    $aResult[$dt->format('Y')][$dt->format('F')][$dt->format('d')] = $dt->format('D'); 
    I am trying to add the day number as the key and the first 3 letters of the day as the value. So that I have which day of the month it is and the day name but its turning out with quotes round the first 8 keys from the second month in, like so:

    Code:
    array (size=3)
      2007 => 
        array (size=10)
          'March' => 
            array (size=8)
              24 => string 'Sat' (length=3)
              25 => string 'Sun' (length=3)
              26 => string 'Mon' (length=3)
              27 => string 'Tue' (length=3)
              28 => string 'Wed' (length=3)
              29 => string 'Thu' (length=3)
              30 => string 'Fri' (length=3)
              31 => string 'Sat' (length=3)
          'April' => 
            array (size=30)
              '01' => string 'Sun' (length=3)
              '02' => string 'Mon' (length=3)
              '03' => string 'Tue' (length=3)
              '04' => string 'Wed' (length=3)
              '05' => string 'Thu' (length=3)
              '06' => string 'Fri' (length=3)
              '07' => string 'Sat' (length=3)
              '08' => string 'Sun' (length=3)
              '09' => string 'Mon' (length=3)
              10 => string 'Tue' (length=3)
              11 => string 'Wed' (length=3)
              12 => string 'Thu' (length=3)
              13 => string 'Fri' (length=3)
              14 => string 'Sat' (length=3)
              15 => string 'Sun' (length=3)
              16 => string 'Mon' (length=3)
              17 => string 'Tue' (length=3)
              18 => string 'Wed' (length=3)
              19 => string 'Thu' (length=3)
              20 => string 'Fri' (length=3)
              21 => string 'Sat' (length=3)
              22 => string 'Sun' (length=3)
              23 => string 'Mon' (length=3)
              24 => string 'Tue' (length=3)
              25 => string 'Wed' (length=3)
              26 => string 'Thu' (length=3)
              27 => string 'Fri' (length=3)
              28 => string 'Sat' (length=3)
              29 => string 'Sun' (length=3)
              30 => string 'Mon' (length=3)
          'May' => 
            array (size=31)
              '01' => string 'Tue' (length=3)
              '02' => string 'Wed' (length=3)
              '03' => string 'Thu' (length=3)
              '04' => string 'Fri' (length=3)
              '05' => string 'Sat' (length=3)
              '06' => string 'Sun' (length=3)
              '07' => string 'Mon' (length=3)
              '08' => string 'Tue' (length=3)
              '09' => string 'Wed' (length=3)
              10 => string 'Thu' (length=3)
              11 => string 'Fri' (length=3)
              12 => string 'Sat' (length=3)
              13 => string 'Sun' (length=3)
              14 => string 'Mon' (length=3)
              15 => string 'Tue' (length=3)
              16 => string 'Wed' (length=3)
              17 => string 'Thu' (length=3)
    Any ideas?

  • #10
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    Use 'j' instead of 'd' in the last $dt->format call. d is a format for a two digit day of the month, and j is for one or two digit. The first 9 require the key to be associative, otherwise it would be interpreted as an octal number (for which 09 cannot exist). Using j should eliminate that problem.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)

  • #11
    New Coder
    Join Date
    Apr 2012
    Posts
    22
    Thanks
    1
    Thanked 0 Times in 0 Posts
    ahh ofcourse, I was thinking there was a problem with the array for some reason.

  • #12
    New Coder
    Join Date
    Apr 2012
    Posts
    22
    Thanks
    1
    Thanked 0 Times in 0 Posts
    This the calendar grid I envisaged, got it eventually. Any ideas to improve it and how to go about plotting the dates for tasks with Jquery onto this grid.
    Edit: actually I have figured out how to plot the dates with jquery.

    The class:
    PHP Code:
    class Gantt {

        private 
    $start_date;
        private 
    $end_date;
        private 
    $tasks;

        public function 
    __construct($start_date$end_date$tasks)
        {
            
    $this->start_date $start_date;
            
    $this->end_date $end_date;
            
    $this->tasks $tasks;
            
    //draw the grid
            
    $this->draw($this->start_date$this->end_date$this->tasks);
        }

        public function 
    draw($start_date$end_date$tasks){

            
    $time_span $this->year_month($start_date$end_date);
            
    $day_count $this->count_days($start_date$end_date);
            
    $project_length $this->time_range($start_date$end_date);
            echo 
    $project_length;

            echo 
    '<table class="main_table"><tr>';

            echo 
    '<td class="side_bar1"><div></div></td><td class="side_bar2"><div></div></td>';

            foreach(
    $time_span as $year => $months) {

                echo 
    '<td class=" main_table years" colspan="'.count($months).'">'.$year.'</td>';
            }

            echo 
    '</tr><tr>';
            echo 
    '<td class="side_bar1"><div></div></td><td class="side_bar2"><div></div></td>';

            foreach(
    $time_span as $months) {

                foreach(
    $months as $month => $days){
                    echo 
    '<td class="main_table years months">'.$month.'</td>';
                }
            }
            echo 
    '</tr><tr>';
            echo 
    '<td><div></div></td><td class="side_bar2"><div></div></td>';
            
    $month_count 0;//start month count
            
    foreach($time_span as $months) {
                
    $m=0;
                foreach(
    $months as $days){

                    echo 
    '<td class="inner_container"><table class="main_table table_inner"><tr>';
                    
    $i=0;
                    foreach(
    $days as $day => $d){
                        if(
    $i == 0){
                            echo 
    '<td class="no-b"><div class="cell_width">'.$day.'</div></td>';
                        }
                        else {
                            echo 
    '<td class="inner_td"><div class="cell_width">'.$day.'</div></td>';
                        }
                        
    $i++;
                    }
                    echo 
    '</tr>';
                    echo 
    '<tr>';
                    
    $i=0;
                    foreach(
    $days as $d){
                        if(
    $d == 0){
                            echo 
    '<td class="no-b2"><div class="cell_width">'.$d[0].'</div></td>';
                        }
                        else {
                            echo 
    '<td class="inner_td2"><div class="cell_width">'.$d[0].'</div></td>';
                        }
                        
    $i++;
                    }
                    echo 
    '</tr></table></td>';
                    
    $m++;
                }

                
    $month_count += $m//total month count
            
    }

            foreach(
    $tasks as $task){

                echo 
    '</tr><tr><td class="task_bar1">'.$task.'</td><td class="task_bar2"></td><td class="no-b2" colspan="'.$month_count.'"><table class="main_table table_inner"><tr>';

                for (
    $x=0$x$day_count$x++)
                {
                    if(
    $x==0){
                        echo 
    '<td class="no-b"><div class="cell_width day_block"></div></td>';
                    }
                    else{
                        echo 
    '<td class="inner_td"><div class="cell_width day_block"></div></td>';
                    }

                }

                echo 
    '</tr></table ></td></tr>';
            }

            echo 
    '</table>';
        }


        
    //Returns an array containing the years, months and days between two dates
        
    public function year_month($start_date$end_date)
        {
            
    $begin = new DateTime$start_date );
            
    $end = new DateTime$end_date);
            
    $interval = new DateInterval('P1D'); // 1 month interval
            
    $period = new DatePeriod($begin$interval$end);
            
    $aResult = array();

            foreach ( 
    $period as $dt )
            {
                
    $aResult[$dt->format('Y')][$dt->format('F')][$dt->format('j')] = $dt->format('D');
            }

            return 
    $aResult;
        }

        
    //Returns the total number of days between two dates
        
    public function count_days($start_date$end_date){

            
    $d1 = new DateTime($start_date);
            
    $d2 = new DateTime($end_date);
            
    $difference $d1->diff($d2);
            return 
    $difference->days;

        }
        
    //Returns the time span between two dates in years  months and days
        
    public function time_range($start_date$end_date){

            
    $datetime1 = new DateTime($start_date);
            
    $datetime2 = new DateTime($end_date);
            
    $interval $datetime1->diff($datetime2);
            echo 
    $interval->format('%y years %m months and %d days');
        }


    The style sheet for it
    Code:
    .main_table {
        border: 1px solid #DDDDDD;
        border-collapse: collapse;
        background-color: #F6F6F6;
        color: #484A4D;
        font-family: Helvetica,Arial,sans-serif;
        line-height: 24px;
        font-size:12px;
    
    
    }
    .main_table th, td {
        padding: 0px;
        overflow: hidden;
        width: 24px;
    }
    .years {
        text-align:center;
        font-size:13px;
        font-weight: bold;
    }
    .months {
    
    }
    .inner_container {
        border-left:0;
    }
    .table_inner {
        border: 0;
        table-layout: fixed;
    }
    .no-b {
        border: 1px solid #DDDDDD;
        text-align:center;
        border-bottom:0;
        border-top:0;
        border-left:0;
    }
    .no-b2 {
        border: 1px solid #DDDDDD;
        text-align:center;
        border-bottom:0;
    }
    
    .inner_td {
        text-align:center;
        border: 1px solid #DDDDDD;
        border-bottom:0;
        border-top:0;
    
    }
    .inner_td2 {
        text-align:center;
        border: 1px solid #DDDDDD;
        border-bottom:0;
    }
    .cell_width{
        width: 25px;
        height:23px;
    }
    .side_bar1 div {
        width:110px;
    }
    .side_bar1 {
    
    }
    .side_bar2 div {
        width:120px;
    
    }
    .side_bar2 {
        border-right: 1px solid #DDDDDD;
    }
    .task_bar1, .task_bar2 {
        border-top: 1px solid #DDDDDD;
        padding-left:5px;
        font-weight: bold;
    }
    .day_block {
        background-color: #ffffff;
    }
    The main display page
    Code:
    <link rel="stylesheet" type="text/css" href="style.css" />
    <?php
    /**
     * Created by JetBrains PhpStorm.
     * User: Andy
     * Date: 11/10/13
     * Time: 00:51
     * To change this template use File | Settings | File Templates.
     */
    include('gantt.php');
    
    $tasks[0] = 'task1';
    $tasks[1] = 'task2';
    $tasks[3] = 'task3';
    
    $gantt1 = new Gantt('2007-03-24', '2007-06-26', $tasks);
    
    echo '<br />';
    
    $gantt2 = new Gantt('2007-03-24', '2009-04-26', $tasks);
    Last edited by recci; 10-12-2013 at 02:07 AM.


  •  

    Tags for this Thread

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •