Calculate Age for PHP 5.2 - php

I am trying to calculate a person's age from their date of birth on an ExpressionEngine site.
The following code works on my local test site but the server is using an older version of PHP (5.2.17) so I amgetting errors.
Could someone suggest what code I would need to use instead?
{exp:channel:entries channel='zoo_visitor'}
<?php
$dob = new DateTime('{member_birthday format='%Y-%m-%d'}');
$now = new DateTime('now');
// This returns a DateInterval object.
$age = $now->diff($dob);
// You can output the date difference however you choose.
echo 'This person is ' .$age->format('%y') .' years old.';
?>
{/exp:channel:entries}

Your current code won't work because DateTime::diff was introduced in PHP 5.3.0.
Normally date arithmetic is quite tricky because you have to take into account timezones, DST and leap years, but for a task as simple as calculating a "whole year" difference you can do it quite easily.
The idea is that the result is equal to the end date's year minus the start date's year, and if the start date's month/day is earlier inside the year than the end date's you should subtract 1 from that. The code:
$dob = new DateTime('24 June 1940');
$now = new DateTime('now');
echo year_diff($now, $dob);
function year_diff($date1, $date2) {
list($year1, $dayOfYear1) = explode(' ', $date1->format('Y z'));
list($year2, $dayOfYear2) = explode(' ', $date2->format('Y z'));
return $year1 - $year2 - ($dayOfYear1 < $dayOfYear2);
}
See it in action. Note how the result increases by 1 on the exact same day as specified for the birthday.

$dob = strtotime('{member_birthday format='%Y-%m-%d'}');
$now = time();
echo 'This person is ' . (1970 - date('Y', ($now - $dob))) .' years old.';

You can use the diff only above PHP 5.3
You can try with modify, it works on 5.2
$age = $now->modify('-' . $dob->format('Y') . 'year');

After much search I have found the answer:
<?php
//date in mm/dd/yyyy format
$birthDate = "{member_birthday format='%m/%d/%Y'}";
//explode the date to get month, day and year
$birthDate = explode("/", $birthDate);
//get age from date or birthdate
$age = (date("md",
date("U",
mktime(0,
0,
0,
$birthDate[0],
$birthDate[1],
$birthDate[2])
)
)
> date("md")
? ((date("Y") - $birthDate[2]) - 1)
: (date("Y") - $birthDate[2]));
echo $age;
?>

The calculations which only use day of year are off by one in some corner cases: They show 1 year for 2012-02-29 and 2011-03-01, while this should be 0 years (and 11 months and 28 days). A possible solution which takes into account leap years is:
<?php
function calculateAge(DateTime $birthDate, DateTime $now = null) {
if ($now == null) {
$now = new DateTime;
}
$age = $now->format('Y') - $birthDate->format('Y');
$dm = $now->format('m') - $birthDate->format('m');
$dd = $now->format('d') - $birthDate->format('d');
if ($dm < 0 || ($dm == 0 && $dd < 0)) {
$age--;
}
return $age;
}
echo calculateAge(new DateTime('2011-04-01'), new DateTime('2012-03-29'));
user579984's solution works, too, though.

$birthday = '1983-03-25';
$cm = date('Y', strtotime($birthday));
$cd = date('Y', strtotime('now'));
$res = $cd - $cm;
if (date('m', strtotime($birthday)) > date('m', strtotime('now')))
$res--;
else if ((date('m', strtotime($birthday)) == date('m', strtotime('now'))) &&
(date('d', strtotime($birthday)) > date('d', strtotime('now'))))
$res--;
echo $res;

I've been using this and it's never let me down. YYYYMMDD being the person's birthday.
$age = floor((date('Ymd') - 'YYYYMMDD') / 10000);
If you want to be more strict you could convert the dates to integers using the intval function or preceding the dates with (int).

Related

Calculating age from date of birth in PHP

What's the most precise function you have come across to work out an age from the users date of birth. I have the following code and was wondering how it could be improved as it doesn't support all date formats and not sure if it's the most accurate function either (DateTime compliance would be nice).
function getAge($birthday) {
return floor((strtotime(date('d-m-Y')) - strtotime($date))/(60*60*24*365.2421896));
}
$birthday = new DateTime($birthday);
$interval = $birthday->diff(new DateTime);
echo $interval->y;
Should work
Check this
<?php
$c= date('Y');
$y= date('Y',strtotime('1988-12-29'));
echo $c-$y;
?>
Use this code to have full age including years, months and days-
<?php
//full age calulator
$bday = new DateTime('02.08.1991');//dd.mm.yyyy
$today = new DateTime('00:00:00'); // Current date
$diff = $today->diff($bday);
printf('%d years, %d month, %d days', $diff->y, $diff->m, $diff->d);
?>
Try using DateTime for this:
$now = new DateTime();
$birthday = new DateTime('1973-04-18 09:48:00');
echo $now->diff($birthday)->format('%y years'); // 49 years
See it in action
This works:
<?
$date = date_create('1984-10-26');
$interval = $date->diff(new DateTime);
echo $interval->y;
?>
If you tell me in what format your $birthday variable comes I will give you exact solution
WTF?
strtotime(date('d-m-Y'))
So you generate a date string from the current timestamp, then convert the date string back into a timestamp?
BTW, one of the reasons it's not working is that strtotime() assumes numeric dates to be in the format m/d/y (i.e. the US format of date first). Another reason is that the parameter ($birthday) is not used in the formula.
Change the $date to $birthday.
For supper accuracy you need to account for the leap year factor:
function get_age($dob_day,$dob_month,$dob_year){
$year = gmdate('Y');
$month = gmdate('m');
$day = gmdate('d');
//seconds in a day = 86400
$days_in_between = (mktime(0,0,0,$month,$day,$year) - mktime(0,0,0,$dob_month,$dob_day,$dob_year))/86400;
$age_float = $days_in_between / 365.242199; // Account for leap year
$age = (int)($age_float); // Remove decimal places without rounding up once number is + .5
return $age;
}
So use:
echo get_date(31,01,1985);
or whatever...
N.B. To see your EXACT age to the decimal
return $age_float
instead.
This function works fine.
function age($birthday){
list($day,$month,$year) = explode("/",$birthday);
$year_diff = date("Y") - $year;
$month_diff = date("m") - $month;
$day_diff = date("d") - $day;
if ($day_diff < 0 && $month_diff==0){$year_diff--;}
if ($day_diff < 0 && $month_diff < 0){$year_diff--;}
return $year_diff;
}
See BLOG Post
Here is my long/detailed version (you can make it shorter if you want):
$timestamp_birthdate = mktime(9, 0, 0, $birthdate_month, $birthdate_day, $birthdate_year);
$timestamp_now = time();
$difference_seconds = $timestamp_now-$timestamp_birthdate;
$difference_minutes = $difference_seconds/60;
$difference_hours = $difference_minutes/60;
$difference_days = $difference_hours/24;
$difference_years = $difference_days/365;

