Help with subtracting dates
Results 1 to 12 of 12

Thread: Help with subtracting dates

  1. #1
    Senior Member
    Join Date
    Sep 2012
    Posts
    269

    Angry Help with subtracting dates

    I have an end date and a start date, which is six days lower than the start date. i.e:

    PHP Code:
    $ExpDate = (explode("-",$ReportDate));

            
    $EndMonth $ExpDate[0];
            
    $EndDay $ExpDate[1];
            
    $EndYear $ExpDate[2];
            
    $ShortYear $EndYear;
            
            if(
    $EndYear<2000$EndYear $EndYear 2000;
            if(
    strlen($EndMonth) < 2$EndMonth "0" $EndMonth;
            if(
    strlen($EndDay) < 2$EndDay "0" $EndDate;
            

            
    $EndDate $EndYear '-' $EndMonth '-' $EndDay;
        
               
    $StartMonth $EndMonth;
                   
    $StartDay $EndDay 6
    This works fine until $StartDay is less than 1. Then I have:

    PHP Code:
        if ($StartDay 1)
            {
            
    $StartMonth $StartMonth 1;
            
    $num cal_days_in_month(CAL_GREGORIAN$StartMonth$StartYear);
            
    $StartDay $num $StartDay;
            } 

    All totaled, I have 6 'if' statements to manipulate the day month and year. I have also tried various and sundry manipulations of the date-time stamp and still need all the 'if' statements.

    I do not understand the '$strtotime' function well enough to get the desired outcome.

    So how can I get from '8-4-12' - 6 days = 2012-07-29 ? Is there a way to do this without all the math?

    Could someone point me in the right direction?

    ty

    tim

  2. #2
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    try the DateTime class.

    PHP Code:
    <?php

    $date 
    = new DateTime'08-04-12' );  // start date 
    //  !! (this format might not be interpreted correctly, however, based on your locale)
    $interval = new DateTimeInterval'P6D' );  // 6 days
    $date->sub$interval );  // subtract 6 days

    print $date->format'Y-m-d' );
    Last edited by traq; 12-29-2012 at 10:43 PM.

  3. #3
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Systems Vehicle "Thrilled To Be Here"
    Posts
    21,773
    Quote Originally Posted by timstring
    I do not understand the '$strtotime' function well enough to get the desired outcome.
    The comment traq gives about "08-04-12" is related to this. That is a very poor way of representing dates, since there are at least three common ways of interpreting it: as 8 April 2012, 4 August 2012, or 12 April 2008 (assuming it refers to the 21st century); strtotime takes the last interpretation. Much better is the form you convert it into (which is the industry standard): they should be stored that way to start with.

    Do you have any control over the format in which you receive the date?
    Last edited by Weedpacket; 12-29-2012 at 10:14 PM.
    THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER
    FAQs! FAQs! FAQs! Most forums have them!
    Search - Debugging 101 - Collected Solutions - General Guidelines - Getting help at all

  4. #4
    Senior Member
    Join Date
    Sep 2012
    Posts
    269
    No, I have no control over the dates, except that the program producing my reports dumps the data into an Excel (egad) spreadsheet and I change the date format before I import the resultant 'CSV' file into my database. The dates are stored in MySQL as yyyy-mm-dd.

    Let me take a step back. The user enters the end date as the American standard m-d-yy, as instructed in the entry form. Manipulating that string into into the ISO format is relatively easy:

    PHP Code:
            $ExpDate = (explode("-",$ReportDate));

            
    $EndMonth $ExpDate[0];
            
    $EndDay $ExpDate[1];
            
    $EndYear $ExpDate[2];
            
    $ShortYear $EndYear;
            
            if(
    $EndYear<2000$EndYear $EndYear 2000;
            if(
    strlen($EndMonth) < 2$EndMonth "0" $EndMonth;
            if(
    strlen($EndDay) < 2$EndDay "0" $EndDate;
            

            
    $EndDate $EndYear '-' $EndMonth '-' $EndDay
    The difference between $StartDate and $EndDate is 6 days. The problem is going calculating the intermediate dates from $StartDate to $EndDate if $StartDate happens to fall in the month, or even year, or, oh heavens, a leap day previous to the $EndDate.

  5. #5
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    Quote Originally Posted by timstring View Post
    ...The user enters the end date as the American standard m-d-yy, as instructed in the entry form. Manipulating that string into into the ISO format is relatively easy
    ...but is insuring that the user entered the string correctly (e.g., you know that they meant August 4 and not April 8) also easy?

    In any case, if you can convert it reliably, then DateTime is a perfect solution. It takes all of the issues you mention (month breaks, leap days, etc.) into account.

    The example I gave omits the $timezone param, so will use your system's default. Since you are only considering dates (not times), and you're starting out with a date string, this might work out all right. I'd recommend setting the tz explicitly, however, for flexibility (and to avoid any future complications).
    Last edited by traq; 12-29-2012 at 10:51 PM.

  6. #6
    Senior Member
    Join Date
    Sep 2012
    Posts
    269

    Exclamation

    Quote Originally Posted by traq View Post
    try the DateTime class.

    PHP Code:
    <?php

    $date 
    = new DateTime'08-04-12' );  // start date 
    //  !! (this format might not be interpreted correctly, however, based on your locale)
    $interval = new DateTimeInterval'P6D' );  // 6 days
    $date->sub$interval );  // subtract 6 days

    print $date->format'Y-m-d' );
    I copied and pasted your script into mine, and the server says "Fatal error: Class 'DateTimeInterval' not found in /Applications/XAMPP/xamppfiles/htdocs/WeeklyReport.php on line 208, which is the '$interval' formula. So, don't ask me why, but this did not have an error

    PHP Code:
    $date = new DateTime($EndDate);
    $date->sub(new DateInterval('P6D'));
    echo 
    $date->format('Y-m-d') . "\n"
    This works, but again, don't ask me why. How, then, do I go from '$date->format(Y-m-d)" to an actual variable?
    Last edited by timstring; 12-30-2012 at 01:59 AM.

  7. #7
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Systems Vehicle "Thrilled To Be Here"
    Posts
    21,773
    Quote Originally Posted by timstring
    I copied and pasted your script into mine,
    Cut and paste code never works. Checking the manual, it should be DateInterval.

    How, then, do I go from '$date->format(Y-m-d)" to an actual variable?
    What does this mean? You want to know how to put a value into a variable?
    THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER
    FAQs! FAQs! FAQs! Most forums have them!
    Search - Debugging 101 - Collected Solutions - General Guidelines - Getting help at all

  8. #8
    Senior Member
    Join Date
    Sep 2012
    Posts
    269
    Quote Originally Posted by Weedpacket View Post
    Cut and paste code never works. Checking the manual, it should be DateInterval
    .

    Funny, HaHa. You must be joking. You must be running Vista. I have been cutting and pasting on a Mac since 1987, and haven't had any problems other than operator error. I have never had a problem cutting and pasting code, even yours. I copied and pasted the script that worked from php.net.

    [QUOTE}What does this mean? You want to know how to put a value into a variable?[/QUOTE]

    I do believe that's what I asked. How do I get from

    PHP Code:
    $date->format('Y-m-d') . "\n"
    to

    PHP Code:
    $x somefunction('$date->format('Y-m-d')) . "\n"'
    While I have your attention, how do I accomplish this?:

    PHP Code:
    for ($counter=1$counter <= 7$counter++)
                    {
                        
    $date = new DateTime($EndDate);
                        
                        
    $test "('P" $counter "D')";
                        echo 
    $date->sub(new DateInterval($test);
                        echo 
    $date->format('Y-m-d') . "\n";

                    } 
    Thanks for the help,
    tim
    Last edited by timstring; 12-30-2012 at 10:19 AM.

  9. #9
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    what weedpacket is implying (and he's correct) is that I made a typo. The name of the class is DateInterval.

    As for how to set the value in a variable, you'd do it just like normal:
    PHP Code:
    $x $date->format'Y-m-d' ); 
    $x would hold the string "2012-08-04", of course, not the date object itself. I don't know if that's what you wanted or not.

    for your loop, you don't need to increment the interval, since datetime.sub changes the date in $date. e.g.,
    PHP Code:
    $date = new DateTime'2012-08-04' );
    $oneday = new DateInterval'P1D' );
    print 
    $date->sub$oneday )->format'Y-m-d' );  // prints "2012-08-03"
    print $date->sub$oneday )->format'Y-m-d' );  // prints "2012-08-02"
    //  . . . etc. 

  10. #10
    Senior Member
    Join Date
    Sep 2012
    Posts
    269
    Quote Originally Posted by traq View Post
    what weedpacket is implying (and he's correct) is that I made a typo. The name of the class is DateInterval.

    I am so near-sited, both mentally and visually, that I didn't make the connection

    As for how to set the value in a variable, you'd do it just like normal:
    PHP Code:
    $x $date->format'Y-m-d' ); 
    $x would hold the string "2012-08-04", of course, not the date object itself. I don't know if that's what you wanted or not.

    for your loop, you don't need to increment the interval, since datetime.sub changes the date in $date. e.g.,
    PHP Code:
    $date = new DateTime'2012-08-04' );
    $oneday = new DateInterval'P1D' );
    print 
    $date->sub$oneday )->format'Y-m-d' );  // prints "2012-08-03"
    print $date->sub$oneday )->format'Y-m-d' );  // prints "2012-08-02"
    //  . . . etc. 
    I do need the counter because I'm not only figuring the date, I'm constructing an array with the counter, too. Also, it condenses 8 lines of code down to 4.

    Here's what I blundered into:
    PHP Code:
    for ($counter=0$counter <= 6$counter++)
                    {
                        
    $date date_create($EndDate);
                        
    date_sub($datedate_interval_create_from_date_string($counter 'days'));
                        
    $IncDate date_format($date'Y-m-d');
                        

                                        
                        
    $Quest "SELECT * FROM `$System` WHERE TechNum = '$TechNum' && WorkDate = '$IncDate'";
                         
    $result mysql_query($Quest$cxn)
                            or die (
    'the bear went over the mountain  ' mysql_error());
                        
        
    ..
    more code..
    ..
    more code...

                                       } 
    Doing this eliminated 18 lines of code:

    PHP Code:
    for ($counter=0$counter <= 6$counter++)
                    {
                        
    $date date_create($EndDate);
                        
    date_sub($datedate_interval_create_from_date_string($counter 'days'));
                        
    $W["$counter"] = date_format($date"D");
                        
    $D["$counter"] = date_format($date"n-j");
                        echo 
    $counter ' ** ' $W["$counter"] . ' ## ' $D["$counter"] . '<br>';
                    }        

    ..
    more code..more code

    for ($counter=0$counter<=6$counter++)
                        {
                      echo 
    '<th style = "width:40px">'  $W["$counter"] . '<br>' $D["$counter"] . '</th>';
                     } 
    Thanks very much for the hints. They pointed me where I needed to go.
    Last edited by timstring; 12-30-2012 at 02:49 PM.

  11. #11
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Systems Vehicle "Thrilled To Be Here"
    Posts
    21,773
    Quote Originally Posted by timstring
    haven't had any problems
    You cut and posted code from here and had a problem.
    other than operator error
    And that's why you had a problem.

    Copying a piece of code without reading it to understand what it even does (let alone verify that it does what you even want), and not checking for any typos that it may contain.
    Last edited by Weedpacket; 12-30-2012 at 05:45 PM.
    THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER
    FAQs! FAQs! FAQs! Most forums have them!
    Search - Debugging 101 - Collected Solutions - General Guidelines - Getting help at all

  12. #12
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    ...I didn't suggest you didn't need the counter; I said you didn't need to increment the date interval. You can simply put that one call to $date->sub() in the loop for however many iterations you like.

    Aside from that, however, can I ask if you're trying to find records within a certain date range? If so, you're following the wrong approach.

    Is WorkDate a DATETIME field?
    Code:
    SELECT whatever FROM table WHERE WorkDate BETWEEN {start} AND {end}

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

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
  •