Age Calculator
Enter your date of birth and get your exact age in years, months and days, the total days, weeks, hours and minutes you have lived, the weekday you were born on, and a countdown to your next birthday. Works for any date, handles 29 February birthdays, and shows the same calculation for Excel, R and Python.
🎂 1. Calculator
Inputs
⚙ Advanced options
Your Result
___
Download your result as a plain text file. Change any field above and press Calculate to refresh it.
📊 2. Your Results
⚡ Quick Answer
An age calculator turns a date of birth into an exact age by counting whole years first, then whole months, then the leftover days.
Rule of thumb: never divide days by 365. That overstates age by about one day for every four years lived, because roughly one year in four has 366 days. Count real calendar days instead.
Every age calculator has to choose a method, and this one counts completed periods. Age also has one rule that surprises people: you are 0 years old on the day you are born and turn 1 on your first birthday. The years figure is unambiguous. The months and days are where calculators disagree, because some count whole months from your birth day of the month and others divide the leftover days by an average month of 30.44 days. This tool uses the first method, which is what official forms and spreadsheets use.
Key Takeaways
- An age calculator counts completed years, so a person born on 15 June 1995 is 31 on 30 August 2026, not 31.2.
- That same person has lived 11,399 days, which includes 8 leap days.
- Dividing days by 365 makes a 60 year old look about 15 days too old. Count real days.
- In Excel the exact age is =DATEDIF(A2,TODAY(),"Y"), a function that still works but no longer appears in the function list.
- A 29 February birthday does not change your exact age. It only changes which day you celebrate in a common year.
- Your birthday weekday repeats every 5, 6 or 11 years, not every 7, because leap years break the cycle.
💬 People Also Ask
How do I calculate my age manually, without an age calculator?
Subtract the birth year from the current year, then take one off if your birthday has not arrived yet this year. For the months and days, count whole months from your birth day of the month, then the days left over. Born 15 June 1995, on 30 August 2026: 31 years, 2 months, 15 days.
How many days old am I?
Subtract your date of birth from today and count every real day, leap days included. A person born on 15 June 1995 has lived 11,399 days by 30 August 2026. Multiplying 31 years by 365 gives 11,315, which is 84 days short, because it ignores eight leap days and the extra months.
What is the Excel formula for age from date of birth?
Use =DATEDIF(A2,TODAY(),"Y") for whole years. Add "YM" for the leftover months and "MD" for the leftover days to build the full age. DATEDIF is undocumented in Excel's function list but present in every version, and it is the only built-in that gives a true calendar age.
At what age does a person turn one year old?
On their first birthday, one year after the date of birth. You are 0 years old for your entire first year of life. This is the international convention. East Asian age reckoning historically counted a newborn as one and added a year each new year, a system South Korea formally left in June 2023.
How do I find my age on a future date?
Change the age as of field from today to the date you care about. Someone born on 15 June 1995 will be 34 years, 6 months and 17 days old on 1 January 2030. This is how you check school entry cutoffs, pension eligibility and licence age thresholds before the date arrives.
Why do two age calculators give different answers?
The years almost always match. The months and days differ because of the borrow method: when the current day of the month is earlier than your birth day, a month has to be borrowed, and tools disagree about which month's length to borrow. That produces answers one or two days apart.
📚 3. What Is an Age Calculator and How Does It Work?
An age calculator takes two dates, a date of birth and a reference date, and reports how much time separates them in the units people actually use. Age is not a subtraction of years. It is a count of completed periods: completed years first, then completed months inside the leftover part of the year, then the days left over after that. You are 31 the whole way from your 31st birthday to the day before your 32nd, and the months and days tell you where in that stretch you are standing.
The reason this needs a calculator at all is that months have different lengths. Subtracting 15 June from 30 August is easy. Subtracting 31 January from 1 March is not, because the answer depends on whether February had 28 or 29 days that year. Dates are written in a standard form under ISO 8601, but the standard says nothing about how to count age, so every tool has to choose a method and state it.
A worked one-liner: born 15 June 1995, measured on 30 August 2026. The birthday has passed this year, so the years are 2026 minus 1995, which is 31. From 15 June to 15 August is 2 whole months. From 15 August to 30 August is 15 days. The answer is 31 years, 2 months and 15 days.
A note on the method this tool uses, and why. When the reference day of the month is earlier than the birth day of the month, a month has to be borrowed, and the size of that borrow decides the answer. This calculator borrows the length of the month before the reference month, which is what Excel's DATEDIF, Python's relativedelta and most official forms do. Some calculators borrow the month before the birth month instead, and some skip the borrow entirely by dividing leftover days by 30.44. Those choices are why two tools can hand you answers a day or two apart while both look right. The years figure is never affected, which is why every legal use of age relies on years alone.
Who needs an exact age and why. Paediatricians plot growth against age in months, not years, because a two month difference matters enormously at that stage. Schools apply an entry cutoff on a fixed date. Pension and benefit systems test age to the day. Sports leagues band players by age at a season cutoff. Insurers price on age next birthday. Clinical trials set inclusion criteria in years. In every one of those the person asking wants a whole number of years and the date it changes, not a decimal.
The three ways of measuring age, compared.
| Method | How it works | Accuracy | Use it for |
|---|---|---|---|
| Calendar age | Completed years, then months, then days | Exact | Everything official: forms, eligibility, records |
| Total days | Straight subtraction of the two dates | Exact | Babies, clinical trials, anything measured in days |
| Decimal years | Total days divided by 365.2425 | Close, drifts near birthdays | Statistical models and regression only |
| Days divided by 365 | Ignores leap days entirely | Wrong by 1 day per 4 years | Nothing. Avoid it |
| Age next birthday | Completed years plus one | Exact but different | Insurance pricing, some actuarial tables |
Conclusion: calendar age and total days are both exact and both useful. The decimal versions exist for convenience in models, and the divide-by-365 version exists only as a mistake.
🧠 4. Interpretation of Your Result
4.1 What your years, months and days actually mean
An age calculator reports three numbers, and they answer different questions. The years figure is your age in the everyday sense, and it is the only part that appears on a form. It counts completed years, so it stays fixed for a full 365 or 366 days and then jumps by one overnight. The months and days tell you how deep into your current year of life you are. Two months and fifteen days means you passed your last birthday two and a half months ago and your next one is still most of a year away.
4.2 Why total days is often the more useful number
Total days is a straight subtraction with no borrowing, no month lengths and no convention to argue about, which makes it the number that never disagrees between tools. It is also the right unit for very young children, where a difference of weeks is clinically meaningful, and for anything being compared statistically, where a smooth continuous measure beats a step function that jumps once a year.
4.3 The leap days hidden inside your age
Roughly one year in four contains a 29 February. Over 31 years you cross about 8 of them, which is why 31 years is 11,399 days rather than the 11,315 that multiplying by 365 suggests. The gap grows with age: by 80 the divide-by-365 shortcut is about 20 days out. This is not a rounding quibble. In any context that counts days rather than years, it is a real error with a predictable direction.
4.4 What your birth weekday tells you
Your birthday does not simply move forward one weekday each year. A common year is 365 days, which is 52 weeks plus 1 day, so the weekday advances by one. A leap year adds a second day. The result is that your birthday returns to the same weekday after 5, 6 or 11 years, in a pattern that depends on where your birthday sits relative to 29 February. That is why some people go a decade without a weekend birthday.
4.5 How the birthday countdown is calculated
The countdown finds your next anniversary after the reference date and counts the calendar days between. If today is your birthday it reads zero rather than jumping to next year, which is the behaviour people expect. The one genuine edge case is a 29 February birthday in a common year, where there is no anniversary to count to, so the tool uses whichever observed date you selected.
4.6 What the milestone table is for
Milestone ages carry real consequences: 18 for adulthood in most countries, 21 for some licences, 65 or 67 for pensions, and various thresholds in between for driving, voting and insurance. The table gives you the exact date each one lands on and the weekday, so you can plan around it rather than discovering it. The dates are exact anniversaries, not approximations from days.
4.7 Age in months, and when it matters more than years
For a child under two, years are almost useless. A 12 month old and a 23 month old are both one, and they are entirely different children. That is why paediatric growth charts, vaccination schedules and developmental milestones are all indexed on months, and why the calculator reports total months alongside years. Above about age three, months stop carrying extra information for most purposes.
4.8 What to do next with your result
Three practical moves come out of any age calculator result. If you needed the age for a form, use the years figure only and note the reference date you used, because an age without a date is meaningless a month later. If you are checking eligibility, set the age as of field to the official cutoff date rather than today. And if you are working with a whole spreadsheet of birth dates, copy the Excel formula in Section 8 rather than running this tool repeatedly.
4.9 Common mistakes this age calculator prevents
- Dividing total days by 365, which drifts by a day for every four years lived.
- Subtracting birth year from current year and forgetting to check whether the birthday has passed, which makes almost half of all people a year too old.
- Treating a 29 February birthday as invalid in a common year rather than choosing an observed date.
- Reading a spreadsheet date that was stored as text, so the arithmetic silently fails or returns an error.
- Mixing day-month-year and month-day-year formats, which turns 03/04/1990 into two different birthdays.
- Using age today when the rule asks for age on a fixed cutoff date.
4.10 What this result does not tell you
It does not tell you whether an age qualifies you for anything, because that depends on a rule written somewhere else. It does not know local conventions such as East Asian age reckoning. It carries no time of day, so someone born at 23:50 and someone born at 00:10 the next morning are treated as a full day apart. And it makes no claim about life expectancy, which is a population statistic and says nothing about any individual.
✍ 5. How to Use Your Result
📌 How to use this one
- Always include the date the age was measured on. An age with no date goes stale immediately.
- Give the years figure first. That is the part anyone else will act on.
- Keep the months and days only where they matter, such as for a young child.
📌 How to use this one
- Forms want completed years and the date of birth, never a decimal age.
- Write the date of birth in ISO form when the form allows it, to remove any day and month ambiguity.
- If the form has a cutoff date, calculate against that date, not today.
📌 How to use this one
- Name the threshold and the exact date it is reached.
- State which rule you are testing against, because thresholds differ by country and scheme.
- Confirm the answer against the official rule before acting on it.
📌 How to use this one
- Paste it into a calendar event set to repeat yearly.
- Include the weekday so you can see at a glance whether it falls on a workday.
- Set the reminder a week ahead, not on the day itself.
📌 How to use this one
- Research records should carry age in days or months as well as years.
- State the index date the age was computed against, every time.
- Say which method produced the months and days, because tools disagree by a day or two.
∑ 6. Formulas Used
📝 7. How to Use This Calculator
The worked example carried through all ten steps is: born 15 June 1995, measured on 30 August 2026, giving 31 years, 2 months and 15 days.
- Enter your date of birth. The field is pre-filled with 15 June 1995 so the page is never blank. Click the calendar icon or type the date directly.
- Check the age as of date. It defaults to today. Leave it alone for your current age, or change it to a past or future date to see your age then.
- Press Calculate Age. The result panel shows 31 years old, the life stage badge, and your position on the 0 to 100 bar.
- Read the years, months and days. Section 2 leads with the full exact age. The years figure is the one to put on a form; the months and days say where you are inside your current year of life.
- Look at the total days lived. The stat cards give 11,399 days, 1,628 weeks and 3 days, 374 months and 273,576 hours, all counted from real calendar days rather than estimated.
- Check the birth weekday. 15 June 1995 was a Thursday. This is worth a glance because a wrong weekday is the fastest sign you typed the wrong year.
- Read the birthday countdown. 289 days to go, landing on a Tuesday. If today is your birthday it reads zero.
- Open the milestone table. It lists the exact dates you turn 18, 21, 30, 40, 50, 60, 65 and 70, with the weekday and whether each has passed.
- Set the leap day rule if you need it. For a 29 February birthday, choose whether it is observed on 1 March or 28 February in common years. Your exact age does not change either way.
- Copy or export. Copy Result gives one sentence, Download TXT the short file, and Download Doc and Download PDF the whole breakdown including the milestone table.
📈 8. How Do You Calculate Age in Excel?
Excel has exactly one function that gives a true calendar age, and it is the one Microsoft hides. DATEDIF does not appear in the function list, gets no tooltip as you type it, and is documented only as a compatibility function, yet it works in every version of Excel and in Google Sheets. It is the correct tool, and everything else people reach for is an approximation.
=DATEDIF(A2,TODAY(),"Y") and press Enter. That is the age in completed years. Format the cell as General, not as a date, or Excel will show the answer as a date in 1900.8.1 The functions you need
| You want | Excel formula | Note |
|---|---|---|
| Age in whole years | =DATEDIF(A2,TODAY(),"Y") | The answer for any form. Returns 31 |
| Leftover months | =DATEDIF(A2,TODAY(),"YM") | Months after the whole years. Returns 2 |
| Leftover days | =DATEDIF(A2,TODAY(),"MD") | Days after the whole months. Returns 15 |
| Total days lived | =TODAY()-A2 | Format as General. Returns 11399 |
| Total months lived | =DATEDIF(A2,TODAY(),"M") | Returns 374 |
| Total weeks lived | =INT((TODAY()-A2)/7) | Returns 1628 whole weeks |
| Full age as a sentence | =DATEDIF(A2,TODAY(),"Y")&" y "&DATEDIF(A2,TODAY(),"YM")&" m "&DATEDIF(A2,TODAY(),"MD")&" d" | Returns 31 y 2 m 15 d |
| Weekday you were born | =TEXT(A2,"dddd") | Returns Thursday |
| Next birthday | =DATE(YEAR(TODAY())+(DATE(YEAR(TODAY()),MONTH(A2),DAY(A2)) | Rolls to next year once the birthday has passed |
| Days to next birthday | =B2-TODAY() | With the next birthday in B2. Returns 289 |
| Age on a fixed date | =DATEDIF(A2,DATE(2030,1,1),"Y") | Swap TODAY() for any date. Returns 34 |
| Date of a milestone | =DATE(YEAR(A2)+18,MONTH(A2),DAY(A2)) | The exact date they turn 18 |
| Decimal age | =YEARFRAC(A2,TODAY(),1) | Basis 1 is actual over actual. For models only |
| Age next birthday | =DATEDIF(A2,TODAY(),"Y")+1 | Used by some insurers |
| Is it their birthday today? | =AND(MONTH(A2)=MONTH(TODAY()),DAY(A2)=DAY(TODAY())) | Returns TRUE or FALSE |
"MD" unit may give a negative number, a zero, or an inaccurate result, and advises against relying on it. In practice it is correct for the great majority of date pairs and wrong only in narrow cases around month ends. If exact days matter, compute them as =TODAY()-EDATE(A2,DATEDIF(A2,TODAY(),"M")) instead, which is what this calculator does internally.8.2 Step by step
1 Put a real date of birth in A2
Type the date and check it right aligns on its own. A left aligned date is text, and DATEDIF on text returns #VALUE! rather than an age.
The date of birth 15/06/1995 sits in A2, right aligned, which is how you know Excel has read it as a real date.
2 Get the years, and name the weekday while you are there
The weekday column costs one formula and catches typos instantly. If someone tells you they were born on a Saturday and the sheet says Thursday, the year is wrong.
=DATEDIF(A2,B2,"Y")=TEXT(A2,"dddd")
Three birth dates measured on 30/08/2026: ages 31, 22 and 36, born on a Thursday, a Sunday and a Wednesday.
3 Add the months and days for the full exact age
Three DATEDIF calls with different unit codes, joined with ampersands. This is the formula worth saving as a snippet, because you will need it again.
=DATEDIF(A2,B2,"YM")=DATEDIF(A2,B2,"MD")
Column E joins the three units. The worked example returns 31 y 2 m 15 d, and the infant row shows why months matter: 0 y 5 m 20 d is far more useful than "0".
4 Count total days, and see the divide-by-365 error
Straight subtraction gives the exact total. Dividing it by 365 gives a decimal that looks like an age but is not one.
=B2-A2=(B2-A2)/365
The 1948 birth date has lived 28,425 days including 19 leap days. Divide by 365 and you get 77.88, which reads as almost 78 when the true age is 77.
5 Finish the summary block
Six rows that answer every question anyone asks about an age. This is the block worth pasting into an email or a record.
=TEXT(A3,"dddd")=B7-A3
The finished block: exact age 31 y 2 m 15 d, 11,399 total days, born on a Thursday, next birthday in 289 days. Every number matches the R and Python scripts below.
8.3 The awkward cases
A 29 February date of birth. DATEDIF handles it correctly for the years: someone born on 29 February 2004 is 22 on 30 August 2026. The problem is the next birthday formula, because =DATE(2027,2,29) silently returns 1 March 2027. That is Excel choosing the roll-forward convention for you. If your rule says 28 February, you have to test for it explicitly.
The date of birth is later than the reference date. DATEDIF returns #NUM! rather than a negative age, which is the right behaviour: a person cannot have a negative age. Guard the formula with =IF(A2>B2,"check dates",DATEDIF(A2,B2,"Y")) when you are running it down a column of imported data.
Blank cells. An empty A2 is read as zero, which Excel treats as 0 January 1900, producing an age of 126 years and no error at all. This is the single most dangerous case in a spreadsheet of ages, because nothing looks broken. Always guard with =IF(A2="","",DATEDIF(A2,TODAY(),"Y")).
Dates before 1900. Excel cannot store them as dates in the 1900 system, so anyone born before 1 January 1900 cannot be aged with DATEDIF. This calculator handles 1900 onwards for the same practical reason.
TODAY() recalculates. A sheet of ages built on TODAY() changes every time it is opened, which is usually what you want and occasionally a disaster when the sheet is a dated record. If the age is part of a record, replace the formula with its value once.
8.4 Why your Excel answer might differ from R or Python
| Situation | What happens | Fix |
|---|---|---|
| DATEDIF "MD" edge cases | Microsoft documents it as unreliable; it can return a negative or zero day count around month ends | Compute leftover days as =B2-EDATE(A2,DATEDIF(A2,B2,"M")) |
| You used YEARFRAC | Returns a decimal on a day-count basis, which can differ from calendar age by a day near a birthday | Use DATEDIF with "Y" for a calendar age; keep YEARFRAC for models |
| You divided by 365 | Overstates by about one day per four years lived | Use exact day subtraction, or 365.2425 if a decimal is genuinely needed |
| Date read as text | #VALUE!, or worse, a plausible wrong answer after an autocorrect | Check alignment, or wrap with DATEVALUE |
| Regional date order | 03/04/1990 is 3 April in the UK and 4 March in the US, a month of difference in age | Enter as =DATE(1990,4,3) or use ISO format in shared files |
| Python without dateutil | A naive year subtraction forgets the birthday check and is a year out for roughly half of people | Use relativedelta, or the borrow logic in the section 10 script |
| Excel's 1900 leap year bug | Excel treats 29 February 1900 as real, so serials before March 1900 are one day out | Only affects births before March 1900 |
| Tool | Age in years | Total days | Full exact age |
|---|---|---|---|
| Excel | =DATEDIF(A2,TODAY(),"Y") | =TODAY()-A2 | Three DATEDIF calls joined |
| Google Sheets | =DATEDIF(A2,TODAY(),"Y") | =TODAY()-A2 | Identical to Excel |
| R | Borrow logic, or lubridate | as.integer(d2 - d1) | The script in section 9 |
| Python | relativedelta(d2, d1).years | (d2 - d1).days | relativedelta, or the section 10 script |
| SQL Server | DATEDIFF(year, dob, d2) then adjust | DATEDIFF(day, dob, d2) | DATEDIFF counts boundaries, not completed years |
| JavaScript | Compare year, month, day parts | Millisecond difference over 86400000 | No built-in; write the borrow |
Note the SQL Server row, which is the classic trap. DATEDIFF(year, '2025-12-31', '2026-01-01') returns 1, because it counts year boundaries crossed rather than completed years. Someone born yesterday would be reported as one year old on new year's day.
8.5 Charting ages in Excel
- Put your ages in one column and the labels in the column beside them.
- For a distribution, select the age column and use Insert → Charts → Histogram, then set the bin width to 5 or 10 years in Format Axis.
- For an age pyramid, split the ages by group, make one group negative, and use a stacked bar chart with the axis labels moved to the low position.
- Set the axis number format to
0so ages never display as decimals. - Label the axis with the reference date the ages were computed on. An unlabelled age chart is undated and therefore unreadable a year later.
Chart 2 in Section 2 of this page already plots your milestone ages against the years remaining, which is usually the view people actually want.
8.6 Excel errors you will probably hit
| Excel shows | Why | Fix |
|---|---|---|
#NUM! | The date of birth is later than the reference date | Check the two dates are the right way round in the DATEDIF arguments |
#VALUE! | One of the cells holds text that looks like a date | Retype it so it right aligns, or wrap with DATEVALUE |
#NAME? | DATEDIF misspelled, or a locale that expects a different separator | Check the spelling; try semicolons instead of commas in some locales |
| Age shows as a date in 1900 | The result cell inherited a date format | Set the number format to General or Number |
| Age of 126 from a blank row | An empty cell is read as zero, which is 0 January 1900 | Guard with =IF(A2="","",DATEDIF(A2,TODAY(),"Y")) |
| Everyone is one year too old | Year subtraction was used without the birthday check | Use DATEDIF, which handles it |
| Age changes every time the file opens | The formula uses TODAY() | Expected. Paste as values if the age is part of a fixed record |
| DATEDIF is not suggested as you type | Microsoft hides it from the function list | Not a fault. Type the whole name and it works |
##### | The column is too narrow | Double click the column border |
Google Sheets: every formula in this section works unchanged, including DATEDIF, YEARFRAC, EDATE and TEXT. Sheets counts from 30 December 1899 and has no 1900 leap year bug, so the two agree on every birth date after March 1900.
📈 9. How Do You Calculate Age in R?
Base R has no age function. A Date is a number of days, so ref - dob gives you total days immediately, but turning that into completed years, months and days needs the borrow logic written out. The script below does exactly that using base R only, so there is nothing to install, and every function it uses is documented in the base R date reference.
Rscript. Change only the two dates in the marked block to use your own.9.1 The complete script
R, base only, saves age_plot.png
# ============================================================ # Age from a date of birth, complete worked example # Base R only. Prints a plain-English verdict and saves one # 300 dpi figure called age_plot.png # ============================================================ # ---- 1. YOUR DATA: change only these two lines --------------- dob <- as.Date("1995-06-15") # date of birth ref <- as.Date("2026-08-30") # measure the age on this date # ref <- Sys.Date() # uncomment for the age right now # ------------------------------------------------------------- # Alternative: read a column of birth dates from a CSV # dat <- read.csv("people.csv", stringsAsFactors = FALSE) # dat <- dat[!is.na(dat$dob), ] # drop missing values # dob <- as.Date(dat$dob[1]) if (dob > ref) stop("The date of birth is after the reference date.") days_in_month <- function(y, m) { as.integer(format(seq(as.Date(sprintf("%04d-%02d-01", y, m)), by = "month", length.out = 2)[2] - 1, "%d")) } exact_age <- function(d1, d2) { p1 <- as.POSIXlt(d1); p2 <- as.POSIXlt(d2) y <- (p2$year - p1$year) m <- (p2$mon - p1$mon) d <- (p2$mday - p1$mday) if (d < 0) { # borrow a month m <- m - 1 pm <- if (p2$mon == 0) 12 else p2$mon py <- if (p2$mon == 0) p2$year + 1899 else p2$year + 1900 d <- d + days_in_month(py, pm) } if (m < 0) { y <- y - 1; m <- m + 12 } # borrow a year c(years = y, months = m, days = d) } is_leap <- function(y) (y %% 4 == 0 & y %% 100 != 0) | (y %% 400 == 0) a <- exact_age(dob, ref) total_days <- as.integer(ref - dob) total_months<- a["years"] * 12 + a["months"] yrs <- seq(as.integer(format(dob, "%Y")), as.integer(format(ref, "%Y"))) feb29 <- as.Date(paste0(yrs[is_leap(yrs)], "-02-29")) leap_days <- sum(feb29 >= dob & feb29 <= ref) next_birthday <- function(d1, d2) { for (y in c(as.integer(format(d2, "%Y")), as.integer(format(d2, "%Y")) + 1)) { m <- as.integer(format(d1, "%m")); dd <- as.integer(format(d1, "%d")) if (m == 2 && dd == 29 && !is_leap(y)) { m <- 3; dd <- 1 } b <- as.Date(sprintf("%04d-%02d-%02d", y, m, dd)) if (b >= d2) return(b) } } nb <- next_birthday(dob, ref) wait <- as.integer(nb - ref) cat("Date of birth :", format(dob, "%A %d %B %Y"), "\n") cat("Age as of :", format(ref, "%A %d %B %Y"), "\n") cat("Exact age :", a["years"], "years,", a["months"], "months,", a["days"], "days\n") cat("Total days lived:", format(total_days, big.mark = ","), "\n") cat("Total weeks :", total_days %/% 7, "weeks and", total_days %% 7, "days\n") cat("Total months :", total_months, "\n") cat("Total hours :", format(total_days * 24, big.mark = ","), "\n") cat("Leap days lived :", leap_days, "\n") cat("Next birthday :", format(nb, "%A %d %B %Y"), "in", wait, "days\n") cat("\nVERDICT: this person is", a["years"], "years old, and has lived", format(total_days, big.mark = ","), "days including", leap_days, "leap days.\n") # ---- 2. FIGURE: one 300 dpi PNG ----------------------------- marks <- c(18, 21, 30, 40, 50, 60, 65, 70) dd <- as.integer(format(dob, "%d")); mm <- as.integer(format(dob, "%m")) if (mm == 2 && dd == 29) dd <- 28 mdates <- as.Date(sprintf("%04d-%02d-%02d", as.integer(format(dob, "%Y")) + marks, mm, dd)) gap <- as.numeric(mdates - ref) / 365.2425 cols <- ifelse(gap < 0, "#94a3b8", "#16a34a") png("age_plot.png", width = 9, height = 5, units = "in", res = 300) par(mar = c(4.5, 5.5, 3.5, 2)) bp <- barplot(rev(gap), horiz = TRUE, col = rev(cols), border = "#1e3a8a", names.arg = rev(marks), las = 1, xlim = c(min(gap) - 8, max(gap) + 12), xlab = paste("Years from", format(ref, "%d %B %Y"), " (negative = already passed)"), ylab = "Milestone age", main = "Age milestones", col.main = "#1e3a8a") text(rev(gap) + ifelse(rev(gap) >= 0, 0.8, -0.8), bp, format(rev(mdates), "%d %b %Y"), adj = ifelse(rev(gap) >= 0, 0, 1), cex = 0.8, col = "#1f2937") abline(v = 0, col = "#1e3a8a", lwd = 1.4) dev.off() cat("\nSaved age_plot.png at 300 dpi\n")
9.2 What each part of the script does
| Lines | What it does | Why it matters |
|---|---|---|
| The two input lines | Set the date of birth and the reference date | The only lines you should ever need to edit |
if (dob > ref) stop(...) | Refuses to compute a negative age | Imported data always contains at least one reversed pair. Failing loudly beats a nonsense number |
days_in_month() | Returns the real length of a given month | The borrow needs a real month length, never an assumed 30 |
exact_age() | Subtracts year, month and day parts, then borrows when the day or month goes negative | This is the whole algorithm. It is what DATEDIF does internally |
as.POSIXlt() | Splits a date into year, month and day components | Note that $year is years since 1900 and $mon is 0 based |
is_leap() | Applies the full 4, 100 and 400 rule | The century exception is what catches naive implementations out on 1900 and 2100 |
feb29 and leap_days | Counts how many 29 Februarys fell inside the lifetime | Explains why total days is never years times 365 |
next_birthday() | Finds the next anniversary, rolling a leap day birth to 1 March in a common year | Returns the reference date itself when today is the birthday, so the countdown reads 0 |
cat(...) block | Prints the plain-English verdict | Reading the age as a sentence catches a wrong year faster than any number will |
png(..., res = 300) | Saves one publication-ready figure | 300 dpi is the usual minimum for print and slides |
9.3 What the figure shows
The script writes age_plot.png to your working directory. It is a horizontal bar chart of the milestone ages, 18 through 70, drawn as years from the reference date. Bars to the left of the zero line are milestones already passed and are drawn grey; bars to the right are still ahead and are drawn green. The exact calendar date of each milestone is printed at the end of its bar.
Read it as a planning view rather than a result. The useful information is the calendar date on each bar, because that is the day the threshold is actually crossed.
9.4 Problems and fixes
| Symptom | Cause | Fix |
|---|---|---|
character string is not in a standard unambiguous format | The date was not in ISO form | Use as.Date("15/06/1995", format = "%d/%m/%Y") |
| The age is out by a year | A naive year(ref) - year(dob) was used with no birthday check | Use exact_age(), which applies the borrow |
$year gives 95 not 1995 | POSIXlt$year counts years since 1900 | Add 1900, as the script does inside days_in_month |
$mon gives 5 for June | POSIXlt$mon is 0 based | Add 1 whenever you print it. The subtraction itself is unaffected |
| Weekday names are in another language | The system locale is not English | Run Sys.setlocale("LC_TIME", "C") before formatting |
Leap day birth crashes as.Date | 29 February does not exist in a common year | The next_birthday() helper rewrites it to 1 March first |
| The PNG is blank | dev.off() was not reached because of an error above it | Run the script top to bottom in one go, then read the console |
9.5 One-liners worth remembering
| Task | R code |
|---|---|
| Total days lived | as.integer(Sys.Date() - as.Date("1995-06-15")) |
| Total weeks lived | as.integer(Sys.Date() - as.Date("1995-06-15")) %/% 7 |
| Whole years, with lubridate | lubridate::interval(dob, Sys.Date()) %/% lubridate::years(1) |
| Weekday of birth | weekdays(as.Date("1995-06-15")) |
| Date they turn 18 | seq(dob, by = "year", length.out = 19)[19] |
| Is this year a leap year? | (y %% 4 == 0 & y %% 100 != 0) | y %% 400 == 0 |
| Decimal age | as.numeric(Sys.Date() - dob) / 365.2425 |
| Age for a whole column | sapply(dobs, function(d) exact_age(d, Sys.Date())["years"]) |
| Bin ages into groups | cut(ages, breaks = c(0, 18, 30, 50, 65, Inf), right = FALSE) |
| Days to next birthday | as.integer(next_birthday(dob, Sys.Date()) - Sys.Date()) |
📈 10. How Do You Calculate Age in Python?
The shortest correct answer in Python is relativedelta from the dateutil package: relativedelta(ref, dob).years gives completed years, with .months and .days for the rest. The standard library's timedelta deliberately has no year or month unit, as the timedelta documentation explains, because neither has a fixed length. The script below writes the borrow out by hand so it runs with no third-party package at all, and it produces exactly the same numbers as the R script above.
datetime and calendar from the standard library, and matplotlib for the figure. Install the one that is not built in with:pip install matplotlibAdd
pip install python-dateutil only if you want the relativedelta shortcut instead of the hand-written borrow.10.1 The complete script
Python 3, standard library plus matplotlib, saves age_plot.png
# ============================================================ # Age from a date of birth, complete worked example # Prints a plain-English verdict and saves one 300 dpi figure # ============================================================ from datetime import date, timedelta import calendar import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt # ---- 1. YOUR DATA: change only these two lines --------------- dob = date(1995, 6, 15) # date of birth ref = date(2026, 8, 30) # measure the age on this date # ref = date.today() # uncomment for the age right now # ------------------------------------------------------------- # Alternative: read a column of birth dates from a CSV # import pandas as pd # df = pd.read_csv("people.csv", parse_dates=["dob"]) # df = df.dropna(subset=["dob"]) # drop missing values # dob = df["dob"].iloc[0].date() if dob > ref: raise ValueError("The date of birth is after the reference date.") def exact_age(d1, d2): """Completed years, then months, then leftover days.""" y = d2.year - d1.year m = d2.month - d1.month d = d2.day - d1.day if d < 0: # borrow a month m -= 1 pm = d2.month - 1 or 12 py = d2.year if d2.month > 1 else d2.year - 1 d += calendar.monthrange(py, pm)[1] if m < 0: # borrow a year y -= 1 m += 12 return y, m, d years, months, days = exact_age(dob, ref) total_days = (ref - dob).days total_months = years * 12 + months leap_days = sum(1 for y in range(dob.year, ref.year + 1) if calendar.isleap(y) and dob <= date(y, 2, 29) <= ref) # next birthday, rolling a 29 February birth to 1 March in a common year def next_birthday(d1, d2): for y in (d2.year, d2.year + 1): m, dd = d1.month, d1.day if m == 2 and dd == 29 and not calendar.isleap(y): m, dd = 3, 1 b = date(y, m, dd) if b >= d2: return b nb = next_birthday(dob, ref) wait = (nb - ref).days print("Date of birth :", dob.strftime("%A %d %B %Y")) print("Age as of :", ref.strftime("%A %d %B %Y")) print("Exact age :", years, "years,", months, "months,", days, "days") print("Total days lived:", format(total_days, ",")) print("Total weeks :", total_days // 7, "weeks and", total_days % 7, "days") print("Total months :", total_months) print("Total hours :", format(total_days * 24, ",")) print("Leap days lived :", leap_days) print("Next birthday :", nb.strftime("%A %d %B %Y"), "in", wait, "days") print() print("VERDICT: this person is", years, "years old, and has lived", format(total_days, ","), "days including", leap_days, "leap days.") # ---- 2. FIGURE: one 300 dpi PNG ----------------------------- marks = [18, 21, 30, 40, 50, 60, 65, 70] dates = [date(dob.year + k, dob.month, dob.day if not (dob.month == 2 and dob.day == 29) else 28) for k in marks] gap = [(d - ref).days / 365.2425 for d in dates] colors = ["#94a3b8" if g < 0 else "#16a34a" for g in gap] fig, ax = plt.subplots(figsize=(9, 5)) bars = ax.barh([str(k) for k in marks], gap, color=colors, edgecolor="#1e3a8a", linewidth=0.8) for bar, d, g in zip(bars, dates, gap): off = 0.6 if g >= 0 else -0.6 ax.text(g + off, bar.get_y() + bar.get_height() / 2, d.strftime("%d %b %Y"), va="center", ha="left" if g >= 0 else "right", fontsize=9, color="#1f2937") ax.axvline(0, color="#1e3a8a", linewidth=1.4) ax.set_xlabel("Years from " + ref.strftime("%d %B %Y") + " (negative = already passed)") ax.set_ylabel("Milestone age") ax.set_title("Age milestones", fontsize=13, color="#1e3a8a") ax.invert_yaxis() ax.spines[["top", "right"]].set_visible(False) fig.tight_layout() fig.savefig("age_plot.png", dpi=300) print("\nSaved age_plot.png at 300 dpi")
10.2 What each part of the script does
| Lines | What it does | Why it matters |
|---|---|---|
| The two input lines | Set the date of birth and the reference date | The only lines you should ever need to edit |
date(1995, 6, 15) | Builds the date from year, month and day parts | Safer than parsing a string, which can be read in the wrong order or as UTC |
raise ValueError | Refuses a date of birth later than the reference date | A negative age is always a data error, never a result |
exact_age() | Subtracts the parts, then borrows a month and a year as needed | Identical logic to the R script, which is why the two agree exactly |
calendar.monthrange() | Returns the real number of days in the borrowed month | Handles February in leap and common years without a special case |
(ref - dob).days | Total days lived, exact | The one number no two calculators ever disagree about |
calendar.isleap() | Applies the full 4, 100 and 400 rule | Counting the leap days lived explains the gap from years times 365 |
next_birthday() | Finds the next anniversary, rolling 29 February to 1 March in a common year | Returns the reference date itself on a birthday, so the countdown reads 0 |
print block | Prints the plain-English verdict | The sentence is what you paste into a record or an email |
fig.savefig(dpi=300) | Saves one publication-ready figure | Same chart, same colours and same labels as the R version |
10.3 What the figure shows
The chart written to age_plot.png is identical in content to the R figure in section 9.3: one horizontal bar per milestone age, grey for milestones already passed, green for those still ahead, with the exact calendar date printed at the end of each bar. Run both scripts on the same date of birth and the two PNGs carry the same dates.
10.4 Problems and fixes
| Symptom | Cause | Fix |
|---|---|---|
TypeError: unsupported operand type(s) | A datetime was subtracted from a date | Call .date() on the datetime so both sides are the same type |
| The age is out by a year | A plain ref.year - dob.year with no birthday check | Use exact_age(), or relativedelta(ref, dob).years |
ValueError: day is out of range for month | A 29 February anniversary was built in a common year | The next_birthday() helper rewrites it to 1 March first |
| The result is one day out | The date was parsed from a string and read as UTC midnight | Build it with date(y, m, d), or datetime.strptime(...).date() |
ModuleNotFoundError: dateutil | relativedelta is not in the standard library | Either pip install python-dateutil, or use this script, which needs neither |
| Ages in a DataFrame come out as timedeltas | Pandas subtraction returns a Timedelta | Use .dt.days, then convert, or apply exact_age row by row |
| The figure never appears | No display is available on a server | matplotlib.use("Agg") is already set at the top of the script |
10.5 One-liners worth remembering
| Task | Python code |
|---|---|
| Total days lived | (date.today() - date(1995, 6, 15)).days |
| Whole years, with dateutil | relativedelta(date.today(), dob).years |
| Full exact age, with dateutil | rd = relativedelta(date.today(), dob); rd.years, rd.months, rd.days |
| Weekday of birth | dob.strftime("%A") |
| Total weeks lived | (date.today() - dob).days // 7 |
| Date they turn 18 | dob.replace(year=dob.year + 18) |
| Is this a leap year? | calendar.isleap(2028) |
| Decimal age | (date.today() - dob).days / 365.2425 |
| Age for a pandas column | (pd.Timestamp.today() - df["dob"]).dt.days // 365 for a rough figure |
| Bin ages into groups | pd.cut(ages, bins=[0, 18, 30, 50, 65, 200], right=False) |
| Days to next birthday | (next_birthday(dob, date.today()) - date.today()).days |
DATEDIF gives the same age. If they disagree, the cause is almost always a date parsed as text or a year subtraction without the birthday check.📋 11. Reference Tables
11.1 Age in every unit, for a person born 15 June 1995
| Unit | Value on 30 August 2026 | How it is counted |
|---|---|---|
| Years | 31 | Completed years since the date of birth |
| Years, months, days | 31 y 2 m 15 d | The exact calendar age |
| Total months | 374 | Whole years times 12, plus the leftover months |
| Total weeks | 1,628 weeks and 3 days | Total days divided by 7 |
| Total days | 11,399 | Real calendar days, including 8 leap days |
| Total hours | 273,576 | Assumes a 24 hour day, ignores daylight saving |
| Total minutes | 16,414,560 | Total hours times 60 |
| Decimal age | 31.21 | Total days divided by 365.2425 |
| Days divided by 365 | 31.23 | Wrong. Overstates by 8 days of leap time |
| Age next birthday | 32 | Completed years plus one, used by some insurers |
Conclusion: years and total days are the two numbers worth recording. Everything else in this table is derived from them, and the last row of the list is an error rather than a unit.
11.2 Total days lived at each round age
| Age in years | Days lived, born 15 June 1995 | Years × 365 | Shortfall | Leap days |
|---|---|---|---|---|
| 1 | 366 | 365 | 1 days | 1 |
| 5 | 1,827 | 1,825 | 2 days | 2 |
| 10 | 3,653 | 3,650 | 3 days | 3 |
| 18 | 6,575 | 6,570 | 5 days | 5 |
| 21 | 7,671 | 7,665 | 6 days | 6 |
| 25 | 9,132 | 9,125 | 7 days | 7 |
| 30 | 10,958 | 10,950 | 8 days | 8 |
| 40 | 14,610 | 14,600 | 10 days | 10 |
| 50 | 18,263 | 18,250 | 13 days | 13 |
| 60 | 21,915 | 21,900 | 15 days | 15 |
| 65 | 23,742 | 23,725 | 17 days | 17 |
| 70 | 25,568 | 25,550 | 18 days | 18 |
| 80 | 29,220 | 29,200 | 20 days | 20 |
| 90 | 32,873 | 32,850 | 23 days | 23 |
| 100 | 36,525 | 36,500 | 25 days | 25 |
Conclusion: the shortfall column is exactly the leap day count. That is the whole reason multiplying years by 365 fails, and it grows by one day every four years without exception until a non-leap century year.
11.3 What age you are on a given birth year, as of 2026
| Birth year | Age if the birthday has passed | Age if it has not | Generation label |
|---|---|---|---|
| 2020 | 6 | 5 | Generation Alpha |
| 2010 | 16 | 15 | Generation Z |
| 2005 | 21 | 20 | Generation Z |
| 2000 | 26 | 25 | Generation Z |
| 1995 | 31 | 30 | Millennial |
| 1990 | 36 | 35 | Millennial |
| 1985 | 41 | 40 | Millennial |
| 1980 | 46 | 45 | Generation X |
| 1975 | 51 | 50 | Generation X |
| 1970 | 56 | 55 | Generation X |
| 1965 | 61 | 60 | Generation X |
| 1960 | 66 | 65 | Baby boomer |
| 1955 | 71 | 70 | Baby boomer |
| 1950 | 76 | 75 | Baby boomer |
| 1945 | 81 | 80 | Silent generation |
Conclusion: two people born in the same year differ in age by a full year for part of every year. This is why a birth year on its own is never enough to establish an age, and why forms ask for a full date of birth.
11.4 The Excel DATEDIF unit codes
| Unit code | What it returns | Result for 15/06/1995 to 30/08/2026 | Safe to use? |
|---|---|---|---|
"Y" | Completed years between the dates | 31 | Yes |
"M" | Completed months between the dates | 374 | Yes |
"D" | Days between the dates | 11399 | Yes |
"YM" | Months after the whole years | 2 | Yes |
"MD" | Days after the whole months | 15 | Documented as unreliable |
"YD" | Days after the whole years, ignoring the year | 76 | Behaves oddly across year ends |
Conclusion: the first four codes are dependable. Microsoft itself warns that "MD" can return a negative or inaccurate result, so compute leftover days by subtracting an EDATE offset when the exact figure matters. As of 2026, DATEDIF is still present in every Excel version despite being absent from the function list.
11.5 When your birthday falls, 2026 to 2040
| Year | Age turning | Date | Weekday | Leap year? |
|---|---|---|---|---|
| 2026 | 31 | 15 Jun 2026 | Monday | No |
| 2027 | 32 | 15 Jun 2027 | Tuesday | No |
| 2028 | 33 | 15 Jun 2028 | Thursday | Yes |
| 2029 | 34 | 15 Jun 2029 | Friday | No |
| 2030 | 35 | 15 Jun 2030 | Saturday | No |
| 2031 | 36 | 15 Jun 2031 | Sunday | No |
| 2032 | 37 | 15 Jun 2032 | Tuesday | Yes |
| 2033 | 38 | 15 Jun 2033 | Wednesday | No |
| 2034 | 39 | 15 Jun 2034 | Thursday | No |
| 2035 | 40 | 15 Jun 2035 | Friday | No |
| 2036 | 41 | 15 Jun 2036 | Sunday | Yes |
| 2037 | 42 | 15 Jun 2037 | Monday | No |
| 2038 | 43 | 15 Jun 2038 | Tuesday | No |
| 2039 | 44 | 15 Jun 2039 | Wednesday | No |
| 2040 | 45 | 15 Jun 2040 | Friday | Yes |
Conclusion: the weekday advances by one each common year and by two across a leap year, so it returns to the same day after 5, 6 or 11 years rather than every 7. Reading down the weekday column shows that pattern directly.
11.6 Leap day birthdays, 2024 to 2044
| Year | Does 29 February exist? | Observed on 1 March | Observed on 28 February |
|---|---|---|---|
| 2024 | Yes | Celebrated on the real date, 29 February 2024 | |
| 2025 | No | 01 Mar 2025 | 28 Feb 2025 |
| 2026 | No | 01 Mar 2026 | 28 Feb 2026 |
| 2027 | No | 01 Mar 2027 | 28 Feb 2027 |
| 2028 | Yes | Celebrated on the real date, 29 February 2028 | |
| 2029 | No | 01 Mar 2029 | 28 Feb 2029 |
| 2030 | No | 01 Mar 2030 | 28 Feb 2030 |
| 2031 | No | 01 Mar 2031 | 28 Feb 2031 |
| 2032 | Yes | Celebrated on the real date, 29 February 2032 | |
| 2033 | No | 01 Mar 2033 | 28 Feb 2033 |
| 2034 | No | 01 Mar 2034 | 28 Feb 2034 |
| 2035 | No | 01 Mar 2035 | 28 Feb 2035 |
| 2036 | Yes | Celebrated on the real date, 29 February 2036 | |
| 2037 | No | 01 Mar 2037 | 28 Feb 2037 |
| 2038 | No | 01 Mar 2038 | 28 Feb 2038 |
| 2039 | No | 01 Mar 2039 | 28 Feb 2039 |
| 2040 | Yes | Celebrated on the real date, 29 February 2040 | |
| 2041 | No | 01 Mar 2041 | 28 Feb 2041 |
| 2042 | No | 01 Mar 2042 | 28 Feb 2042 |
| 2043 | No | 01 Mar 2043 | 28 Feb 2043 |
| 2044 | Yes | Celebrated on the real date, 29 February 2044 | |
Conclusion: a leap day baby gets a real birthday once every four years and an observed one in between. The exact age in years, months and days is identical under either convention. Only the countdown to the next birthday changes.
11.7 Common age thresholds and what they usually govern
| Age | Commonly governs | Date reached, born 15 June 1995 | Weekday |
|---|---|---|---|
| 16 | Minimum working age and some driving licences in several countries | 15 Jun 2011 | Wednesday |
| 18 | Legal adulthood and voting in most countries | 15 Jun 2013 | Saturday |
| 21 | Some licences, and the drinking age in the United States | 15 Jun 2016 | Wednesday |
| 25 | Lower car hire surcharges in many markets | 15 Jun 2020 | Monday |
| 30 | Some tax and savings scheme thresholds | 15 Jun 2025 | Sunday |
| 40 | Routine health screening begins in several systems | 15 Jun 2035 | Friday |
| 50 | Catch-up retirement contributions in some schemes | 15 Jun 2045 | Thursday |
| 60 | Early pension access in several countries | 15 Jun 2055 | Tuesday |
| 65 | Traditional retirement age and senior concessions | 15 Jun 2060 | Tuesday |
| 67 | Full state pension age in a number of countries | 15 Jun 2062 | Thursday |
| 70 | Mandatory pension drawdown in several systems | 15 Jun 2065 | Monday |
Conclusion: every threshold in this table varies by country and scheme, and several have been changing upward. Treat the ages as typical rather than authoritative, and confirm the current rule with the official source before relying on any of them. Figures as of 2026.
📈 12. Example Results
A straightforward adult age
The clean case the whole page is built on.
Someone born on 15 June 1995 needs their exact age for a form dated 30 August 2026.
| Item | Value | Note |
|---|---|---|
| Date of birth | 15 June 1995 | Thursday |
| Age as of | 30 August 2026 | Sunday |
| Exact age | 31 years, 2 months, 15 days | Completed years, then months, then days |
| Total days lived | 11,399 | Real calendar days |
| Total weeks | 1,628 weeks and 3 days | Total days divided by 7 |
| Total months | 374 | Whole months lived |
| Leap days lived | 8 | 29 Februarys inside the lifetime |
| Next birthday | 15 June 2027 | Tuesday, in 289 days |
What it means: The birthday has already passed in 2026, so the years are simply 2026 minus 1995. Notice that 31 years is 11,399 days rather than the 11,315 that multiplying by 365 would give, a gap of exactly the 8 leap days lived.
How to use it: Age 31 (31 years, 2 months, 15 days as at 30 August 2026), date of birth 15 June 1995.
Born on 29 February
The case that breaks naive calculators.
Someone born on 29 February 2004 wants their age, and wants to know when they celebrate in 2027.
| Item | Value | Note |
|---|---|---|
| Date of birth | 29 February 2004 | Sunday |
| Age as of | 30 August 2026 | Sunday |
| Exact age | 22 years, 6 months, 1 days | Completed years, then months, then days |
| Total days lived | 8,218 | Real calendar days |
| Total weeks | 1,174 weeks and 0 days | Total days divided by 7 |
| Total months | 270 | Whole months lived |
| Leap days lived | 6 | 29 Februarys inside the lifetime |
| Next birthday | 01 March 2027 | Monday, in 183 days |
| 29 February exists in 2026? | No | 2026 is a common year |
| Observed birthday, 1 March rule | 01 March 2027 | The legal convention in most places |
| Observed birthday, 28 February rule | 28 February 2027 | The common everyday choice |
| Next real 29 February | 29 February 2028 | Four years between real birthdays |
What it means: Excel's =DATE(2027,2,29) silently returns 1 March 2027, which happens to match the legal convention but is Excel guessing rather than deciding. If your rule says 28 February you must test for it explicitly, which is why this calculator makes it a setting rather than an assumption.
How to use it: Age 22 as at 30 August 2026, date of birth 29 February 2004; birthday observed on 1 March in common years.
A five month old baby
Where years are useless and months are everything.
A paediatric record needs the age of a baby born on 10 March 2026, as at 30 August 2026.
| Item | Value | Note |
|---|---|---|
| Date of birth | 10 March 2026 | Tuesday |
| Age as of | 30 August 2026 | Sunday |
| Exact age | 0 years, 5 months, 20 days | Completed years, then months, then days |
| Total days lived | 173 | Real calendar days |
| Total weeks | 24 weeks and 5 days | Total days divided by 7 |
| Total months | 5 | Whole months lived |
| Leap days lived | 0 | 29 Februarys inside the lifetime |
| Next birthday | 10 March 2027 | Wednesday, in 192 days |
| Age in completed years | 0 | True but useless at this stage |
| Age in weeks | 24 weeks and 5 days | The unit used for the first few months |
| Why months matter | A 12 and a 23 month old are both 1 | Growth charts are indexed on months, never years |
What it means: This is the strongest argument for a calculator that reports every unit rather than just the years. Growth charts, vaccination schedules and developmental milestones for the first two years are all indexed on months or weeks, and rounding to years discards the entire signal.
How to use it: Age 5 months and 20 days (173 days) as at 30 August 2026, date of birth 10 March 2026.
Born on the 31st
The borderline case where the borrow rule shows itself.
Someone born on 31 January 1990 checks their age on 30 August 2026, one day short of a clean month.
| Item | Value | Note |
|---|---|---|
| Date of birth | 31 January 1990 | Wednesday |
| Age as of | 30 August 2026 | Sunday |
| Exact age | 36 years, 6 months, 30 days | Completed years, then months, then days |
| Total days lived | 13,360 | Real calendar days |
| Total weeks | 1,908 weeks and 4 days | Total days divided by 7 |
| Total months | 438 | Whole months lived |
| Leap days lived | 9 | 29 Februarys inside the lifetime |
| Next birthday | 31 January 2027 | Sunday, in 154 days |
| Borrow applied? | Yes | 30 August is before the 31st of the month |
| Month borrowed from | July, 31 days | The month before the reference month |
| If August were borrowed instead | 6 months 30 days | Same here, but the two rules can differ by a day |
| Tomorrow's answer | 6 months 31 days? No, 7 months 0 days | The months tick over on 31 August |
What it means: This is exactly the situation Microsoft warns about for DATEDIF's "MD" unit. On the very next day the answer becomes 7 months and 0 days. If two calculators are ever going to disagree with each other, it is on a date pair that looks like this one.
How to use it: Age 36 (36 years, 6 months, 30 days as at 30 August 2026), date of birth 31 January 1990.
A 77 year old
Where the divide-by-365 error becomes large.
A pension record needs the exact age of someone born on 2 November 1948, as at 30 August 2026.
| Item | Value | Note |
|---|---|---|
| Date of birth | 02 November 1948 | Tuesday |
| Age as of | 30 August 2026 | Sunday |
| Exact age | 77 years, 9 months, 28 days | Completed years, then months, then days |
| Total days lived | 28,425 | Real calendar days |
| Total weeks | 4,060 weeks and 5 days | Total days divided by 7 |
| Total months | 933 | Whole months lived |
| Leap days lived | 19 | 29 Februarys inside the lifetime |
| Next birthday | 02 November 2026 | Monday, in 64 days |
| Days divided by 365 | 77.88 | Reads as almost 78 when the true age is 77 |
| Decimal age, /365.2425 | 77.83 | The correct decimal, still not a calendar age |
| Error from the 365 shortcut | 19 days | Exactly the leap days lived |
| Turns 78 on | 02 November 2026 | In 64 days |
What it means: Nineteen leap days is nearly three weeks of drift. In a pension or benefits context, where a threshold is tested to the day, that is the difference between eligible and not. Always count real days.
How to use it: Age 77 (77 years, 9 months, 28 days as at 30 August 2026), date of birth 2 November 1948.
Working out a future threshold
Using a future reference date instead of today.
Someone born on 20 April 1962 wants to know when they reach a state pension age of 67.
| Item | Value | Note |
|---|---|---|
| Date of birth | 20 April 1962 | Friday |
| Age as of | 30 August 2026 | Sunday |
| Exact age | 64 years, 4 months, 10 days | Completed years, then months, then days |
| Total days lived | 23,508 | Real calendar days |
| Total weeks | 3,358 weeks and 2 days | Total days divided by 7 |
| Total months | 772 | Whole months lived |
| Leap days lived | 16 | 29 Februarys inside the lifetime |
| Next birthday | 20 April 2027 | Tuesday, in 233 days |
| Age today | 64 years, 4 months, 10 days | As at 30 August 2026 |
| Turns 67 on | 20 April 2029 | A Friday |
| Days until then | 964 | Just over two and a half years |
| Age on 1 January 2029 | 66 years, 8 months, 12 days | Still short of the threshold |
| How to check it | Set age as of to the cutoff date | Rather than working it out from today's age |
What it means: The reliable way to test any eligibility rule is to put the official cutoff date into the age as of field and read the age directly, rather than adding years to today's age in your head. Pension ages in particular have been moving, so confirm the current figure with the official source.
How to use it: Reaches age 67 on 20 April 2029, date of birth 20 April 1962; confirm the applicable pension age with the official scheme.
Your age on a date years ahead
The same calculation, pointed forwards.
The person from example 1 wants their age on 1 January 2030, for a long-term plan.
| Item | Value | Note |
|---|---|---|
| Date of birth | 15 June 1995 | Thursday |
| Age as of | 01 January 2030 | Tuesday |
| Exact age | 34 years, 6 months, 17 days | Completed years, then months, then days |
| Total days lived by then | 12,619 | Real calendar days |
| Days from 30 Aug 2026 | 1,220 | How far ahead the reference date is |
| Age turned most recently | 34, on 15 June 2029 | The last birthday before the reference date |
| Leap days lived by then | 9 | One more than by 2026, from 29 February 2028 |
| Next birthday after that | 15 June 2030 | A Saturday |
What it means: The only thing to watch is that the leap day count keeps growing: by 1 January 2030 this person has lived through 9 leap days rather than 8, because 2028 has been crossed. Any calculation that assumed a fixed 365 day year would now be a full extra day out.
How to use it: Age on 1 January 2030 will be 34 (34 years, 6 months, 17 days), date of birth 15 June 1995.
What the calculator does with bad input
How errors are reported rather than hidden.
A user leaves the date of birth blank, then types a birth date that is later than the reference date, then a year of 1850.
| Item | Value | Note |
|---|---|---|
| Blank date of birth | Blocked | An inline message asks for a date of birth |
| Date of birth after the reference date | Blocked | A negative age is a data error, never a result |
| Year before 1900 | Blocked | Outside the supported range, matching Excel's own limit |
| Non-existent date such as 31 February | Rejected by the date field | The browser control will not accept it |
| Reference date left blank | Blocked | An inline message asks for the age as of date |
| Result shown | Nothing | The result panel stays in its placeholder state |
| Download TXT button | Disabled | A file containing blanks is worse than no file |
| What you see instead | A message naming the fix | Never a bare NaN, a negative age or an empty box |
What it means: This matters more for age than for most calculations, because a wrong age looks completely plausible. An age of 126 from a blank spreadsheet cell is the classic example: nothing errors, nothing looks broken, and the number is nonsense. The calculator refuses rather than guessing.
How to use it: Enter a real date of birth on or after 1 January 1900, and make sure it falls before the age as of date.
🧪 13. How Do You Get Your Input Dates Right?
An age calculator has only two inputs, and both are read off a document. Almost every wrong age traces back to one of them being misread rather than to the arithmetic.
- Take the date of birth from a document, not from memory. Use the passport, birth certificate or official record. People routinely misremember a parent's or child's birth year by one.
- Check the date order before you type it. 03/04/1990 is 3 April in the UK, India and most of Europe, and 4 March in the United States. If the source is ambiguous, look for another date in the same document with a day above 12, which settles the order at once.
- Write it in ISO form as you go. Recording 1990-04-03 in your notes removes the ambiguity permanently and matches what every field on this page expects.
- Verify against the weekday. If the person knows they were born on a Saturday and the calculator says Wednesday, the year or the month is wrong. This one check catches more typos than any other.
- Decide which reference date the rule wants. Today, a scheme cutoff, the first day of a school year, or a policy start date are all different, and they give different ages.
- Handle 29 February deliberately. If the date of birth is a leap day, choose the observed date rule before you calculate, and record which one you used.
- Watch for spreadsheet text dates. A date that sits on the left of a cell is text, and the age formula will either error or silently skip it. Fix the column before you compute anything.
- Guard against blank rows. An empty cell reads as zero, which is 0 January 1900, and produces an age of about 126 with no error at all. This is the most dangerous failure in a sheet of ages, because nothing looks broken.
- Record the reference date beside every age. An age with no date attached is wrong within a year and unverifiable immediately.
- Sanity check the extremes. Sort a column of computed ages and look at the top and bottom. Anything under 0 or over about 115 is almost certainly a data error rather than a person.
| Input | Format | Valid range | Where it comes from |
|---|---|---|---|
| Date of birth | Calendar date | 1 January 1900 onwards | Passport, birth certificate, personnel or patient record |
| Age as of date | Calendar date | On or after the date of birth | Today, or the cutoff date named in the rule you are testing |
| Leap day rule | 1 March or 28 February | Only used for 29 February births | The scheme's own wording, or local convention |
| Featured unit | Days, weeks, months or hours | Display preference only | Whichever unit your context uses |
Dates are entered through the browser's own date control, which rejects impossible dates such as 31 February before the calculator ever sees them.
Common mistakes when gathering the inputs:
- Using today's date when the rule names a fixed cutoff.
- Copying a birth date from a spreadsheet cell that displayed a different format from the value it held.
- Typing a two digit year, so 65 becomes 2065 rather than 1965.
- Reading a birth year from a document that recorded age rather than date of birth.
- Assuming a leap day birthday is invalid and shifting it permanently to 1 March in the record itself.
- Storing an age instead of a date of birth, which goes stale the moment it is written down.
🎯 14. When Should You Use This Age Calculator?
Use this age calculator when:
- ✓ You need an exact age in years, months and days from a date of birth.
- ✓ You need the total days, weeks, months or hours someone has lived.
- ✓ You are checking an age against a threshold on a specific cutoff date.
- ✓ You need the weekday of a birth date, or a countdown to the next birthday.
- ✓ The date of birth is 29 February and you need it handled properly.
- ✓ You want the same calculation as an Excel formula or an R or Python script to run over a whole column.
Do not use it when:
- ✗ You need a legal determination of eligibility. Use the number here to prepare, then confirm against the rule that applies.
- ✗ You need East Asian age reckoning or any non-Gregorian calendar.
- ✗ Time of day matters, for example for twins born either side of midnight.
- ✗ You need gestational or corrected age for a premature infant, which is measured from the due date, not the birth date.
- ✗ You want a life expectancy estimate. That is a population statistic and says nothing about an individual.
- ✗ The date of birth is before 1900, which is outside the supported range.
Four worked situations where an age calculator earns its place:
Four worked situations:
- Filling in a form. Born 15 June 1995, on 30 August 2026: enter 31. Record the date the age was taken.
- A school entry cutoff. Set the age as of field to the cutoff date named in the policy, not to today, and read the years figure.
- A baby's clinic appointment. Use the months and days, or the total days. Years are meaningless below age two.
- Pension planning. Put the scheme's pension age into the milestone view and read the exact date, then confirm the current pension age with the scheme.
🔧 15. Troubleshooting and Common Errors
The age is exactly one year more than I expected
Cause: a year subtraction with no birthday check. Fix: the years figure must drop by one when the birthday has not yet happened in the reference year. This calculator applies that automatically. In Excel, use DATEDIF rather than YEAR(TODAY())-YEAR(A2), which is wrong for roughly half of all people at any given moment.
Another calculator gives a different number of months and days
Cause: a different borrow rule. Fix: nothing is broken. When the reference day of the month is earlier than the birth day, a month has to be borrowed, and tools differ on which month's length to use. The years figure will agree; the months and days can differ by a day or two. This tool borrows the month before the reference month, matching Excel and most official forms.
The total days does not match years times 365
Cause: leap days. Fix: nothing is wrong, and the gap is exactly the number of 29 Februarys you have lived through. Over 31 years that is 8 days; over 77 years it is 19. The stat cards report the leap day count so you can check the arithmetic yourself.
My 29 February birthday is not accepted
Cause: a leap day date typed for a common year. Fix: 29 February exists only in leap years, so 29 February 2003 is not a real date and the date field will reject it. Check the birth year is actually a leap year. If it is, the date will be accepted and the observed-date setting handles the birthday.
The Calculate button does nothing
Cause: a field failed validation. Fix: look for an orange message under one of the two date fields. The usual causes are an empty date of birth, an empty age as of date, a date of birth later than the reference date, or a birth year before 1900.
Excel returns #NUM! for the age
Cause: the arguments are the wrong way round. Fix: DATEDIF takes the earlier date first. =DATEDIF(TODAY(),A2,"Y") returns #NUM! because it is being asked for a negative age. Swap them to =DATEDIF(A2,TODAY(),"Y").
Excel returns #VALUE! for the age
Cause: the date of birth cell holds text. Fix: a real date right aligns in its cell on its own. If yours is left aligned, retype it, or wrap the formula as =DATEDIF(DATEVALUE(A2),TODAY(),"Y"). Text dates are the most common spreadsheet date fault by a wide margin.
A blank spreadsheet row shows an age of 126
Cause: an empty cell is read as zero, which Excel treats as 0 January 1900. Fix: guard the formula with =IF(A2="","",DATEDIF(A2,TODAY(),"Y")). This one is worth hunting down deliberately, because it produces a plausible looking number and no error at all.
Excel does not offer DATEDIF as I type it
Cause: Microsoft hides it from the function list. Fix: not a fault. Type the whole name and the arguments manually and it works in every version of Excel and in Google Sheets. It is documented only as a compatibility function carried over from Lotus 1-2-3.
The age changes every time I open the spreadsheet
Cause: the formula uses TODAY(), which recalculates. Fix: that is correct behaviour for a live age. If the age is part of a dated record rather than a live figure, copy the column and paste it as values once, and write the reference date in the header.
The age is a day out from a colleague's answer
Cause: almost always a time zone or a text date. Fix: a date parsed from a string in JavaScript or Python is read as UTC midnight, which is the previous day in the Americas. Build dates from year, month and day parts instead, which is what the R and Python scripts on this page do deliberately.
Which method does this calculator use?
Answer: completed years, then completed months, then leftover days, with the borrow taken from the month before the reference month. Leap years use the full 4, 100 and 400 rule. Total days are counted exactly, never estimated. A 29 February birthday defaults to being observed on 1 March in common years, and you can switch that to 28 February. The proleptic Gregorian calendar applies throughout.
⚖ 16. Assumptions and Limitations
Assumptions
- Age is counted from the day of birth, in completed years. If it fails, for example under a rule that attains an age on the day before the anniversary, every result is one day late.
- The Gregorian calendar applies throughout. If it fails, dates before 1583 shift by up to 13 days, which is why the tool starts at 1900.
- The month borrow is taken from the month before the reference month. If your rule borrows differently, the months and days can be one day out. The years are never affected.
- A 29 February birthday is observed on the date you selected. If it fails, the birthday countdown is one or two days out. The exact age is unaffected.
- Dates carry no time of day. If it fails, someone born at 23:50 and someone born at 00:10 the next morning are treated as a day apart when they are twenty minutes apart.
- The date of birth is correct. If it fails, everything downstream is wrong in a way no arithmetic can detect. The weekday check in Section 13 is the cheapest defence.
- A day is 24 hours. If it fails, the hours and minutes figures drift by an hour twice a year wherever daylight saving applies.
Limitations
- It makes no eligibility determination. Legal thresholds for adulthood, pensions, licences and school entry are set by law and vary by country and scheme. Confirm the rule with the official source.
- It uses the international age convention only. East Asian age reckoning, which counted a newborn as one year old, is not supported. South Korea moved to the international system in June 2023.
- It supports the Gregorian calendar only. For Hijri, Hebrew, Persian or Japanese imperial dates you need a calendar conversion tool first.
- It handles whole days only, with no time of day and no time zones.
- It does not compute gestational or corrected age for premature infants, which is measured from the due date rather than the birth date and is a different calculation.
- It says nothing about life expectancy. The position bar is a display scale from 0 to 100, not a prediction about anyone.
- Dates before 1 January 1900 are outside the supported range, matching the practical limit of spreadsheet date systems.
🏁 17. Conclusion
An age calculator looks like the simplest tool on any site, and it hides two traps that catch people constantly. The first is forgetting to check whether the birthday has happened yet this year, which makes roughly half the population a year too old. The second is dividing days by 365, which quietly overstates age by a day for every four years lived and turns a 77 year old into a 78 year old on a spreadsheet.
Both traps have the same cure: count completed periods rather than estimating them. Completed years, then completed months, then the days left over. That is what official forms mean by age, what Excel's DATEDIF computes, and what the scripts in Sections 9 and 10 reproduce exactly. It also explains why two calculators can hand you months and days a day apart while agreeing perfectly on the years, and why the years figure is the only part any rule actually tests.
Record the reference date alongside every age you write down. An age with no date attached is stale within a year and unverifiable immediately, which is why records should store a date of birth and compute the age on demand rather than storing the age itself. The same habit protects you when a threshold is tested on a fixed cutoff rather than on today.
For very young children, drop the years entirely. A twelve month old and a twenty three month old are both one year old and are completely different children, which is why growth charts, vaccination schedules and developmental milestones are all indexed on months. The calculator reports every unit precisely so you can pick the one your context needs rather than rounding away the signal.
Use the age calculator at the top of this page whenever you need an exact age, set the age as of field to a cutoff date when you are testing eligibility, and copy the Excel, R or Python version from Sections 8 to 10 when you need to run the same calculation down a whole column of birth dates.
❓ 18. Frequently Asked Questions
Q1. How do I calculate my age from my date of birth?
Subtract the birth year from the current year, then adjust down by one if your birthday has not happened yet this year. For the exact age, count whole years first, then whole months, then the leftover days. A person born on 15 June 1995 is 31 years, 2 months and 15 days old on 30 August 2026.
Q2. How do you calculate age in Excel?
Use DATEDIF. With the date of birth in A2, =DATEDIF(A2,TODAY(),"Y") gives whole years, "YM" gives the leftover months and "MD" gives the leftover days. Combine them with TEXT to get a full sentence. DATEDIF is hidden from Excel's function list but works in every version.
Q3. What is the formula for age in Excel?
The complete formula is =DATEDIF(A2,TODAY(),"Y")&" years, "&DATEDIF(A2,TODAY(),"YM")&" months, "&DATEDIF(A2,TODAY(),"MD")&" days". For years only, =DATEDIF(A2,TODAY(),"Y") is enough. Avoid =(TODAY()-A2)/365, which drifts by a day for every four years lived.
Q4. How many days old am I?
Subtract your date of birth from today's date. Someone born on 15 June 1995 has lived 11,399 days by 30 August 2026, which includes 8 leap days. This calculator counts real days rather than multiplying years by 365, so the number is exact.
Q5. How do I calculate age from a date of birth in Excel without DATEDIF?
Use =YEARFRAC(A2,TODAY()) and wrap it in INT to get whole years, or =INT((TODAY()-A2)/365.25) as a rough version. Both are approximations. YEARFRAC uses a day-count basis that can differ from a calendar age by a day around a birthday, so DATEDIF stays the accurate choice.
Q6. How is age calculated for a 29 February birthday?
The exact age in years, months and days is unaffected: someone born on 29 February 2004 is 22 years, 6 months and 1 day old on 30 August 2026. What varies is which day the birthday is observed in a common year. Most legal systems use 1 March, while many everyday uses pick 28 February.
Q7. How do I calculate age in Python?
Use dateutil.relativedelta: from dateutil.relativedelta import relativedelta; rd = relativedelta(date.today(), date(1995, 6, 15)) gives rd.years, rd.months and rd.days. Without dateutil, subtract the years and adjust with a borrow, which is what the script in section 10 does using only the standard library.
Q8. How do I calculate age in R?
Base R has no age function, so compare the date parts directly. The script in section 9 subtracts the years and then borrows a month or a year when the month and day have not yet been reached. The lubridate package offers interval(dob, today) %/% years(1) as a shortcut for whole years.
Q9. What is my age in months?
Multiply your whole years by 12 and add the leftover months. Someone aged 31 years and 2 months has lived 374 whole months. Age in months is the standard measure for babies and toddlers up to 24 months, and paediatric growth charts are plotted against it rather than against years.
Q10. Does age count from the day you were born or the day after?
From the day you were born. You are 0 years old on the day of birth and turn 1 on your first birthday, which is the convention in almost every country. English common law once treated a person as attaining an age on the day before the anniversary, and a few legal contexts still preserve that rule.
Q11. Why do age calculators give slightly different answers?
Because they use different month arithmetic. Some count whole months then leftover days from the birth day of the month, and some divide total days by an average month length of 30.44. The years figure almost always agrees. The months and days figures are where the methods diverge, usually by a day or two.
Q12. How do I work out my age on a future date?
Change the age at date field from today to the future date you care about. Someone born on 15 June 1995 will be 34 years, 6 months and 17 days old on 1 January 2030. This is how you check eligibility cutoffs, retirement dates and school entry thresholds in advance.
Q13. What weekday was I born on?
The calculator names it from your date of birth. 15 June 1995 was a Thursday. The weekday repeats on your birthday every 5, 6 or 11 years depending on where leap years fall, which is why your birthday does not simply move forward one day each year.
Q14. How many days until my next birthday?
The calculator counts forward from the age at date to your next anniversary. Someone born on 15 June has 289 days to wait on 30 August 2026, and that birthday falls on a Tuesday. If today is your birthday the countdown reads zero rather than jumping to next year.
Q15. Is age calculated the same way in every country?
No. The international convention counts completed years from the date of birth, but East Asian age reckoning historically counted a newborn as one year old and added a year at new year. South Korea moved to the international system in June 2023. This tool uses the international convention only.
Q16. How do I calculate the age difference between two people?
Run the calculator twice, once for each date of birth on the same age at date, then subtract the two results. Or enter the older person's date of birth as the date of birth and the younger person's as the age at date, which returns the gap directly in years, months and days.
Q17. Why is dividing days by 365 wrong for age?
Because roughly one year in four has 366 days. Dividing by 365 overstates age by about one day for every four years lived, so a 60 year old comes out about 15 days too old. Dividing by 365.25 is closer but still drifts around leap years and near birthdays.
Q18. Can I calculate the age of something other than a person?
Yes. The arithmetic is the same for a building, a company, a vehicle, an account or a specimen. Enter the start date as the date of birth. Anything measured from a fixed start date to a chosen later date works, as long as both are real calendar dates.
Q19. Does the calculator store my date of birth?
No. Everything runs in your browser and nothing is sent anywhere or saved. Closing the page discards the date entirely. That matters because a date of birth is personal data in most privacy regimes, so a calculator has no business transmitting one.
Q20. Is this age calculator free?
Yes, it is completely free with no sign up and no limits. You can export your result as a plain text file or a printable PDF, and the Excel, R and Python sections let you repeat the same calculation over a whole spreadsheet of birth dates.
📑 19. Cite This Tool
StatsUnlock. (2026). Age calculator [Interactive date tool]. https://statsunlock.com/age-calculator/@misc{statsunlock_age_2026, title={Age Calculator}, author={{StatsUnlock}}, year={2026}, note={Interactive date tool}, url={https://statsunlock.com/age-calculator/}}Ages were computed using the StatsUnlock Age Calculator (2026). Age is reported as completed years, then completed calendar months, then the residual days, with the month borrow taken from the month preceding the index date. Total days were counted exactly from the proleptic Gregorian calendar, including all intervening leap days, rather than estimated from an assumed year length. Where a date of birth fell on 29 February, the birthday was treated as observed on 1 March in common years. All ages are stated with the index date on which they were computed.🔗 20. Related Tools
Why an age in weeks never divides cleanly by 52, and how the extra day each year builds up over a lifetime.
Open the tool →Every everyday calculator and converter on StatsUnlock, including the date and time set this page belongs to.
Browse the category →Average age of a group, class or sample, with seven kinds of average and a recommendation on which to report.
Open the tool →The middle age of a group. More honest than the mean when a few much older or younger people skew the spread.
Open the tool →Describe a whole age distribution at once with quartiles, minimum, maximum and a box plot.
Open the tool →Where one age sits inside a group, the same idea behind height and weight percentile charts for children.
Open the tool →📖 21. Glossary of Terms
| Term | Plain-English meaning |
|---|---|
| Age next birthday | Your completed years plus one. Used by some insurers instead of your current age. |
| Anniversary | The same day and month in a later year. Your birthday is the anniversary of your birth. |
| Borrow | Taking days from the previous month when the day of the month has not yet been reached. The step where age calculators disagree. |
| Chronological age | Age measured in calendar time from the date of birth. What this calculator gives. |
| Completed years | Whole years finished since birth. You are 31 until the day before your 32nd birthday. |
| Corrected age | Age of a premature infant measured from the due date rather than the birth date. Not computed here. |
| Cutoff date | The fixed date a rule tests an age against, such as a school entry date. Often not today. |
| DATEDIF | The Excel function that returns a true calendar age. It works in every version but is hidden from the function list. |
| Date of birth | The calendar day a person was born. Records should store this rather than an age, which goes stale. |
| Decimal age | Total days divided by 365.2425. Useful in statistical models, never correct on a form. |
| East Asian age reckoning | A traditional system counting a newborn as one year old. South Korea moved off it in June 2023. |
| Gestational age | Age measured from the start of a pregnancy rather than from birth. A different calculation entirely. |
| Gregorian calendar | The calendar in everyday worldwide use, introduced in 1582 and adopted at different times by different countries. |
| Index date | The date an age was computed on. An age without one cannot be checked. |
| ISO 8601 | The international date standard, which writes dates as YYYY-MM-DD and removes day and month ambiguity. |
| Leap day | 29 February, which exists only in leap years. Roughly one year in four has one. |
| Leap year | A 366 day year. It divides by 4, unless it is a century year, which must also divide by 400. |
| Milestone age | An age that carries a legal or practical consequence, such as 18, 21, 65 or 67. |
| Observed birthday | The day a 29 February birthday is marked in a common year, either 1 March or 28 February. |
| Proleptic calendar | A calendar rule applied to dates before it was introduced, so software handles old dates consistently. |
| Reference date | The date the age is measured on. Today by default, or any date you choose. |
| Serial number | The whole number a spreadsheet uses to store a date. Excel counts days from 1 January 1900. |
| Total days lived | The exact count of calendar days between birth and the reference date, leap days included. |
| YEARFRAC | An Excel function returning a decimal year fraction on a chosen day-count basis. Not a calendar age. |
📚 22. References
Twenty peer-reviewed journal articles on calendars, date representation, age measurement and date handling in software and research data. Standards documents and official age thresholds are named in Section 11 rather than here.
- Dershowitz, N., & Reingold, E. M. (1990). Calendrical calculations. Software: Practice and Experience, 20(9), 899-928. https://doi.org/10.1002/spe.4380200905
- Reingold, E. M., Dershowitz, N., & Clamen, S. M. (1993). Calendrical calculations, II: Three historical calendars. Software: Practice and Experience, 23(4), 383-404. https://doi.org/10.1002/spe.4380230404
- Fliegel, H. F., & Van Flandern, T. C. (1968). A machine algorithm for processing calendar dates. Communications of the ACM, 11(10), 657. https://doi.org/10.1145/364096.364097
- Richards, E. G. (2013). Calendars and their reform. Astronomy & Geophysics, 54(3), 3.28-3.30. https://doi.org/10.1093/astrogeo/att088
- Allen, J. F. (1983). Maintaining knowledge about temporal intervals. Communications of the ACM, 26(11), 832-843. https://doi.org/10.1145/182.358434
- Bettini, C., Jajodia, S., & Wang, X. S. (1998). A general framework for time granularity and its application to temporal reasoning. Annals of Mathematics and Artificial Intelligence, 22(1), 29-58. https://doi.org/10.1023/A:1018938900494
- Dyreson, C. E., Evans, W. S., Lin, H., & Snodgrass, R. T. (2000). Efficiently supporting temporal granularities. IEEE Transactions on Knowledge and Data Engineering, 12(4), 568-587. https://doi.org/10.1109/69.868908
- Snodgrass, R. T., & Ahn, I. (1986). Temporal databases. Computer, 19(9), 35-42. https://doi.org/10.1109/MC.1986.1663327
- Jensen, C. S., & Snodgrass, R. T. (1999). Temporal data management. IEEE Transactions on Knowledge and Data Engineering, 11(1), 36-44. https://doi.org/10.1109/69.755613
- Ohlbach, H. J., & Gabbay, D. (1998). Calendar logic. Journal of Applied Non-Classical Logics, 8(4), 291-324. https://doi.org/10.1080/11663081.1998.10510949
- Wang, X. S., Bettini, C., Brodsky, A., & Jajodia, S. (1997). Logical design for temporal databases with multiple granularities. ACM Transactions on Database Systems, 22(2), 115-170. https://doi.org/10.1145/249978.249979
- Combi, C., Franceschet, M., & Peron, A. (2004). Representing and reasoning about temporal granularities. Journal of Logic and Computation, 14(1), 51-77. https://doi.org/10.1093/logcom/14.1.51
- Goralwalla, I. A., Leontiev, Y., Ozsu, M. T., Szafron, D., & Combi, C. (2001). Temporal granularity: Completing the puzzle. Journal of Intelligent Information Systems, 16(1), 41-63. https://doi.org/10.1023/A:1008737019055
- Terenziani, P., & Snodgrass, R. T. (2004). Reconciling point-based and interval-based semantics in temporal relational databases. IEEE Transactions on Knowledge and Data Engineering, 16(5), 540-551. https://doi.org/10.1109/TKDE.2004.1277816
- Strotgen, J., & Gertz, M. (2013). Multilingual and cross-domain temporal tagging. Language Resources and Evaluation, 47(2), 269-298. https://doi.org/10.1007/s10579-012-9179-y
- Verhagen, M., Sauri, R., Caselli, T., & Pustejovsky, J. (2013). Temporal expression recognition and normalization. Language Resources and Evaluation, 47(1), 123-152. https://doi.org/10.1007/s10579-012-9198-8
- Kuh, D., Ben-Shlomo, Y., Lynch, J., Hallqvist, J., & Power, C. (2003). Life course epidemiology. Journal of Epidemiology and Community Health, 57(10), 778-783. https://doi.org/10.1136/jech.57.10.778
- Kramer, M. S., Platt, R. W., Wen, S. W., Joseph, K. S., Allen, A., Abrahamowicz, M., Blondel, B., & Breart, G. (2001). A new and improved population-based Canadian reference for birth weight for gestational age. Pediatrics, 108(2), e35. https://doi.org/10.1542/peds.108.2.e35
- de Onis, M., Onyango, A. W., Borghi, E., Siyam, A., Nishida, C., & Siekmann, J. (2007). Development of a WHO growth reference for school-aged children and adolescents. Bulletin of the World Health Organization, 85(9), 660-667. https://doi.org/10.2471/BLT.07.043497
- Sperrin, M., Marshall, A. D., Higgins, V., Renehan, A. G., & Buchan, I. E. (2016). Body mass index relates weight to height differently in women and older adults. Journal of Public Health, 38(3), 607-610. https://doi.org/10.1093/pubmed/fdv067
