Skip to content

Conversation

Ommodi07
Copy link

@Ommodi07 Ommodi07 commented Oct 16, 2025

Describe your change:

Added an algorithm to calculate absolute age difference between two people.
Includes input validation and doctests.
Fixes #13489

  • Add an algorithm?
  • Fix a bug or typo in an existing algorithm?
  • Add or change doctests? -- Note: Please avoid changing both code and tests in a single pull request.
  • Documentation change?

Checklist:

  • I have read CONTRIBUTING.md.
  • This pull request is all my own work -- I have not plagiarized.
  • I know that pull requests will not be merged if they fail the automated tests.
  • This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.
  • All new Python files are placed inside an existing directory.
  • All filenames are in all lowercase characters with no spaces or dashes.
  • All functions and variable names follow Python naming conventions.
  • All function parameters and return values are annotated with Python type hints.
  • All functions have doctests that pass the automated testing.
  • All new algorithms include at least one URL that points to Wikipedia or another similar explanation.
  • If this pull request resolves one or more open issues then the description above includes the issue number(s) with a closing keyword: "Fixes Python #13489 ".

@algorithms-keeper algorithms-keeper bot added the awaiting reviews This PR is ready to be reviewed label Oct 16, 2025
@ankit-nirala54
Copy link

#!/usr/bin/env python3
"""
age_diff.py

Calculate the absolute age difference between two people given their birthdates.

Functions:

  • parse_date(value): parse and validate a date string (YYYY-MM-DD) or accept datetime.date.
  • absolute_age_difference(d1, d2): return (years, months, days) difference, absolute value.

Run doctests:
python -m doctest age_diff.py -v
"""

from datetime import date, datetime, timedelta
from typing import Tuple, Union

DateLike = Union[str, date, datetime]

def parse_date(value: DateLike) -> date:
"""
Parse a date-like input into a datetime.date and validate it's not in the future.

Accepts:
  - 'YYYY-MM-DD' string
  - datetime.date
  - datetime.datetime

Raises:
  ValueError on invalid format or if the date is in the future.

Examples
--------
>>> parse_date("2000-01-15")
datetime.date(2000, 1, 15)
>>> # invalid format
>>> try:
...     parse_date("15-01-2000")
... except ValueError as e:
...     print("err")
err
"""
if isinstance(value, date) and not isinstance(value, datetime):
    d = value
elif isinstance(value, datetime):
    d = value.date()
elif isinstance(value, str):
    try:
        d = datetime.strptime(value, "%Y-%m-%d").date()
    except ValueError as exc:
        raise ValueError(f"Date string must be YYYY-MM-DD, got: {value!r}") from exc
else:
    raise ValueError(f"Unsupported date type: {type(value)}")

today = date.today()
if d > today:
    raise ValueError(f"Date {d.isoformat()} is in the future (today is {today.isoformat()}).")
return d

def _days_in_prev_month(ref: date) -> int:
"""
Helper: number of days in the month preceding the month of ref.
For example, if ref is 2020-03-05 -> returns days in Feb 2020 (29).
"""
first_of_month = ref.replace(day=1)
prev_last_day = first_of_month - timedelta(days=1)
return prev_last_day.day

def absolute_age_difference(d1: DateLike, d2: DateLike) -> Tuple[int, int, int]:
"""
Return the absolute difference between two dates as (years, months, days).

Rules:
  - years is the number of full years between the two dates
  - months is full months after removing years
  - days is remaining days after removing years and months

Examples
--------
Same day -> zero difference:
>>> absolute_age_difference("2000-01-01", "2000-01-01")
(0, 0, 0)

Simple difference:
>>> absolute_age_difference("1990-05-10", "1995-07-15")
(5, 2, 5)

Order doesn't matter (it's absolute):
>>> absolute_age_difference("1995-07-15", "1990-05-10")
(5, 2, 5)

Leap day handling (Feb 29):
>>> absolute_age_difference("2000-02-29", "2001-02-28")
(0, 11, 30)

Another leap example across many years:
>>> absolute_age_difference("1988-02-29", "2012-02-29")
(24, 0, 0)
"""
a = parse_date(d1)
b = parse_date(d2)

# Ensure a <= b
if a > b:
    a, b = b, a

# Start with year difference
years = b.year - a.year

# Adjust years if the last year is not yet a full year
if (b.month, b.day) < (a.month, a.day):
    years -= 1

# For months and days, compute an "anniversary" date after removing full years
# anniversary = a advanced by `year

@Ommodi07
Copy link
Author

Ommodi07 commented Oct 19, 2025 via email

@Ommodi07 Ommodi07 closed this Oct 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting reviews This PR is ready to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python

2 participants