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:"))
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.
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:"))
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.