How do you make a range exclusive to a certain condition?

Question:

I want to have users input a date and use their previously chosen month to make sure they enter a valid date that’s within that month, but the else clause for my first month bleeds out to february (I’m assuming because the wrong answers are inclusive within Jan’s range). Is there a way to fix this? Or would I have to make a list for each month’s day?

    month = ["january", "february", "march", "april", "may", "june", "july","august", "september", "october", "november", "december"] 

mes = (input("input a month in full: "))
while mes not in month:
  print()
  mes = (input("mm please input a month in full: "))
  print()
else:
    print()
    print("*.+ " + mes + " +.*")
    print()

mesD=int(input("input a date:"))
while mesD:
  while mes<="january":
    if 0 < mesD <= 31:
      print()
      print("*.+ " + mes +' '+ str(mesD) + " +.*")
      print()
      break
    else:
      print()
      print("there are only 31 days in january silly!")
      print()
      mesD=int(input("input a date:"))
  while mes<="february":
      if 0 < mesD <= 28:
        print()
        print("*.+ " + mes +' '+ str(mesD) + " +.*")
        print()
        break
      else:
        print()
        print("there are only 28 days in february silly!")
        print()
        mesD=int(input("input a date:"))
  
Asked By: Vanessa Nguyen

||

Answers:

For a very simple script/use case, you could use a dictionary to store month names mapped to the number of days in those months. Then you won’t have to check each month individually in code. Here is an example:

MONTHS = {
    "january": 31,
    "february": 28,
    "march": 31,
    "april": 30,
    # and so on...
}


def main() -> None:
    while True:
        month = input("please input a month in full: ").lower()
        if month in MONTHS:
            break
        print("not a valid month")
    max_days = MONTHS[month]
    while True:
        day = int(input(f"input a day of {month}: "))
        if day < 1:
            print("very funny...")
            continue
        if day > max_days:
            print(f"{month} has only {max_days} days")
            continue
        break
    print(f"*.+ {month} {day} +.*")


if __name__ == '__main__':
    main()

Execution example:

please input a month in full: foo
not a valid month
please input a month in full: april
input a day of april: -1
very funny...
input a day of april: 31
april has only 30 days
input a day of april: 20
*.+ april 20 +.*

But for anything remotely serious, you should probably use specialized modules that take care of things like the correct number of days in leap years and so on, as mentioned by Thierry. Python’s standard library has the calendar module for example.

PS:

You can make use of the calendar.monthrange function, which takes a year and month (as a number) and returns a 2-tuple, with the second element being the number of days in that month. In the MONTHS dictionary we now just keep the number of that month:

from calendar import monthrange


MONTHS = {
    "january": 1,
    "february": 2,
    "march": 3,
    "april": 4,
    # and so on...
}
YEAR = 2022


def main() -> None:
    while True:
        month = input("please input a month in full: ").lower()
        if month in MONTHS:
            break
        print("not a valid month")
    month_number = MONTHS[month]
    max_days = monthrange(YEAR, month_number)[1]
    while True:
        day = int(input(f"input a day of {month}: "))
        if day < 1:
            print("very funny...")
            continue
        if day > max_days:
            print(f"{month} has only {max_days} days")
            continue
        break
    print(f"*.+ {month} {day} +.*")


if __name__ == '__main__':
    main()

Output works the same way.

Answered By: Daniil Fajnberg
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.