I am not using any datetime module. I created my own functions to calculate the day, month, and year. I want to calculate the refunds based on the date. If the date is invalid, it should ask the user to try again until a date is true.
year = 0
month = 0
day = 0
money_owed = 0
def if_leap_year(year):
if (year % 400 == 0): return 366
elif (year % 100 == 0): return 365
elif (year % 4 == 0): return 366
else:
return 365
#print(if_leap_year(year))
def days_in_month(month, year):
if month in {1, 3, 5, 7, 8, 10, 12}:
return 31
if month == 2:
if if_leap_year(year):
return 29
return 28
return 30
#print(days_in_month(month, year))
def is_valid_date(year, month, day):
if days_in_month(month, year)<day:#checks if the given day is possible
given the month
return False
else:
return True
def days_left_in_year(month, day, year):
daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31]
daysLeft = (if_leap_year(year) if month < 3 else 365) -
sum(daysInMonth[:month - 1]) - day
return daysLeft
def refund_period():
month = int(input("Enter the month of the year: "))
day = int(input("Enter the day of the year: "))
year = int(input("Enter the year to determine the number of days: "))
if is_valid_date(year , month , day):
money_owed = (days_left_in_year(month, day, year) /
if_leap_year(year)) * 278
return round(money_owed, 2)
else:
print("Your date is invalid, try again.")
while is_valid_date(year, month, day):
print('you will be refunded','$', + refund_period())
break
else:
print("Your date is invalid, try again.")
I am getting:
you will be refunded $ -8.38
even though the calculation shouldn't be performed since the date is invalid
You are setting year =0 , month =0, day = 0 in first loop.
Also the while is not clear. All your functions return an int so never validate if the date is correct.
Maybe you can create a function to validate the date something like this :
def is_valid_date(year , month , day):
if month <1 or month >12: #Validate a allowed month
return False
if day <1 or day > days_in_month(month, year): # validate an allowed day for the month
return False
return True
and you can change this function :
def refund_period():
month = int(input("Enter the month of the year: "))
day = int(input("Enter the day of the year: "))
year = int(input("Enter the year to determine the number of days: "))
if is_valid_date(year , month , day):
money_owed = (days_left_in_year(month, day, year) / if_leap_year(year)) * 278
return round(money_owed, 2)
else :
print("Your date is invalid, try again.")
Just a couple of comments:
You are getting the year, month, and day using input() so you don't need to create global variables for that.
you don't need to ask if if_leap_year(year) == 365 or 366 because this function returns 365 or 366 so you can use it directly when you calculate the money_owned, as I do.
Also you can use if_leap_year(year) instead
(if_leap_year(year) if month < 3 else 365) . That functions return 366 or 365, you dont need to validate again.
And you can use list comprehension for you daysInMonth variable inside days_left_in_year function :
daysInMonth = [days_in_month(m, year) for m in range(1,13)]
Your while loop is not comparing the function value but just checking if the object exists. Instead of conditions like while days_left_in_year(month, day, year), use conditions like while days_left_in_year(month, day, year)<30 (assuming you wanted to deny refunds on orders older than 30 days.
To validate dates, add the following function under your comment #print(days_in_month(month, year)):
def is_valid_date(year, month, day)
if days_in_month(month, year)<day:#checks if the given day is possible given the month
return False
else:
return True
then your condition should look something like this:
if ((is_valid_date(year, month, day) == True) and (month<13)):
print('you will be refunded','$', + refund_period())
else:
print("Your date is invalid, try again.")
This question already has answers here:
Why does "a == x or y or z" always evaluate to True? How can I compare "a" to all of those?
(8 answers)
Closed 1 year ago.
import re
ausgabe =[]
Datum = re.compile(r"([0-2][1-9]|[3][0|1])(\/)([0-1][0-9])(\/)([0-2][0-9]{3})") #filter
Daten =(" 31/12/2000 blub 31.02.2000 und 32/01/2099 blub 28/02/2000 29/09/2009 29/39/2009 ") #Datenstr
ausgabe =Datum.findall(Daten) #durchsuchen
month = None
day = None
year = None
for Datum in ausgabe:
allright = True
day = int(Datum[0])
month =int(Datum[2])
year = int(Datum[4])
# print(day + "/" + month + "/" + year + "\n", end="")
if month == 4 or 6 or 11: #if the month is 4, 6,11
print(month)
if day > 30: #check the days of the month
allright= False
elif month == 2:
if day > 28:
print("feb hat nur 28 tage")
allright = False
elif day > 31:
print("größer als 31")
allright = False
if allright == True:
print(str(day) + "/" + str(month) + "/" + str(year) + "\n", end="")
Problem is in the following line.
The month is 12 and it jumps into the next if statement inside and checks this
but also if isnt 4 6 and 11. This is out of automate the boring stuff with python.
i just started coding some weeks ago so maybee its super easy to see...
i rewatched some videos and thougth about it but i dont understand this
if month == 4 or 6 or 11: #if the month is 4, 6,11
print(month)
if day > 30: #check the days of the month
allright= False
Instead of
if month == 4 or 6 or 11: #if the month is 4, 6,11
you should use
if month == 4 or month == 6 or month == 11: #if the month is 4, 6,11
The
if month == 4 or 6 or 11:
Is interpreted by Python as
if (month == 4) or (6) or (11):
while 6 and 11 are positive integers interpreted by Python as True
As described here
So im trying to change the index and output the values as numbers.
this is my code:
import datetime
year = int(input('Enter the year (4 digits):\n'))
month = int(input('Enter the month (1-12)')
DayL = ['Mon','Tues','Wednes','Thurs','Fri','Satur','Sun']
date = DayL[datetime.date(year,month,1).weekday()] + 'day'
print(date)
Sample Output:
Enter the year (4 digits):
> 2020
Enter the month (1 - 12):
> 1
Wednesday
Im trying to get the output as a index, and it should start at Sunday (Sunday = 0), but still give the correct answer. How do i go about this ?
The output i want:
Enter the year (4 digits):
> 2020
Enter the month (1 - 12):
> 1
3
There’s no reason to use DayL.
The date.weekday function already gives you the numeric weekday using Monday=0.
To map that to a Sunday=0 system, just add 1 mod 7:
weekday = (datetime.date(year,month,1).weekday() + 1) % 7
Try to use this:
>>> (datetime.datetime( 2020, 1, 1).weekday() + 1) % 7
3
>>>
For example if I want Saturday, starting with Oct 01, 2019, I need the result to return the monthly occurrence of the last Saturday (09/28/2019); in this case, 4.
This code gives me the desired result but I'd like to find a cleaner way (preferably only using datetime module):
def seq_of_sat():
newday = today
#gets the last Saturday
while newday.weekday() !=5:
newday -= timedelta(days=1)
if (newday.day > 28):
return 5
elif (newday.day > 21):
return 4
elif (newday.day > 14):
return 3
elif (newday.day > 7):
return 2
else: return 1
Edit:Solution
shift = (newday.weekday() + 2) % 7
newday -= timedelta(days=shift)
return (int(newday.day) + 6) // 7
So I this code which is suppose to return a list with the closest leap year of a list of years.
For example: calling the function with [1995 1750 2018] should return
1996 1748 2016
Which it does for that set of numbers.
The problem I am having is that when a leap year is in the input for example 2008 it does not give me back the closest leap year to 2008. I get back 2008.
Any suggestions as to how I can modify the code to make it work?
code
def is_leap(year):
leap = False
if year % 4 == 0:
if year % 100 != 0 or year % 400 == 0:
leap = True
return leap
major_b = []
major_f = []
newLst = []
def year_forward(yearBounds):
for item in yearBounds:
counter = 0
while not is_leap(item):
item = item + 1
counter += 1
major_f.append([item, counter])
return major_f
def year_backward(yearBounds):
for item in yearBounds:
counter = 0
while not is_leap(item):
item = item - 1
counter -= 1
major_b.append([item,counter])
return major_b
def findLastLeapYears(yearBounds):
forward = year_forward(yearBounds)
backward = year_backward(yearBounds)
counter = 0
for item in forward:
if abs(item[1]) < abs(backward[counter][1]):
newLst.append (str(item[0]))
counter+=1
elif abs(item[1]) == abs(backward[counter][1]):
if item[0] < backward[counter][0]:
newLst.append (str(item[0]))
counter += 1
else:
newLst.append (str(backward[counter][0]))
counter += 1
else:
newLst.append (str(backward[counter][0]))
counter+=1
return newLst
I'd avoid trying to roll your own leap year detection code. Use calendar.isleap to determine whether a year is a leap year or not.
Then go in a loop, like this:
import calendar
def find_nearest_leap(year):
offset = 1
while True:
if calendar.isleap(year - offset):
return year - offset
if calendar.isleap(year + offset):
return year + offset
offset += 1
To find the list of nearest leap years for a list of values, do this:
nearest_leap_years = [find_nearest_leap(year) for year in years]
Where years is the list of years you are interested in.
I'm also assuming the nearest leap year isn't the year itself, which seems to be a constraint of the problem...