Get week number (in the year) from a date PHP

I want to take a date and work out its week number.
So far, I have the following. It is returning 24 when it should be 42.
<?php
$ddate = "2012-10-18";
$duedt = explode("-",$ddate);
$date = mktime(0, 0, 0, $duedt[2], $duedt[1],$duedt[0]);
$week = (int)date('W', $date);
echo "Weeknummer: ".$week;
?>
Is it wrong and a coincidence that the digits are reversed? Or am I nearly there?
Today, using PHP's DateTime objects is better:
<?php
$ddate = "2012-10-18";
$date = new DateTime($ddate);
$week = $date->format("W");
echo "Weeknummer: $week";
It's because in mktime(), it goes like this:
mktime(hour, minute, second, month, day, year);
Hence, your order is wrong.
<?php
$ddate = "2012-10-18";
$duedt = explode("-", $ddate);
$date = mktime(0, 0, 0, $duedt[1], $duedt[2], $duedt[0]);
$week = (int)date('W', $date);
echo "Weeknummer: " . $week;
?>
$date_string = "2012-10-18";
echo "Weeknummer: " . date("W", strtotime($date_string));
Use PHP's date function
http://php.net/manual/en/function.date.php
date("W", $yourdate)
This get today date then tell the week number for the week
<?php
$date=date("W");
echo $date." Week Number";
?>
Just as a suggestion:
<?php echo date("W", strtotime("2012-10-18")); ?>
Might be a little simpler than all that lot.
Other things you could do:
<?php echo date("Weeknumber: W", strtotime("2012-10-18 01:00:00")); ?>
<?php echo date("Weeknumber: W", strtotime($MY_DATE)); ?>
Becomes more difficult when you need year and week.
Try to find out which week is 01.01.2017.
(It is the 52nd week of 2016, which is from Mon 26.12.2016 - Sun 01.01.2017).
After a longer search I found
strftime('%G-%V',strtotime("2017-01-01"))
Result: 2016-52
https://www.php.net/manual/de/function.strftime.php
ISO-8601:1988 week number of the given year, starting with the first week of the year with at least 4 weekdays, with Monday being the start of the week. (01 through 53)
The equivalent in mysql is DATE_FORMAT(date, '%x-%v')
https://www.w3schools.com/sql/func_mysql_date_format.asp
Week where Monday is the first day of the week (01 to 53).
Could not find a corresponding solution with DateTime.
At least not without solutions like "+1day, last monday".
Edit: since strftime is now deprecated, maybe you can also use date.
Didn't verify it though.
date('o-W',strtotime("2017-01-01"));
I have tried to solve this question for years now, I thought I found a shorter solution but had to come back again to the long story. This function gives back the right ISO week notation:
/**
* calcweek("2018-12-31") => 1901
* This function calculates the production weeknumber according to the start on
* monday and with at least 4 days in the new year. Given that the $date has
* the following format Y-m-d then the outcome is and integer.
*
* #author M.S.B. Bachus
*
* #param date-notation PHP "Y-m-d" showing the data as yyyy-mm-dd
* #return integer
**/
function calcweek($date) {
// 1. Convert input to $year, $month, $day
$dateset = strtotime($date);
$year = date("Y", $dateset);
$month = date("m", $dateset);
$day = date("d", $dateset);
$referenceday = getdate(mktime(0,0,0, $month, $day, $year));
$jan1day = getdate(mktime(0,0,0,1,1,$referenceday[year]));
// 2. check if $year is a leapyear
if ( ($year%4==0 && $year%100!=0) || $year%400==0) {
$leapyear = true;
} else {
$leapyear = false;
}
// 3. check if $year-1 is a leapyear
if ( (($year-1)%4==0 && ($year-1)%100!=0) || ($year-1)%400==0 ) {
$leapyearprev = true;
} else {
$leapyearprev = false;
}
// 4. find the dayofyearnumber for y m d
$mnth = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
$dayofyearnumber = $day + $mnth[$month-1];
if ( $leapyear && $month > 2 ) { $dayofyearnumber++; }
// 5. find the jan1weekday for y (monday=1, sunday=7)
$yy = ($year-1)%100;
$c = ($year-1) - $yy;
$g = $yy + intval($yy/4);
$jan1weekday = 1+((((intval($c/100)%4)*5)+$g)%7);
// 6. find the weekday for y m d
$h = $dayofyearnumber + ($jan1weekday-1);
$weekday = 1+(($h-1)%7);
// 7. find if y m d falls in yearnumber y-1, weeknumber 52 or 53
$foundweeknum = false;
if ( $dayofyearnumber <= (8-$jan1weekday) && $jan1weekday > 4 ) {
$yearnumber = $year - 1;
if ( $jan1weekday = 5 || ( $jan1weekday = 6 && $leapyearprev )) {
$weeknumber = 53;
} else {
$weeknumber = 52;
}
$foundweeknum = true;
} else {
$yearnumber = $year;
}
// 8. find if y m d falls in yearnumber y+1, weeknumber 1
if ( $yearnumber == $year && !$foundweeknum) {
if ( $leapyear ) {
$i = 366;
} else {
$i = 365;
}
if ( ($i - $dayofyearnumber) < (4 - $weekday) ) {
$yearnumber = $year + 1;
$weeknumber = 1;
$foundweeknum = true;
}
}
// 9. find if y m d falls in yearnumber y, weeknumber 1 through 53
if ( $yearnumber == $year && !$foundweeknum ) {
$j = $dayofyearnumber + (7 - $weekday) + ($jan1weekday - 1);
$weeknumber = intval( $j/7 );
if ( $jan1weekday > 4 ) { $weeknumber--; }
}
// 10. output iso week number (YYWW)
return ($yearnumber-2000)*100+$weeknumber;
}
I found out that my short solution missed the 2018-12-31 as it gave back 1801 instead of 1901. So I had to put in this long version which is correct.
How about using the IntlGregorianCalendar class?
Requirements: Before you start to use IntlGregorianCalendar make sure that libicu or pecl/intl is installed on the Server.
So run on the CLI:
php -m
If you see intl in the [PHP Modules] list, then you can use IntlGregorianCalendar.
DateTime vs IntlGregorianCalendar:
IntlGregorianCalendar is not better then DateTime. But the good thing about IntlGregorianCalendar is that it will give you the week number as an int.
Example:
$dateTime = new DateTime('21-09-2020 09:00:00');
echo $dateTime->format("W"); // string '39'
$intlCalendar = IntlCalendar::fromDateTime ('21-09-2020 09:00:00');
echo $intlCalendar->get(IntlCalendar::FIELD_WEEK_OF_YEAR); // integer 39
<?php
$ddate = "2012-10-18";
$duedt = explode("-",$ddate);
$date = mktime(0, 0, 0, $duedt[1], $duedt[2],$duedt[0]);
$week = (int)date('W', $date);
echo "Weeknummer: ".$week;
?>
You had the params to mktime wrong - needs to be Month/Day/Year, not Day/Month/Year
To get the week number for a date in North America I do like this:
function week_number($n)
{
$w = date('w', $n);
return 1 + date('z', $n + (6 - $w) * 24 * 3600) / 7;
}
$n = strtotime('2022-12-27');
printf("%s: %d\n", date('D Y-m-d', $n), week_number($n));
and get:
Tue 2022-12-27: 53
for get week number in jalai calendar you can use this:
$weeknumber = date("W"); //number week in year
$dayweek = date("w"); //number day in week
if ($dayweek == "6")
{
$weeknumberint = (int)$weeknumber;
$date2int++;
$weeknumber = (string)$date2int;
}
echo $date2;
result:
15
week number change in saturday
The most of the above given examples create a problem when a year has 53 weeks (like 2020). So every fourth year you will experience a week difference. This code does not:
$thisYear = "2020";
$thisDate = "2020-04-24"; //or any other custom date
$weeknr = date("W", strtotime($thisDate)); //when you want the weeknumber of a specific week, or just enter the weeknumber yourself
$tempDatum = new DateTime();
$tempDatum->setISODate($thisYear, $weeknr);
$tempDatum_start = $tempDatum->format('Y-m-d');
$tempDatum->setISODate($thisYear, $weeknr, 7);
$tempDatum_end = $tempDatum->format('Y-m-d');
echo $tempDatum_start //will output the date of monday
echo $tempDatum_end // will output the date of sunday
Very simple
Just one line:
<?php $date=date("W"); echo "Week " . $date; ?>"
You can also, for example like I needed for a graph, subtract to get the previous week like:
<?php $date=date("W"); echo "Week " . ($date - 1); ?>
Your code will work but you need to flip the 4th and the 5th argument.
I would do it this way
$date_string = "2012-10-18";
$date_int = strtotime($date_string);
$date_date = date($date_int);
$week_number = date('W', $date_date);
echo "Weeknumber: {$week_number}.";
Also, your variable names will be confusing to you after a week of not looking at that code, you should consider reading http://net.tutsplus.com/tutorials/php/why-youre-a-bad-php-programmer/
The rule is that the first week of a year is the week that contains the first Thursday of the year.
I personally use Zend_Date for this kind of calculation and to get the week for today is this simple. They have a lot of other useful functions if you work with dates.
$now = Zend_Date::now();
$week = $now->get(Zend_Date::WEEK);
// 10
To get Correct Week Count for Date 2018-12-31 Please use below Code
$day_count = date('N',strtotime('2018-12-31'));
$week_count = date('W',strtotime('2018-12-31'));
if($week_count=='01' && date('m',strtotime('2018-12-31'))==12){
$yr_count = date('y',strtotime('2018-12-31')) + 1;
}else{
$yr_count = date('y',strtotime('2018-12-31'));
}
function last_monday($date)
{
if (!is_numeric($date))
$date = strtotime($date);
if (date('w', $date) == 1)
return $date;
else
return date('Y-m-d',strtotime('last monday',$date));
}
$date = '2021-01-04'; //Enter custom date
$year = date('Y',strtotime($date));
$date1 = new DateTime($date);
$ldate = last_monday($year."-01-01");
$date2 = new DateTime($ldate);
$diff = $date2->diff($date1)->format("%a");
$diff = $diff/7;
$week = intval($diff) + 1;
echo $week;
//Returns 2.
try this solution
date( 'W', strtotime( "2017-01-01 + 1 day" ) );

