views:

34

answers:

5

Hi,

I have a MySQL DATETIME field that holds the date of birth of a user. I want to use that date to display the age the user in years.

Is there a method of the Time core helper to do this?

Also, why when you add a DATETIME field to a form in Cake does it not let you select a date less than 1990?

Thanks,

Jonesy

+2  A: 

timeAgoinWords() may do what you want for the first part. Check out the Book

This has to do with the automagic form fields. You can adjust the year range with options. Check out the Book.

Jason McCreary
+1  A: 

You can perform the calculation using standard PHP funtions - look in the date section. I'm not going to tell you how to do it because you'll learn a huge amount by doing it yourself.

I will say that you need to be careful to get an accurate result. 365 days is not always a year and a month has a variable number of days.

You can configure the date selection range in the Cake form helper.

Leo
you are totally right Leo, the basics are required always
Nik
+3  A: 

the function is called timeAgoInWords

<?php echo $this->Time->timeAgoInWords(
      '1975-12-29 13:40', 
      array(
            'end'=>'+150 years'
      )
);?>

The end parameter mean to display the time ago with words until the date is less than 150 years (at least I haven't heard of 150yo man :)))).

The current result is: born: before 34 years, 9 months, 4 weeks

But also check API and CookBook as Jason suggest

Nik
+1 I didn't know about this function, but I stand by my answer that you should become familiar with PHP date functions!
Leo
thanks for this, now I jsut need to figure out how to show it in years only as in Age: 34
iamjonesy
+1  A: 

Adding new answer because the code will be shown better. How I would do that:

in your model create virtual field like this.

var $virtualFields = array(
   'age' => "YEAR(NOW())-YEAR(YourModelName.datetimeField)"
);

Then use it as normal field in the model. :)

Nik
this looks good but im gettin a sql error. here is my code var $virtualFields = array( 'age' => "(YEAR(NOW()-YEAR(User.dob))" ); and the error is You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `User__age` FROM `users` AS `User` WHERE 1 = 1
iamjonesy
There was a typo - wrong brackets count :) Get the code and try again
Nik
thanks so much!
iamjonesy
A: 

i always use this tested method:

/*
 * @return int age (0 if both timestamps are equal or empty, -1 on invalid dates)
 * 2009-03-12 ms
 */
function age($start = null, $end = null, $accuracy = 0) {
    $age = 0;
    if (empty($start) && empty($end) || $start == $end) {
        return 0;
    }

    if (empty($start)) {
        list($yearS, $monthS, $dayS) = explode('-', date(FORMAT_DB_DATE));
    } else {
        $startDate = $this->fromString($start);
        $yearS = date('Y', $startDate);
        $monthS = date('m', $startDate);
        $dayS = date('d', $startDate);
        if (!checkdate($monthS, $dayS, $yearS)) {
            return -1;
        }
    }
    if (empty($end)) {
        list($yearE, $monthE, $dayE) = explode('-', date(FORMAT_DB_DATE));
    } else {
        $endDate = $this->fromString($end);
        $yearE = date('Y', $endDate);
        $monthE = date('m', $endDate);
        $dayE = date('d', $endDate);
        if (!checkdate($monthE, $dayE, $yearE)) {
            return -1;
        }
    }

    $n_tag = $dayE;
    $n_monat = $monthE;
    $n_jahr = $yearE;
    $g_tag = $dayS;
    $g_monat = $monthS;
    $g_jahr = $yearS;
    $g_date = mktime(0,0,0,$g_tag,$g_monat,$g_jahr);

    if (($n_monat>$g_monat)||(($n_monat == $g_monat)&&($n_tag>$g_tag))||(($n_monat == $g_monat)&&($n_tag==$g_tag))) {
        $age = $n_jahr-$g_jahr; // is correct if one already had his birthday this year
    } else {
        $age = $n_jahr-$g_jahr-1; // is correct if one didnt have his birthday yet in this year
    }
    return $age;
}

it can probably be refactured but it works with leap years and all kinds of stuff. so i never bothered...

it uses a constant you dont have

its just: define('FORMAT_DB_DATE', 'Y-m-d');

mark