90

If I have a person's date of birth stored in a table in the form dd-mm-yyyy, and I subtract it from the current date, what format is the date returned in?

How can I use this returned format to calculate someone's age?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user559142
  • 12,279
  • 49
  • 116
  • 179
  • 5
    What RDBMS is this for? Date Functions aren't that well standardised AFAIK. And what do you mean stored in the format `dd-mm-yyyy`? if it is of `date` datatype it will likely be stored in a numeric format (e.g. as an integer with days since some start point) – Martin Smith Apr 24 '11 at 21:47
  • Hi I am using InnoDb with phpMyAdmin....It is stored as a date variable. I think it is yyyymmdd - made mistake above – user559142 Apr 24 '11 at 22:06
  • If data is stored as a DATE or DATETIME data type, it is stored as a binary value, NOT in any particular human-readable format. Formatting only happens on output to text, and is dependent on factors like OS locale setting, or explicit format instructions provided by you. To the extent possible, process DATE and DATETIME values with functions that _expect_ DATE and DATETIME type values. Then you don't have problems with date format. You MIGHT still need to mess with timezone, but at least then your calc is just a little off rather than completely broken. – gwideman Jul 29 '14 at 09:14

13 Answers13

306

You can use TIMESTAMPDIFF(unit, datetime_expr1, datetime_expr2) function:

SELECT TIMESTAMPDIFF(YEAR, '1970-02-01', CURDATE()) AS age

Demo

Glavić
  • 42,781
  • 13
  • 77
  • 107
68

If the value is stored as a DATETIME data type:

SELECT YEAR(CURRENT_TIMESTAMP) - YEAR(dob) - (RIGHT(CURRENT_TIMESTAMP, 5) < RIGHT(dob, 5)) as age 
  FROM YOUR_TABLE

Less precise when you consider leap years:

SELECT DATEDIFF(CURRENT_DATE, STR_TO_DATE(t.birthday, '%d-%m-%Y'))/365 AS ageInYears
  FROM YOUR_TABLE t 
Benjamin Crouzier
  • 40,265
  • 44
  • 171
  • 236
OMG Ponies
  • 325,700
  • 82
  • 523
  • 502
  • ... /365.25 to handle leap-years. But in the year 2000, the leap year was skipped. But if you can live with an error of 1 day. – user unknown Apr 24 '11 at 22:36
  • 45
    There is a correct answer in the official MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/date-calculations.html – mojuba Jan 23 '13 at 01:35
  • @mojuba: That's a different way, not necessarily correct -- I don't think the OP would've marked this as the answer if it wasn't satisfactory. I'd appreciate it if you're reverse your downvote in light of that, and that the question is almost two years old. – OMG Ponies Jan 23 '13 at 04:44
  • 4
    @OMG Ponies I'm sorry but an assumption that there are 365 days in a year can never give correct age calculation. For a 40 year old person, for example, you will be giving a wrong age during 10 days after the person's birthday. – mojuba Jan 23 '13 at 15:17
  • 1
    @OMG Ponies No, no and no. The error in your formula is approx age/4, because that's the number of leap years (which is the number of unaccounted-for extra days) in your formula. Try this to verify: http://www.timeanddate.com/date/duration.html – mojuba Jan 24 '13 at 08:07
  • thanks i was looking for this. Can you please explain what this part is for (RIGHT(CURRENT_TIMESTAMP, 5) < RIGHT(dob, 5)) – Abhishek Salian Feb 03 '14 at 00:40
  • The RIGHT(...) business carves off the rightmost 5 characters of the implied conversion of the date to string, in format yyyy-mm-dd. Hence RIGHT(date1,5) – gwideman Jul 29 '14 at 06:24
  • If you are reading this, please use mojuba comment or Glavic answer. – Leandro Bardelli Jan 27 '19 at 21:04
  • It is worth noting that if the value is DATE (and not DATETIME), "CURRENT_TIMESTAMP" should be replaced by "CURDATE()". – Marco Sep 02 '19 at 21:45
15
SELECT TIMESTAMPDIFF (YEAR, YOUR_COLUMN, CURDATE()) FROM YOUR_TABLE AS AGE

Check the demo image below

sql time difference example

Simple but elegant..

MAZ
  • 864
  • 11
  • 19
Ferd Shinoda
  • 159
  • 1
  • 3
13

Use:

select *,year(curdate())-year(dob) - (right(curdate(),5) < right(dob,5)) as age from your_table

In this way, you consider even month and day of birth in order to have a more accurate age calculation.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nicola Cossu
  • 54,599
  • 15
  • 92
  • 98
  • Wow this works great - can you explain to me what the - (right(curdate(),5) < right(dob,5)) part does? – user559142 Apr 24 '11 at 22:26
  • Yes. Right(...,5) extracts mm-dd from current date and from date of birth. You compare them with "<" symbol that returns 0 if day and month of date of birth are less than current date, 1 otherwise. So you can subtract it (0 or 1) from year difference. – Nicola Cossu Apr 24 '11 at 22:31
  • 2
    I would make one big modification. On my MySQL right(dob,5) return the hours-minutes section of the date. This would be fixed by using `year(curdate())-year(dob) - (dayofyear(curdate()) < dayofyear(dob)) as age`, and I feel dayofyear is more elegant. – regilero Mar 01 '13 at 11:52
  • And of course this all fails if dob happens to be stored as a datetime. Just use TIMESTAMPDIFF() – gwideman Jul 29 '14 at 08:58
