PHP: Difference in Dates Using Zend_Date

December 4th, 2008 by Richy B. Leave a reply »

I’ve had to write some code recently that handles peoples ages based on their date of births… Something simple you expect, until you realise that PHP can’t really deal with years before 1970 (due to UNIX date time restrictions). Luckily Zend_Date (in the Zend Framework) comes to hand to help!

But how do you actually turn a date in the format YYYY-MM-DD into a difference in years? Well, here’s how! We’re relying on the date to be consistently 10 characters long in the format YYYY-MM-DD with any unused date “zerod” out (for example, if we are using OpenID which allows people to “hide” parts of their DOB):

if (preg_match('/^([1-2][0-9][0-9][0-9])\-([0-1][0-9])\-([0-3][0-9])$/',$sDob,$aMatches)) {
    $iYear=$aMatches[1];
    $iMonth=$aMatches[2];
    if ($iMonth<1 || $iMonth>12) {
        // Set a minimum/standard month for this calculation
        $iMonth=1;
    }//end if ($iMonth<1 || $iMonth>12) {
    $iDay=$aMatches[3];
    if ($iDay<1 || $iDay>31) {
        // Set a minimum/standard day of the month for this calculation
        $iDay=1;
    }//end if ($iDay<1 || $iDay>31) {
    // If anybody was born before 1850 or after 3,000 (say they have a time machine)
    // then, sorry, they'll have to check their date of birth elsewhere!
    if ($iYear>1850 && $iYear<3000) {         if (checkdate($iMonth,$iDay,$iYear)) {             $cNowDate=new Zend_Date();             $cUserDate=new Zend_Date(Array('year'=>$iYear,'month'=>$iMonth,'day'=>$iDay));
            // Sanity check that the date the user entered is actually in the past!
            // No future time travellers welcome here!
            if ($cNowDate->isLater($cUserDate)) {
                $cDifference=$cNowDate->subDate($cUserDate);
                $aDifference=$cDifference->toArray();
                print 'Year difference is:'.$aDifference['year'];
            }//end if ($cNowDate->isLater($cUserDate)) {
        }//end if (checkdate($iMonth,$iDay,$iYear)) {
    }//end if ($iYear>1850 && $iYear<3000) {  }//end if (preg_match

This post is over 6 months old.

This means that, despite my best intentions, it may no longer be accurate.

This blog holds over 12 years of archived content - during that time, I may have changed my opinion of something, technology will have advanced (and old "best standards" may no longer be the case), my technology "know how" has improved etc etc - it would probably take me a considerable amount of time to update all the archival entries: and defeat the point of keeping them anyway.

Please take these posts for what they are: a brief look into my past, my history, my journey and "caveat emptor".

1 comment

  1. Hi Richy,

    I discovered a problem when subtracting dates. Try setting $cUserDate to a date which is exactly one day after $cNowDate. The value $aDifference[‘year’] will not be correct. This is because subtracting dates in this way is not reliable and was not made for this purpose.

    I used a different approach. If I want to check if a user is at least 18 years old, then I add 18 years to the birthdate with $cUserDate->add(18, Zend_Date::YEAR) and then I check the result using $cNowDate->isEarlier($cUserDate)

    Hope this helps you and others reading this blog.

    Cya,
    Patrick

Leave a Reply

gamy-dance
%d bloggers like this: