Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: consider months and days in years_old #11234

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: 3.12
allow-prereleases: true
Expand Down
72 changes: 36 additions & 36 deletions web_programming/get_top_billionaires.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,56 @@
This works for some of us but fails for others.
"""

from datetime import UTC, datetime, timedelta
from datetime import UTC, date, datetime

import requests
from rich import box
from rich import console as rich_console
from rich import table as rich_table

LIMIT = 10
TODAY = datetime.now()

TODAY = datetime.now(tz=UTC)
API_URL = (
"https://www.forbes.com/forbesapi/person/rtb/0/position/true.json"
"?fields=personName,gender,source,countryOfCitizenship,birthDate,finalWorth"
f"&limit={LIMIT}"
)


def calculate_age(unix_date: float) -> str:
"""Calculates age from given unix time format.
def years_old(birth_timestamp: int, today: date | None = None) -> int:
"""
Calculate the age in years based on the given birth date. Only the year, month,
and day are used in the calculation. The time of day is ignored.

Args:
birth_timestamp: The date of birth.
today: (useful for writing tests) or if None then datetime.date.today().

Returns:
Age as string

>>> from datetime import datetime, UTC
>>> years_since_create = datetime.now(tz=UTC).year - 2022
>>> int(calculate_age(-657244800000)) - years_since_create
73
>>> int(calculate_age(46915200000)) - years_since_create
51
int: The age in years.

Examples:
>>> today = date(2024, 1, 12)
>>> years_old(birth_timestamp=datetime(1959, 11, 20).timestamp(), today=today)
64
>>> years_old(birth_timestamp=datetime(1970, 2, 13).timestamp(), today=today)
53
>>> all(
... years_old(datetime(today.year - i, 1, 12).timestamp(), today=today) == i
... for i in range(1, 111)
... )
True
"""
# Convert date from milliseconds to seconds
unix_date /= 1000

if unix_date < 0:
# Handle timestamp before epoch
epoch = datetime.fromtimestamp(0, tz=UTC)
seconds_since_epoch = (datetime.now(tz=UTC) - epoch).seconds
birthdate = (
epoch - timedelta(seconds=abs(unix_date) - seconds_since_epoch)
).date()
else:
birthdate = datetime.fromtimestamp(unix_date, tz=UTC).date()
return str(
TODAY.year
- birthdate.year
- ((TODAY.month, TODAY.day) < (birthdate.month, birthdate.day))
today = today or TODAY.date()
birth_date = datetime.fromtimestamp(birth_timestamp, tz=UTC).date()
return (today.year - birth_date.year) - (
(today.month, today.day) < (birth_date.month, birth_date.day)
)


def get_forbes_real_time_billionaires() -> list[dict[str, str]]:
"""Get top 10 realtime billionaires using forbes API.
def get_forbes_real_time_billionaires() -> list[dict[str, int | str]]:
"""
Get the top 10 real-time billionaires using Forbes API.

Returns:
List of top 10 realtime billionaires data.
Expand All @@ -66,21 +65,22 @@ def get_forbes_real_time_billionaires() -> list[dict[str, str]]:
"Country": person["countryOfCitizenship"],
"Gender": person["gender"],
"Worth ($)": f"{person['finalWorth'] / 1000:.1f} Billion",
"Age": calculate_age(person["birthDate"]),
"Age": years_old(person["birthDate"]),
}
for person in response_json["personList"]["personsLists"]
]


def display_billionaires(forbes_billionaires: list[dict[str, str]]) -> None:
"""Display Forbes real time billionaires in a rich table.
def display_billionaires(forbes_billionaires: list[dict[str, int | str]]) -> None:
"""
Display Forbes real-time billionaires in a rich table.

Args:
forbes_billionaires (list): Forbes top 10 real time billionaires
forbes_billionaires (list): Forbes top 10 real-time billionaires
"""

table = rich_table.Table(
title=f"Forbes Top {LIMIT} Real Time Billionaires at {TODAY:%Y-%m-%d %H:%M}",
title=f"Forbes Top {LIMIT} Real-Time Billionaires at {TODAY:%Y-%m-%d %H:%M}",
style="green",
highlight=True,
box=box.SQUARE,
Expand Down