5
select floor(datediff (now(), birthday)/365) as age
lobster1234
  • 7,679
  • 26
  • 30
  • Sorry..just fixed it. He can use floor or ceil based on the requirement. – lobster1234 Apr 24 '11 at 22:22
  • 1
    Yes, it wont work for that level of accuracy if thats what OP wants. However, you'd need to have 365 leap years to make 1 year of difference in age, no? – lobster1234 Apr 24 '11 at 22:28
2

Simply:

DATE_FORMAT(FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(`birthDate`)), '%Y')+0 AS age
Damonsson
  • 1,532
  • 14
  • 25
2

Since the question is being tagged for mysql, I have the following implementation that works for me and I hope similar alternatives would be there for other RDBMS's. Here's the sql:

select YEAR(now()) - YEAR(dob) - ( DAYOFYEAR(now()) < DAYOFYEAR(dob) ) as age 
from table 
where ...
mickeymoon
  • 4,820
  • 5
  • 31
  • 56
1

Simply do

SELECT birthdate, (YEAR(CURDATE())-YEAR(birthdate)) AS age FROM `member` 

birthdate is field name that keep birthdate name take CURDATE() turn to year by YEAR() command minus with YEAR() from the birthdate field

Kuzmiraun
  • 27
  • 2
  • 2
    if you do not take in mind the month and day, the number might have a difference of one year with the real age – Juan Mar 22 '19 at 11:20
1

Try this:

SET @birthday = CAST('1980-05-01' AS DATE);
SET @today = CURRENT_DATE();

SELECT YEAR(@today) - YEAR(@birthday) - 
  (CASE WHEN
    MONTH(@birthday) > MONTH(@today) OR 
    (MONTH(@birthday) = MONTH(@today) AND DAY(@birthday) > DAY(@today)) 
      THEN 1 
      ELSE 0 
  END);

It returns this year - birth year (how old the person will be this year after the birthday) and adjusts based on whether the person has had the birthday yet this year.

It doesn't suffer from the rounding errors of other methods presented here.

Freely adapted from here

Sklivvz
  • 30,601
  • 24
  • 116
  • 172
0

You can make a function to do it:

drop function if exists getIdade;

delimiter |

create function getIdade( data_nascimento datetime )
returns int
begin
    declare idade int;
    declare ano_atual int;
    declare mes_atual int;
    declare dia_atual int;
    declare ano int;
    declare mes int;
    declare dia int;

    set ano_atual = year(curdate());
    set mes_atual = month( curdate());
    set dia_atual = day( curdate());

    set ano = year( data_nascimento );
    set mes = month( data_nascimento );
    set dia = day( data_nascimento );

    set idade = ano_atual - ano;

    if( mes > mes_atual ) then
            set idade = idade - 1;
    end if;

    if( mes = mes_atual and dia > dia_atual ) then
            set idade = idade - 1;
    end if;

    return idade;
end|

delimiter ;

Now, you can get the age from a date:

select getIdade('1983-09-16');

If you date is in format Y-m-d H:i:s, you can do this:

select getIdade(substring_index('1983-09-16 23:43:01', ' ', 1));

You can reuse this function anywhere ;)

Idealmind
  • 1,278
  • 15
  • 8
0

I prefer use a function this way.

DELIMITER $$ DROP FUNCTION IF EXISTS `db`.`F_AGE` $$
    CREATE FUNCTION `F_AGE`(in_dob datetime) RETURNS int(11)
        NO SQL
    BEGIN
       DECLARE l_age INT;
       IF DATE_FORMAT(NOW(  ),'00-%m-%d') >= DATE_FORMAT(in_dob,'00-%m-%d') THEN
          -- This person has had a birthday this year
          SET l_age=DATE_FORMAT(NOW(  ),'%Y')-DATE_FORMAT(in_dob,'%Y');
        ELSE
          -- Yet to have a birthday this year
          SET l_age=DATE_FORMAT(NOW(  ),'%Y')-DATE_FORMAT(in_dob,'%Y')-1;
       END IF;
       RETURN(l_age);
    END $$

    DELIMITER ;

now to use

SELECT F_AGE('1979-02-11') AS AGE; 

OR

SELECT F_AGE(date) AS age FROM table;
HEMM
  • 11
0

There is two simple ways to do that:

  1.  

     select("users.birthdate",
             DB::raw("FLOOR(DATEDIFF(CURRENT_DATE, STR_TO_DATE(users.birthdate, '%Y-%m-%d'))/365) AS age_way_one"),
    
  2.  

     select("users.birthdate",DB::raw("(YEAR(CURDATE())-YEAR(users.birthdate)) AS age_way_two"))
    
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aouidane Med Amine
  • 1,571
  • 16
  • 17
  • Perhaps *describe* the two simple ways? Currently, it is not much more than a code-only/"try this" answer. What is the idea? What are some properties of them (accuracy, exceptions, valid range of use, performance, etc.)? Why should one be preferred over the other? Etc. Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/45835585/edit), not here in comments (******** ***without*** ******** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Oct 11 '22 at 17:24
0

This is how to calculate the age in MySQL:

select
  date_format(now(), '%Y') - date_format(date_of_birth, '%Y') - 
  (date_format(now(), '00-%m-%d') < date_format(date_of_birth, '00-%m-%d'))
as age from table
Mosty Mostacho
  • 42,742
  • 16
  • 96
  • 123