In this tutorial I’m gonna show you how to calculate and display properly the age from a date CCK field the simplest way. The method I’m about to show you doesn’t need the Views module and if you use Views you’ll find that it’s totally compatible without adding any PHP code.
Requirements
Before starting I want you to meet the following requirements in order to follow this tutorial:
- Install and enable the Computed_field module
- Install and enable the Date module (Date API, Date & Date popup)
- Install and enable the Rules module
- Enable the core PHP filter module
- Add a date field to an existing content type (let’s call it
field_dob
)
For the purpose of this tutorial I created a very simple content type named Candidate with only 2 fields:
- I changed the title from Title to Full name and removed the Body field
- I added a Date field and named it
field_dob
Add a computed field
Now let’s add a new field with Age as a label and field_age
as a name and Computed as a field type.
In the next screen we will set the field settings:
- Computed Code (PHP):
$entity_field[0]['value'] = ( time() - strtotime($entity->field_dob[LANGUAGE_NONE][0]['value']) ) / 86400 / 365.25;
- Display Code (PHP):
$display_output = floor($entity_field_item['value']);
- Data type: Decimal
- Decimal Scale (decimal): 3
Add content and test
Now let’s add a few items and see if it works as we expected, I added a couple of entries and tested:
- Old KADIMI (born on 1 Jan 1990) => Age computed 21
- Young KADIMI (born on 2 Jan 1990) => Age computed 21
Sorting with Views
You may want to use the Views module to accommodate the output to your needs, one of the features of the Views module is that it enable you to sort results.
So what if we wanted to sort our candidates by age, Both KADIMI brothers (Old and Young) are 21 years old but Old is 1 day older that Young, for Drupal they have the same age and the result of the sorting may be inaccurate, actually we already fixed this issue by storing the age as a decimal number with 3 decimal points and displaying it as an integer (by using floor), by looking into the database table field_data_field_age
with phpMyAdmin:
- Young KADIMI is 21.570 years old
- Old KADIMI is 21.573 yeas old
Update age
In order to recompute a candidate age we must re-save that candidate node, one way to do this is using Rules and Drupal cron
- Visit /admin/config/workflow/rules/reaction/add to add a rule, give it a descriptive name like “Re-save candidates nodes”
Set React on event to: Cron maintenance tasks are performed - Add a new action
Set Select the action to add to: Execute custom PHP code
Set the PHP code to:$old = '1 day'; # Content is considered outdated if older than {$old} $type = 'candidate'; # Apply to nodes of type {$type} $limit = 20; # Update {$limit} nodes per cron $old = strtotime("now - $old"); $sql = ' SELECT n.nid FROM {node} n WHERE n.type = :type AND n.changed < :old ORDER BY n.changed ASC LIMIT :limit '; $sql_vars = [ ':type' => $type, ':old' => $old, ':limit' => $limit, ]; $nids = db_query($sql, $sql_vars); foreach ($nids as $nid){ $node = node_load($nid); node_save($node); }
Tweak the 3 parameters in a way that suits your needs and that’s it!
Need help?
If you found this tutorial difficult and couldn’t follow the instructions you can ask for help on the comments section or you can hire me and I will take care of this for you.
This is wrong.
How about if the birthday is before 1970, where you cannot use strtotime
It works for dates later than ’12/14/1901’… I don’t know why, I will update as soon as I know something:
The answer is here:
http://en.wikipedia.org/wiki/1901#Significance_of_1901_for_modern_computers
It’s due to 32bit Unix systems not able to go back than 1901-12-13 20:45:52 UTC and up to 2038-01-19 03:14:02 UTC
I did this and it works great except now when I create an exposed filter in views if I put 23 as the max age it doesnt bring up any of the people who are 23 because in the computers mind they are older then 23, they are 23.1 or wtvr.
You have two solutions:
1 – Setup another custom field where the age is stored as an integer and filter on this field
or
2 – Use two filters (min and max)
Thanks! Switching the field to be stored as an integer worked.
I am now working on the Update age php and I just want to make sure I did this correctly. I switched where it says candidate by type to what my content type is called and I changed the count to 100 so it does more nodes per cron. Is that what I was supposed to do to customize it for my site?
So after adding the Update Age php I noticed I get errors when running the cron and my site has lines of error code on it.
Any idea?
Thanks
Turns out that switching the age filed to be an integer does not work because then it doesnt calculate correctly. Also I tried the Min and Max for the filters and its still not working.
Thanks
Thank you for this tutorial.
What do I change in the Rules PHP code to use for user field instead of node field? I would like to update the user’s account at midnight on the birthday. Thanks.
Did you ever find a solution to that?
You can use EntityFieldQuery() which works on entities (users, nodes, field_collections…)
If you can’t figure out how to do it just send me a question with more details and I’ll be glad to write a tutorial for you and other people in the same situation.
Life saving (metaphorically speaking) tutorial!! Thanks.
What do you change the PHP Update age code to for use with Users? Seams more relevant when talking about age. Would you change all $nid to $uid and $node to $user?
e.g.
$old = ‘1 day’; # Content is considered outdated if older than {$old}
$type = ‘user’; # Apply to nodes of type {$type}
$limit = 20; # Update {$limit} nodes per cron
$old = strtotime(“now – $old”);
$sql = ‘
SELECT n.nid FROM {user} n
WHERE n.type = :type
AND n.changed $type,
‘:old’ => $old,
‘:limit’ => $limit,
];
$uids = db_query($sql, $sql_vars);
foreach ($uids as $uid){
$user = user_load($uid);
user_save($user);
}
i have problem !
what if:
today: July 8, 1989
birth day : July 9, 1989
my age should be 22, but your code display 23 !?
any help 🙂
Did you find a solution to this? I’m having the same problem with some of my profiles, but not all of them xD
Thanks for your tutorial. I found that easier way is to create “code field” in Display Suite. That don’t need any cron task.
thanks that helped me but in my case age is profile2 field how to update this field please help me
hi please just for precision
should it be the table n.created or n.changed
You’re 100% right, post updated.
thanks Nabil
Nabil , one more question please
i the PHP code , didn’t see were the $count variable that suppose to limit the number of node to be fetched for resave.
Updated again, thanks a million.
Your welcome Nabil.. and thanks for he tutorial
Got stuck for a while with the output not rendering until I ticked on the recalculate setting and Not Null. Also, how do you append a text say xx year/s old? Thanks, Nabil!