PHP strtotime +1 month behaviour

I know about the unwanted behaviour of PHP's function
strtotime
For example, when adding a month (+1 month) to dates like: 31.01.2011 -> 03.03.2011
I know it's not officially a PHP bug, and that this solution has some arguments behind it, but at least for me, this behavior has caused a lot waste of time (in the past and present) and I personally hate it.
What I found even stranger is that for example in:
MySQL: DATE_ADD('2011-01-31', INTERVAL 1 MONTH) returns 2011-02-28
or
C# where new DateTime(2011, 01, 31).AddMonths(1); will return 28.02.2011
wolframalpha.com giving 31.01.2013 + 1 month as input; will return Thursday, February 28, 2013
It sees to me that others have found a more decent solution to the stupid question that I saw alot in PHP bug reports "what day will it be, if I say we meet in a month from now" or something like that. The answer is: if 31 does not exists in next month, get me the last day of that month, but please stick to next month.
So MY QUESTION IS: is there a PHP function (written by somebody) that resolves this not officially recognized bug? As I don't think I am the only one who wants another behavior when adding / subtracting months.
I am particulary interested in solutions what also work not just for the end of the month, but a complete replacement of strtotime. Also the case strotime +n months should be also dealt with.
Happy coding!
what you need is to tell PHP to be smarter
$the_date = strtotime('31.01.2011');
echo date('r', strtotime('last day of next month', $the_date));
$the_date = strtotime('31.03.2011');
echo date('r', strtotime('last day of next month', $the_date));
assuming you are only interesting on the last day of next month
reference - http://www.php.net/manual/en/datetime.formats.relative.php
PHP devs surely don't consider this as bug. But in strtotime's docs there are few comments with solutions for your problem (look for 28th Feb examples ;)), i.e. this one extending DateTime class:
<?php
// this will give us 2010-02-28 ()
echo PHPDateTime::DateNextMonth(strftime('%F', strtotime("2010-01-31 00:00:00")), 31);
?>
Class PHPDateTime:
<?php
/**
* IA FrameWork
* #package: Classes & Object Oriented Programming
* #subpackage: Date & Time Manipulation
* #author: ItsAsh <ash at itsash dot co dot uk>
*/
final class PHPDateTime extends DateTime {
// Public Methods
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Calculate time difference between two dates
* ...
*/
public static function TimeDifference($date1, $date2)
$date1 = is_int($date1) ? $date1 : strtotime($date1);
$date2 = is_int($date2) ? $date2 : strtotime($date2);
if (($date1 !== false) && ($date2 !== false)) {
if ($date2 >= $date1) {
$diff = ($date2 - $date1);
if ($days = intval((floor($diff / 86400))))
$diff %= 86400;
if ($hours = intval((floor($diff / 3600))))
$diff %= 3600;
if ($minutes = intval((floor($diff / 60))))
$diff %= 60;
return array($days, $hours, $minutes, intval($diff));
}
}
return false;
}
/**
* Formatted time difference between two dates
*
* ...
*/
public static function StringTimeDifference($date1, $date2) {
$i = array();
list($d, $h, $m, $s) = (array) self::TimeDifference($date1, $date2);
if ($d > 0)
$i[] = sprintf('%d Days', $d);
if ($h > 0)
$i[] = sprintf('%d Hours', $h);
if (($d == 0) && ($m > 0))
$i[] = sprintf('%d Minutes', $m);
if (($h == 0) && ($s > 0))
$i[] = sprintf('%d Seconds', $s);
return count($i) ? implode(' ', $i) : 'Just Now';
}
/**
* Calculate the date next month
*
* ...
*/
public static function DateNextMonth($now, $date = 0) {
$mdate = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
list($y, $m, $d) = explode('-', (is_int($now) ? strftime('%F', $now) : $now));
if ($date)
$d = $date;
if (++$m == 2)
$d = (($y % 4) === 0) ? (($d <= 29) ? $d : 29) : (($d <= 28) ? $d : 28);
else
$d = ($d <= $mdate[$m]) ? $d : $mdate[$m];
return strftime('%F', mktime(0, 0, 0, $m, $d, $y));
}
}
?>
Here's the algorithm you can use. It should be simple enough to implement yourself.
Have the original date and the +1 month date in variables
Extract the month part of both variables
If the difference is greater than 1 month (or if the original is December and the other is not January) change the latter variable to the last day of the next month. You can use for example t in date() to get the last day: date( 't.m.Y' )
Had the same issue recently and ended up writing a class that handles adding/subtracting various time intervals to DateTime objects.
Here's the code:
https://gist.github.com/pavlepredic/6220041#file-gistfile1-php
I've been using this class for a while and it seems to work fine, but I'm really interested in some peer review. What you do is create a TimeInterval object (in your case, you would specify 1 month as the interval) and then call addToDate() method, making sure you set $preventMonthOverflow argument to true. The code will make sure that the resulting date does not overflow into next month.
Sample usage:
$int = new TimeInterval(1, TimeInterval::MONTH);
$date = date_create('2013-01-31');
$future = $int->addToDate($date, true);
echo $future->format('Y-m-d');
Resulting date is:
2013-02-28
Here is an implementation of an improved version of Juhana's answer above:
<?php
function sameDateNextMonth(DateTime $createdDate, DateTime $currentDate) {
$addMon = clone $currentDate;
$addMon->add(new DateInterval("P1M"));
$nextMon = clone $currentDate;
$nextMon->modify("last day of next month");
if ($addMon->format("n") == $nextMon->format("n")) {
$recurDay = $createdDate->format("j");
$daysInMon = $addMon->format("t");
$currentDay = $currentDate->format("j");
if ($recurDay > $currentDay && $recurDay <= $daysInMon) {
$addMon->setDate($addMon->format("Y"), $addMon->format("n"), $recurDay);
}
return $addMon;
} else {
return $nextMon;
}
}
This version takes $createdDate under the presumption that you are dealing with a recurring monthly period, such as a subscription, that started on a specific date, such as the 31st. It always takes $createdDate so late "recurs on" dates won't shift to lower values as they are pushed forward thru lesser-valued months (e.g., so all 29th, 30th or 31st recur dates won't eventually get stuck on the 28th after passing thru a non-leap-year February).
Here is some driver code to test the algorithm:
$createdDate = new DateTime("2015-03-31");
echo "created date = " . $createdDate->format("Y-m-d") . PHP_EOL;
$next = sameDateNextMonth($createdDate, $createdDate);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
foreach(range(1, 12) as $i) {
$next = sameDateNextMonth($createdDate, $next);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
}
Which outputs:
created date = 2015-03-31
next date = 2015-04-30
next date = 2015-05-31
next date = 2015-06-30
next date = 2015-07-31
next date = 2015-08-31
next date = 2015-09-30
next date = 2015-10-31
next date = 2015-11-30
next date = 2015-12-31
next date = 2016-01-31
next date = 2016-02-29
next date = 2016-03-31
next date = 2016-04-30
I have solved it by this way:
$startDate = date("Y-m-d");
$month = date("m",strtotime($startDate));
$nextmonth = date("m",strtotime("$startDate +1 month"));
if((($nextmonth-$month) > 1) || ($month == 12 && $nextmonth != 1))
{
$nextDate = date( 't.m.Y',strtotime("$initialDate +1 week"));
}else
{
$nextDate = date("Y-m-d",strtotime("$initialDate +1 month"));
}
echo $nextDate;
Somewhat similar to the Juhana's answer but more intuitive and less complications expected. Idea is like this:
Store original date and the +n month(s) date in variables
Extract the day part of both variables
If days do not match, subtract number of days from the future date
Plus side of this solution is that works for any date (not just the border dates) and it also works for subtracting months (by putting - instead of +).
Here is an example implementation:
$start = mktime(0,0,0,1,31,2015);
for ($contract = 0; $contract < 12; $contract++) {
$end = strtotime('+ ' . $contract . ' months', $start);
if (date('d', $start) != date('d', $end)) {
$end = strtotime('- ' . date('d', $end) . ' days', $end);
}
echo date('d-m-Y', $end) . '|';
}
And the output is following:
31-01-2015|28-02-2015|31-03-2015|30-04-2015|31-05-2015|30-06-2015|31-07-2015|31-08-2015|30-09-2015|31-10-2015|30-11-2015|31-12-2015|
function ldom($m,$y){
//return tha last date of a given month based on the month and the year
//(factors in leap years)
$first_day= strtotime (date($m.'/1/'.$y));
$next_month = date('m',strtotime ( '+32 day' , $first_day)) ;
$last_day= strtotime ( '-1 day' , strtotime (date($next_month.'/1/'.$y)) ) ;
return $last_day;
}

