fix: consider months and days in years_old (#11234)

* fix: do not consider months in `calculate_age`

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update get_top_billionaires.py

* Update get_top_billionaires.py

* Update get_top_billionaires.py

* TODAY = datetime.utcnow()

* Update get_top_billionaires.py

* Update build.yml

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Christian Clauss <cclauss@me.com>
This commit is contained in:
Piotr Idzik 2024-01-12 17:12:15 +01:00 committed by GitHub
parent 9caf4784aa
commit 227944eb29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 36 deletions

View File

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-python@v4 - uses: actions/setup-python@v5
with: with:
python-version: 3.12 python-version: 3.12
allow-prereleases: true allow-prereleases: true

View File

@ -3,7 +3,7 @@ CAUTION: You may get a json.decoding error.
This works for some of us but fails for others. This works for some of us but fails for others.
""" """
from datetime import UTC, datetime, timedelta from datetime import UTC, date, datetime
import requests import requests
from rich import box from rich import box
@ -11,8 +11,7 @@ from rich import console as rich_console
from rich import table as rich_table from rich import table as rich_table
LIMIT = 10 LIMIT = 10
TODAY = datetime.now() TODAY = datetime.now(tz=UTC)
API_URL = ( API_URL = (
"https://www.forbes.com/forbesapi/person/rtb/0/position/true.json" "https://www.forbes.com/forbesapi/person/rtb/0/position/true.json"
"?fields=personName,gender,source,countryOfCitizenship,birthDate,finalWorth" "?fields=personName,gender,source,countryOfCitizenship,birthDate,finalWorth"
@ -20,40 +19,40 @@ API_URL = (
) )
def calculate_age(unix_date: float) -> str: def years_old(birth_timestamp: int, today: date | None = None) -> int:
"""Calculates age from given unix time format. """
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: Returns:
Age as string int: The age in years.
>>> from datetime import datetime, UTC Examples:
>>> years_since_create = datetime.now(tz=UTC).year - 2022 >>> today = date(2024, 1, 12)
>>> int(calculate_age(-657244800000)) - years_since_create >>> years_old(birth_timestamp=datetime(1959, 11, 20).timestamp(), today=today)
73 64
>>> int(calculate_age(46915200000)) - years_since_create >>> years_old(birth_timestamp=datetime(1970, 2, 13).timestamp(), today=today)
51 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 today = today or TODAY.date()
unix_date /= 1000 birth_date = datetime.fromtimestamp(birth_timestamp, tz=UTC).date()
return (today.year - birth_date.year) - (
if unix_date < 0: (today.month, today.day) < (birth_date.month, birth_date.day)
# 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))
) )
def get_forbes_real_time_billionaires() -> list[dict[str, str]]: def get_forbes_real_time_billionaires() -> list[dict[str, int | str]]:
"""Get top 10 realtime billionaires using forbes API. """
Get the top 10 real-time billionaires using Forbes API.
Returns: Returns:
List of top 10 realtime billionaires data. List of top 10 realtime billionaires data.
@ -66,21 +65,22 @@ def get_forbes_real_time_billionaires() -> list[dict[str, str]]:
"Country": person["countryOfCitizenship"], "Country": person["countryOfCitizenship"],
"Gender": person["gender"], "Gender": person["gender"],
"Worth ($)": f"{person['finalWorth'] / 1000:.1f} Billion", "Worth ($)": f"{person['finalWorth'] / 1000:.1f} Billion",
"Age": calculate_age(person["birthDate"]), "Age": years_old(person["birthDate"]),
} }
for person in response_json["personList"]["personsLists"] for person in response_json["personList"]["personsLists"]
] ]
def display_billionaires(forbes_billionaires: list[dict[str, str]]) -> None: def display_billionaires(forbes_billionaires: list[dict[str, int | str]]) -> None:
"""Display Forbes real time billionaires in a rich table. """
Display Forbes real-time billionaires in a rich table.
Args: Args:
forbes_billionaires (list): Forbes top 10 real time billionaires forbes_billionaires (list): Forbes top 10 real-time billionaires
""" """
table = rich_table.Table( 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", style="green",
highlight=True, highlight=True,
box=box.SQUARE, box=box.SQUARE,