diff --git a/__main__.py b/__main__.py index 53c2c43..003737c 100644 --- a/__main__.py +++ b/__main__.py @@ -1,5 +1,26 @@ def main() -> None: - print("Hello world") + """Fonction Main""" + date_input_by_user = str(input("Saisir une date au format YYYY-MM-DD:")) + input_is_date(date_input_by_user) +def input_is_date(date_result: str) -> bool: + + if len(date_result) != 10: + print("Input date is not valid") + return False + + years = int(date_result[:4]) + month = int(date_result[5:7]) + days = int(date_result[8:]) + + try: + if years <= 1583 or month > 12 or days > 31: + print("Valeur fausse") + return False + + return True + except ValueError: + print("Error car le format de la date n'est pas bon " + date_result) + return False main() diff --git a/doomsday/algorithm.py b/doomsday/algorithm.py index cf81d60..20c55f9 100644 --- a/doomsday/algorithm.py +++ b/doomsday/algorithm.py @@ -1,2 +1,116 @@ +from doomsday.date import is_valid_date, WEEK_DAYS, is_leap_year + + +def is_even(number: int) -> bool: + """Returns true if the number is even + """ + return number % 2 == 0 + + +def get_higher_multiple_of_7(number: int) -> int: + """Returns the closest multiple of 7 above a given number + """ + return (number // 7) + 1 + + +def get_century_index(century: int) -> int: + """Returns the index of a given century + """ + number_of_the_century = (century // 100) % 4 + if number_of_the_century == 0: + return 2 + elif number_of_the_century == 1: + return 0 + elif number_of_the_century == 2: + return 5 + else: + return 3 + + +def get_week_anchor_day_of_year(year: str) -> int: + """Returns the number of the week day corresponding to the anchor day from + a given year + """ + year_2_last_digits: int = int(year[2:]) + + if not is_even(year_2_last_digits): + year_2_last_digits += 11 + + year_2_last_digits //= 3 + + if not is_even(year_2_last_digits): + year_2_last_digits += 11 + + # Convert to integer after calculations + year_2_last_digits = int(year_2_last_digits) + + number_to_multiple_of_7: int = (get_higher_multiple_of_7( + year_2_last_digits) * 7) - year_2_last_digits + + number_to_multiple_of_7 += get_century_index(int(year) - + year_2_last_digits) + + # Get the day between 0 and 6 + number_to_multiple_of_7 %= 7 + + return int(number_to_multiple_of_7) + + +def get_anchor_day_of_the_month(month: int, year: int) -> int: + """Returns the anchor day of a given month number + """ + # April, June, August, October and December + if month == 4 or month == 6 or month == 8 or month == 10 or month == 12: + return month + + # January and February + if month == 1 or month == 2: + if is_leap_year(year): + return 11 if month == 1 else 22 + else: + return 10 if month == 1 else 21 + + # March, May, July, September, November + if month == 3: + return 0 + elif month == 5: + return 9 + elif month == 7: + return 11 + elif month == 9: + return 5 + else: + return 7 + + +def get_week_day(day_in_month: int, anchor_day: int, + week_doomsday: int) -> str: + """Returns the week day of a day in a month using the week day of the + anchor day + """ + return WEEK_DAYS[(week_doomsday + (day_in_month - anchor_day)) % 7] + + def get_weekday_for_date(date: str) -> str: - return "Sunday" + """Returns the week day of a given date + """ + if not is_valid_date(date): + return "The date is not valid." + + year: str = date[:4] + # We check if the 7th character of the date is a number or a separator + # because the month can have one or two digits + if date[6].isnumeric(): + month: int = int(date[5:7]) + day: int = int(date[8:]) + else: + month: int = int(date[5]) + day: int = int(date[7:]) + + # The week day of the anchor day of the year + anchor_week_day: int = get_week_anchor_day_of_year(year) + + # The number of the anchor day of the month + anchor_day: int = get_anchor_day_of_the_month(month, int(year)) + + return get_week_day(day, anchor_day, anchor_week_day) diff --git a/doomsday/date.py b/doomsday/date.py index 0f8e737..355ba66 100644 --- a/doomsday/date.py +++ b/doomsday/date.py @@ -1,2 +1,144 @@ +MONTHS: list[str] = ["January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", + "December"] +WEEK_DAYS: list[str] = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday"] + + +def is_valid_year(year: str) -> bool: + """Checks if the year is a valid number and greater than 1583 + """ + + if not year.isnumeric(): + print("Error: the year must be a number of 4 digits") + return False + + if not int(year) >= 1583: + print("Error: the year must be greater than 1583") + return False + + return True + + +def is_valid_separator(separator: str) -> bool: + """Returns true if the date separator is - + """ + + if separator != '-': + print("Error: the date separator must be -") + return False + + return True + + +def is_valid_month(month: str) -> bool: + """Checks if the month is a valid number and between 1 and 12 + """ + + if not month.isnumeric(): + print("Error: the month must be a number of 1 or 2 digits") + return False + + if not 1 <= int(month) <= 12: + print("Error: the month must between 1 and 12") + return False + + return True + + +def is_valid_day(day: str, month: str, year: str) -> bool: + """Checks if the day is a valid number and between 1 and the last day of + the month + """ + + if not day.isnumeric(): + print("Error: the day must be a number of 1 or 2 digits") + return False + + if not 1 <= int(day): + print("Error: the day must greater than 0") + return False + + if not is_valid_day_in_month(int(day), int(month), int(year)): + return False + + return True + + +def is_leap_year(year: int) -> bool: + """Returns true if the year is a leap year + """ + return year % 4 == 0 and (not year % 100 == 0 or year % 400 == 0) + + +def is_valid_day_in_month(day: int, month: int, year: int) -> bool: + """Returns true if the day exists in its month + """ + + # Month with 30 days + if month == 4 or month == 6 or month == 9 or month == 11: + if not day <= 30: + print("Error: the date is not valid, there are 30 days in", + MONTHS[month - 1]) + return False + + # Month with 31 days + if (month == 1 or month == 3 or month == 5 or month == 7 or month == 8 or + month == 10 or month == 12): + if not day <= 31: + print("Error: the date is not valid, there are 31 days in", + MONTHS[month - 1]) + return False + + # February + if is_leap_year(year): + if month == 2 and not day <= 29: + print("Error: the date is not valid, there are 29 days in " + "February this year") + return False + else: + if month == 2 and not day <= 28: + print("Error: the date is not valid, there are 28 days in " + "February this year") + return False + + return True + + def is_valid_date(date: str) -> bool: + """Returns true if the date is valid + """ + + # The year is necessarily the first four characters of the date + if not is_valid_year(date[:4]): + return False + + year: str = date[:4] + + if not is_valid_separator(date[4]): + return False + + # We check if the 7th character of the date is a number or a separator + # because the month can have one or two digits + if date[6].isnumeric(): + # The month has two digits + if not is_valid_month(date[5:7]): + return False + + if not is_valid_separator(date[7]): + return False + + if not is_valid_day(date[8:], date[5:7], year): + return False + else: + # The month has only one digit + if not is_valid_month(date[5]): + return False + + if not is_valid_separator(date[6]): + return False + + if not is_valid_day(date[7:], date[5], year): + return False + return True