PHP Accurately Calculate Nearest Age for a given DOB

I am trying to calculate the nearest Age based on DOB, but i cant wrap my head around how to do it. I have tried some methods which estimates but this is not good enough. We need to calculate the days from today and the next birthday, whether it is in the current year or next year. and also calculate the days from today and the last birthday again whether it is in the current year or last year.
Any suggestions?
I think this is what you want.... of course, you could just get a persons age accurate to the day and round it up or down to the closest year..... which is probably what I should have done.
It's quite brute force, so I'm sure you can do it better, but what it does is check the number of days until this year's, next year's, and last year's birthday (I checked each of those three separately instead of subtracting from 365, since date() takes care of leap years, and I don't want to). Then it calculates age from whichever one of those birthdays is closest.
Working example
<?php
$bday = "September 3, 1990";
// Output is 21 on 2011-08-27 for 1990-09-03
// Check the times until this, next, and last year's bdays
$time_until = strtotime(date('M j', strtotime($bday))) - time();
$this_year = abs($time_until);
$time_until = strtotime(date('M j', strtotime($bday)).' +1 year') - time();
$next_year = abs($time_until);
$time_until = strtotime(date('M j', strtotime($bday)).' -1 year') - time();
$last_year = abs($time_until);
$years = array($this_year, $next_year, $last_year);
// Calculate age based on closest bday
if (min($years) == $this_year) {
$age = date('Y', time()) - date('Y', strtotime($bday));
}
if (min($years) == $next_year) {
$age = date('Y', strtotime('+1 year')) - date('Y', strtotime($bday));
}
if (min($years) == $last_year) {
$age = date('Y', strtotime('-1 year')) - date('Y', strtotime($bday));
}
echo "You are $age years old.";
?>
Edit: Removed unnecessary date()s in the $time_until calcs.
If I understand correctly you want to "round" the age? Then how about something along these lines:
$dob = new DateTime($birthday);
$diff = $dob->diff(new DateTime);
if ($diff->format('%m') > 6) {
echo 'Age: ' . ($diff->format('%y') + 1);
} else {
echo 'Age: ' . $diff->format('%y');
}
Edit: rewrote to use DateInterval
This should do the trick for you...
$birthday = new DateTime('1990-09-03');
$today = new DateTime();
$diff = $birthday->diff($today, TRUE);
$age = $diff->format('%Y');
$next_birthday = $birthday->modify('+'. $age + 1 . ' years');
$halfway_to_bday = $next_birthday->sub(DateInterval::createFromDateString('182 days 12 hours'));
if($today >= $halfway_to_bday)
{
$age++;
}
echo $age;

PHP calculate age

I'm looking for a way to calculate the age of a person, given their DOB in the format dd/mm/yyyy.
I was using the following function which worked fine for several months until some kind of glitch caused the while loop to never end and grind the entire site to a halt. Since there are almost 100,000 DOBs going through this function several times a day, it's hard to pin down what was causing this.
Does anyone have a more reliable way of calculating the age?
//replace / with - so strtotime works
$dob = strtotime(str_replace("/","-",$birthdayDate));
$tdate = time();
$age = 0;
while( $tdate > $dob = strtotime('+1 year', $dob))
{
++$age;
}
return $age;
EDIT: this function seems to work OK some of the time, but returns "40" for a DOB of 14/09/1986
return floor((time() - strtotime($birthdayDate))/31556926);
This works fine.
<?php
//date in mm/dd/yyyy format; or it can be in other formats as well
$birthDate = "12/17/1983";
//explode the date to get month, day and year
$birthDate = explode("/", $birthDate);
//get age from date or birthdate
$age = (date("md", date("U", mktime(0, 0, 0, $birthDate[0], $birthDate[1], $birthDate[2]))) > date("md")
? ((date("Y") - $birthDate[2]) - 1)
: (date("Y") - $birthDate[2]));
echo "Age is:" . $age;
?>
$tz = new DateTimeZone('Europe/Brussels');
$age = DateTime::createFromFormat('d/m/Y', '12/02/1973', $tz)
->diff(new DateTime('now', $tz))
->y;
As of PHP 5.3.0 you can use the handy DateTime::createFromFormat to ensure that your date does not get mistaken for m/d/Y format and the DateInterval class (via DateTime::diff) to get the number of years between now and the target date.
$date = new DateTime($bithdayDate);
$now = new DateTime();
$interval = $now->diff($date);
return $interval->y;
I use Date/Time for this:
$age = date_diff(date_create($bdate), date_create('now'))->y;
Simple method for calculating Age from dob:
$_age = floor((time() - strtotime('1986-09-16')) / 31556926);
31556926 is the number of seconds in a year.
I find this works and is simple.
Subtract from 1970 because strtotime calculates time from 1970-01-01 (http://php.net/manual/en/function.strtotime.php)
function getAge($date) {
return intval(date('Y', time() - strtotime($date))) - 1970;
}
Results:
Current Time: 2015-10-22 10:04:23
getAge('2005-10-22') // => 10
getAge('1997-10-22 10:06:52') // one 1s before => 17
getAge('1997-10-22 10:06:50') // one 1s after => 18
getAge('1985-02-04') // => 30
getAge('1920-02-29') // => 95
// Age Calculator
function getAge($dob,$condate){
$birthdate = new DateTime(date("Y-m-d", strtotime(implode('-', array_reverse(explode('/', $dob))))));
$today= new DateTime(date("Y-m-d", strtotime(implode('-', array_reverse(explode('/', $condate))))));
$age = $birthdate->diff($today)->y;
return $age;
}
$dob='06/06/1996'; //date of Birth
$condate='07/02/16'; //Certain fix Date of Age
echo getAge($dob,$condate);
Write a PHP script to calculate the current age of a person.
Sample date of birth : 11.4.1987
Sample Solution:
PHP Code:
<?php
$bday = new DateTime('11.4.1987'); // Your date of birth
$today = new Datetime(date('m.d.y'));
$diff = $today->diff($bday);
printf(' Your age : %d years, %d month, %d days', $diff->y, $diff->m, $diff->d);
printf("\n");
?>
Sample Output:
Your age : 30 years, 3 month, 0 days
Figured I'd throw this on here since this seems to be most popular form of this question.
I ran a 100 year comparison on 3 of the most popular types of age funcs i could find for PHP and posted my results (as well as the functions) to my blog.
As you can see there, all 3 funcs preform well with just a slight difference on the 2nd function. My suggestion based on my results is to use the 3rd function unless you want to do something specific on a person's birthday, in which case the 1st function provides a simple way to do exactly that.
Found small issue with test, and another issue with 2nd method! Update coming to blog soon! For now, I'd take note, 2nd method is still most popular one I find online, and yet still the one I'm finding the most inaccuracies with!
My suggestions after my 100 year review:
If you want something more elongated so that you can include occasions like birthdays and such:
function getAge($date) { // Y-m-d format
$now = explode("-", date('Y-m-d'));
$dob = explode("-", $date);
$dif = $now[0] - $dob[0];
if ($dob[1] > $now[1]) { // birthday month has not hit this year
$dif -= 1;
}
elseif ($dob[1] == $now[1]) { // birthday month is this month, check day
if ($dob[2] > $now[2]) {
$dif -= 1;
}
elseif ($dob[2] == $now[2]) { // Happy Birthday!
$dif = $dif." Happy Birthday!";
};
};
return $dif;
}
getAge('1980-02-29');
But if you just simply want to know the age and nothing more, then:
function getAge($date) { // Y-m-d format
return intval(substr(date('Ymd') - date('Ymd', strtotime($date)), 0, -4));
}
getAge('1980-02-29');
See BLOG
A key note about the strtotime method:
Note:
Dates in the m/d/y or d-m-y formats are disambiguated by looking at the
separator between the various components: if the separator is a slash (/),
then the American m/d/y is assumed; whereas if the separator is a dash (-)
or a dot (.), then the European d-m-y format is assumed. If, however, the
year is given in a two digit format and the separator is a dash (-, the date
string is parsed as y-m-d.
To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) dates or
DateTime::createFromFormat() when possible.
You can use the Carbon library, which is an API extension for DateTime.
You can:
function calculate_age($date) {
$date = new \Carbon\Carbon($date);
return (int) $date->diffInYears();
}
or:
$age = (new \Carbon\Carbon($date))->age;
If you want to caculate the Age of using the dob, you can also use this function.
It uses the DateTime object.
function calcutateAge($dob){
$dob = date("Y-m-d",strtotime($dob));
$dobObject = new DateTime($dob);
$nowObject = new DateTime();
$diff = $dobObject->diff($nowObject);
return $diff->y;
}
If you don't need great precision, just the number of years, you could consider using the code below ...
print floor((time() - strtotime("1971-11-20")) / (60*60*24*365));
You only need to put this into a function and replace the date "1971-11-20" with a variable.
Please note that precision of the code above is not high because of the leap years, i.e. about every 4 years the days are 366 instead of 365. The expression 60*60*24*365 calculates the number of seconds in one year - you can replace it with 31536000.
Another important thing is that because of the use of UNIX Timestamp it has both the Year 1901 and Year 2038 problem which means the the expression above will not work correctly for dates before year 1901 and after year 2038.
If you can live with the limitations mentioned above that code should work for you.
$birthday_timestamp = strtotime('1988-12-10');
// Calculates age correctly
// Just need birthday in timestamp
$age = date('md', $birthday_timestamp) > date('md') ? date('Y') - date('Y', $birthday_timestamp) - 1 : date('Y') - date('Y', $birthday_timestamp);
//replace / with - so strtotime works
$dob = strtotime(str_replace("/","-",$birthdayDate));
$tdate = time();
return date('Y', $tdate) - date('Y', $dob);
function dob ($birthday){
list($day,$month,$year) = explode("/",$birthday);
$year_diff = date("Y") - $year;
$month_diff = date("m") - $month;
$day_diff = date("d") - $day;
if ($day_diff < 0 || $month_diff < 0)
$year_diff--;
return $year_diff;
}
I have found this script reliable. It takes the date format as YYYY-mm-dd, but it could be modified for other formats pretty easily.
/*
* Get age from dob
* #param dob string The dob to validate in mysql format (yyyy-mm-dd)
* #return integer The age in years as of the current date
*/
function getAge($dob) {
//calculate years of age (input string: YYYY-MM-DD)
list($year, $month, $day) = explode("-", $dob);
$year_diff = date("Y") - $year;
$month_diff = date("m") - $month;
$day_diff = date("d") - $day;
if ($day_diff < 0 || $month_diff < 0)
$year_diff--;
return $year_diff;
}
i18n :
function getAge($birthdate, $pattern = 'eu')
{
$patterns = array(
'eu' => 'd/m/Y',
'mysql' => 'Y-m-d',
'us' => 'm/d/Y',
);
$now = new DateTime();
$in = DateTime::createFromFormat($patterns[$pattern], $birthdate);
$interval = $now->diff($in);
return $interval->y;
}
// Usage
echo getAge('05/29/1984', 'us');
// return 28
Try any of these using DateTime object
$hours_in_day = 24;
$minutes_in_hour= 60;
$seconds_in_mins= 60;
$birth_date = new DateTime("1988-07-31T00:00:00");
$current_date = new DateTime();
$diff = $birth_date->diff($current_date);
echo $years = $diff->y . " years " . $diff->m . " months " . $diff->d . " day(s)"; echo "<br/>";
echo $months = ($diff->y * 12) + $diff->m . " months " . $diff->d . " day(s)"; echo "<br/>";
echo $weeks = floor($diff->days/7) . " weeks " . $diff->d%7 . " day(s)"; echo "<br/>";
echo $days = $diff->days . " days"; echo "<br/>";
echo $hours = $diff->h + ($diff->days * $hours_in_day) . " hours"; echo "<br/>";
echo $mins = $diff->h + ($diff->days * $hours_in_day * $minutes_in_hour) . " minutest"; echo "<br/>";
echo $seconds = $diff->h + ($diff->days * $hours_in_day * $minutes_in_hour * $seconds_in_mins) . " seconds"; echo "<br/>";
Reference http://www.calculator.net/age-calculator.html
this is my function to calculating DOB with the specific return of age by year, month, and day
function ageDOB($y=2014,$m=12,$d=31){ /* $y = year, $m = month, $d = day */
date_default_timezone_set("Asia/Jakarta"); /* can change with others time zone */
$ageY = date("Y")-intval($y);
$ageM = date("n")-intval($m);
$ageD = date("j")-intval($d);
if ($ageD < 0){
$ageD = $ageD += date("t");
$ageM--;
}
if ($ageM < 0){
$ageM+=12;
$ageY--;
}
if ($ageY < 0){ $ageD = $ageM = $ageY = -1; }
return array( 'y'=>$ageY, 'm'=>$ageM, 'd'=>$ageD );
}
this how to use it
$age = ageDOB(1984,5,8); /* with my local time is 2014-07-01 */
echo sprintf("age = %d years %d months %d days",$age['y'],$age['m'],$age['d']); /* output -> age = 29 year 1 month 24 day */
This function will return the age in years. Input value is a date formated (YYYY-MM-DD) day of birth string eg: 2000-01-01
It works with day - precision
function getAge($dob) {
//calculate years of age (input string: YYYY-MM-DD)
list($year, $month, $day) = explode("-", $dob);
$year_diff = date("Y") - $year;
$month_diff = date("m") - $month;
$day_diff = date("d") - $day;
// if we are any month before the birthdate: year - 1
// OR if we are in the month of birth but on a day
// before the actual birth day: year - 1
if ( ($month_diff < 0 ) || ($month_diff === 0 && $day_diff < 0))
$year_diff--;
return $year_diff;
}
Cheers, nira
If you want to only get fullyears as age, there is a supersimple way on doing that. treat dates formatted as 'YYYYMMDD' as numbers and substract them. After that cancel out the MMDD part by dividing the result with 10000 and floor it down. Simple and never fails, even takes to account leapyears and your current server time ;)
Since birthdays or mostly provided by full dates on birth location and they are relevant to CURRENT LOCAL TIME (where the age check is actually done).
$now = date['Ymd'];
$birthday = '19780917'; #september 17th, 1978
$age = floor(($now-$birthday)/10000);
so if you want to check if someone is 18 or 21 or below 100 on your timezone (nevermind the origin timezone) by birthday, this is my way to do this
If you can't seem to use some of the newer functions, here's something I whipped up. Probably more than you need, and I'm sure there are better ways, but it's easy to read, so it should do the job:
function get_age($date, $units='years')
{
$modifier = date('n') - date('n', strtotime($date)) ? 1 : (date('j') - date('j', strtotime($date)) ? 1 : 0);
$seconds = (time()-strtotime($date));
$years = (date('Y')-date('Y', strtotime($date))-$modifier);
switch($units)
{
case 'seconds':
return $seconds;
case 'minutes':
return round($seconds/60);
case 'hours':
return round($seconds/60/60);
case 'days':
return round($seconds/60/60/24);
case 'months':
return ($years*12+date('n'));
case 'decades':
return ($years/10);
case 'centuries':
return ($years/100);
case 'years':
default:
return $years;
}
}
Example Use:
echo 'I am '.get_age('September 19th, 1984', 'days').' days old';
Hope this helps.
Due to leap year, it is not wise just to subtract one date from another and floor it to number of years. To calculate the age like the humans, you will need something like this:
$birthday_date = '1977-04-01';
$age = date('Y') - substr($birthday_date, 0, 4);
if (strtotime(date('Y-m-d')) - strtotime(date('Y') . substr($birthday_date, 4, 6)) < 0)
{
$age--;
}
The following works great for me and seems to be a lot simpler than the examples that have already been given.
$dob_date = "01";
$dob_month = "01";
$dob_year = "1970";
$year = gmdate("Y");
$month = gmdate("m");
$day = gmdate("d");
$age = $year-$dob_year; // $age calculates the user's age determined by only the year
if($month < $dob_month) { // this checks if the current month is before the user's month of birth
$age = $age-1;
} else if($month == $dob_month && $day >= $dob_date) { // this checks if the current month is the same as the user's month of birth and then checks if it is the user's birthday or if it is after it
$age = $age;
} else if($month == $dob_month && $day < $dob_date) { //this checks if the current month is the user's month of birth and checks if it before the user's birthday
$age = $age-1;
} else {
$age = $age;
}
I've tested and actively use this code, it might seem a little cumbersome but it is very simple to use and edit and is quite accurate.
Following the first logic, you have to use = in the comparison.
<?php
function age($birthdate) {
$birthdate = strtotime($birthdate);
$now = time();
$age = 0;
while ($now >= ($birthdate = strtotime("+1 YEAR", $birthdate))) {
$age++;
}
return $age;
}
// Usage:
echo age(implode("-",array_reverse(explode("/",'14/09/1986')))); // format yyyy-mm-dd is safe!
echo age("-10 YEARS") // without = in the comparison, will returns 9.
?>
It is a problem when you use strtotime with DD/MM/YYYY. You cant use that format. Instead of it you can use MM/DD/YYYY (or many others like YYYYMMDD or YYYY-MM-DD) and it should work properly.
How about launching this query and having MySQL calculating it for you:
SELECT
username
,date_of_birth
,(PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(date_of_birth, '%Y%m') )) DIV 12 AS years
,(PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(date_of_birth, '%Y%m') )) MOD 12 AS months
FROM users
Result:
r2d2, 1986-12-23 00:00:00, 27 , 6
The user has 27 years and 6 months (it counts an entire month)
I did it like this.
$geboortedatum = 1980-01-30 00:00:00;
echo leeftijd($geboortedatum)
function leeftijd($geboortedatum) {
$leeftijd = date('Y')-date('Y', strtotime($geboortedatum));
if (date('m')<date('m', strtotime($geboortedatum)))
$leeftijd = $leeftijd-1;
elseif (date('m')==date('m', strtotime($geboortedatum)))
if (date('d')<date('d', strtotime($geboortedatum)))
$leeftijd = $leeftijd-1;
return $leeftijd;
}
The top answer for this is OK but only calualtes the year a person was born, I tweaked it for my own purposes to work out the day and month. But thought it was worth sharing.
This works by taken a timestamp of the the users DOB, but feel free to change that
$birthDate = date('d-m-Y',$usersDOBtimestamp);
$currentDate = date('d-m-Y', time());
//explode the date to get month, day and year
$birthDate = explode("-", $birthDate);
$currentDate = explode("-", $currentDate);
$birthDate[0] = ltrim($birthDate[0],'0');
$currentDate[0] = ltrim($currentDate[0],'0');
//that gets a rough age
$age = $currentDate[2] - $birthDate[2];
//check if month has passed
if($birthDate[1] > $currentDate[1]){
//user birthday has not passed
$age = $age - 1;
} else if($birthDate[1] == $currentDate[1]){
//check if birthday is in current month
if($birthDate[0] > $currentDate[0]){
$age - 1;
}
}
echo $age;
Here is the process that is more simple and works both for the formats dd/mm/yyyy and dd-mm-yyyy. This is working great for me:
<?php
$birthday = '26/04/1994';
$dob = strtotime(str_replace("/", "-", $birthday));
$tdate = time();
echo date('Y', $tdate) - date('Y', $dob);
?>

Categories