Hi I'm a beginner at Python and am currently using Python 3.4.1 on PyCharm. I have recently made a project that calculates the amount of days between 2 dates, but there are 2 problems.
def get_first_day():
while True:
try:
print('First Date')
day = int(input('Day:'))
month = int(input('Month:'))
year = int(input('Year:'))
print(day, '/', month, '/', year)
date = [day, month, year * 365]
get_second_day(date)
except ValueError:
print('You were supposed to enter a date.')
def get_second_day(date_1):
while True:
try:
print('Second Date')
day = int(input('Day:'))
month = int(input('Month:'))
year = int(input('Year:'))
print(day, '/', month, '/', year)
date = [day, month, year * 365]
convert_dates_and_months(date_1, date)
except ValueError:
print('You were supposed to enter a date.')
def convert_dates_and_months(date_1, date_2):
days_unfiltered = [date_1[0], date_2[0]]
months_unfiltered = [date_1[1], date_2[1]]
year = [date_1[2], date_2[2]]
date_unfiltered = zip(days_unfiltered, months_unfiltered, year)
for d, m, y in date_unfiltered:
if m in [1, 3, 5, 7, 8, 10, 12]:
a = 31
elif m in [4, 6, 9, 11]:
a = 30
elif m in [2, 0] and int(y) % 4 is 0:
a = 29
else:
a = 28
m *= a
days = list(filter(lambda x: 0 < x < (a + 1), days_unfiltered))
months = list(filter(lambda x: 0 < x < 13, months_unfiltered))
date_1 = [days[0], months[0], year[0]]
date_2 = [days[1], months[1], year[1]]
determine_date_displacement(date_1, date_2)
def determine_date_displacement(date_1, date_2):
full_dates = zip(date_1, date_2)
days = -1
for k, v in full_dates:
days += (int(v) - int(k))
if days < 0:
days *= -1
print(days)
get_first_day()
The first problem is that the counter returns an incorrect number of days between 2 dates. The second is that def get_second_day repeats at the end for some reason. I'll show you what I mean:
First Date
Day:10
Month:09
Year:03
10 / 9 / 3
Second Date
Day:06
Month:06
Year:06
6 / 6 / 6
1087
Second Date
Day:
I know for a fact there are exactly 1,000 days between 10/09/03 and 06/06/06, yet the project returns 1,087 days.
If anyone could explain why this project is returning an incorrect number, as well as why it asks me to fill the second date again at the end, that would be perfect.
As this is my first question and I'm a beginner at Python, I apologise in advance for any weird phrasing/bad practices seen in this question.
Problem 1:
Your leap year calculation is off:
Leap years are years % 4 == 0 but only for years not year % 100 == 0 unless
they are also year % 400 == 0:
2004,2008,2012 : leap year (%4==0, not %100==0)
1700,1800,1900 : no leap year (%4 == 0 , % 100 == 0 but not %400 == 0)
1200,1600,2000 : leap years (* 1200 theor. b/c gregorian cal start)
Problem 2:
In your input you premultiply the year by 365 w/o checking for leap-years - they schould have 366 days but got 365 - which would result in lacking days when computing the amount of days for years that leap(ed).
Problem 3:
You have a controlflow-issue: the get_second_day() repeats because you do:
get_first_date()
while without end:
do smth
call get_second_date(..)
while without end:
do smth
call some calculation functions
that calc and print and return with None
back in get_second_date(), no break, so back to the beginning
of its while and start over forever - you are TRAPPED
fix it by putting a break after convert_dates_and_months(date_1, date) inside get_second_day(..)
Suggestions:
You can streamline the input by reducing the amount of duplicate code between get_first_day() and get_second_day() - this follows the DRY principle (Don't Repeat Yourself):
def getDate(text):
while True:
try:
print(text)
day = int(input('Day:'))
month = int(input('Month:'))
year = int(input('Year:'))
print(day, '/', month, '/', year)
return [day, month, year * 365] # see Problem 2
except ValueError:
print('You were supposed to enter a date.')
def get_first_day():
date1 = getDate("First Date")
# rest of code omitted
def get_second_day(date_1):
date = getDate("Second Date")
# rest of code omitted
A better solution would utilize datetime and datettime-parsing, especially if you want to handle input validation and leap-year estimation you would need far more checks.
Using datetime module would simplyfy this a lot:
import datetime
def getDate(text):
while True:
try:
print(text)
day = int(input('Day:'))
month = int(input('Month:'))
year = int(input('Year (4 digits):'))
print(day, '/', month, '/', year)
# this will throw error on invalid dates:
# f.e. 66.22.2871 or even (29.2.1977) and user
# gets a new chance to input something valid
return datetime.datetime.strptime("{}.{}.{}".format(year,month,day),"%Y.%m.%d")
except (ValueError,EOFError):
print('You were supposed to enter a valid date.')
def get_first_day():
return getDate("First Date")
def get_second_day():
return getDate("Second Date")
# while True: # uncomment and indent next lines to loop endlessly
first = get_first_day() # getDate("First Date") and getDate("Second Date")
second = get_second_day() # directly would be fine IMHO, no function needed
print( (second-first).days)
Output:
First Date
Day:10
Month:9
Year (4 digits):2003
10 / 9 / 2003
Second Date
Day:6
Month:6
Year (4 digits):2006
6 / 6 / 2006
1000
Good read: How to debug small programs (#1) - following it, could have at least lead you to the control-flow issue.
Related
def isYearLeap(year): # Leap year formula
if year % 4 == 0 and year % 100 != 0 :
return True
elif year % 400 == 0 :
return True
else :
return False
testData = [1900, 2000, 2016, 1987] # Test Data as reference
testResults = [False, True, True, False]
for i in range(len(testData)):
yr = testData[i]
print(yr,"->",end="")
result = isYearLeap(yr)
if result == testResults[i]:
print("OK")
else:
print("Failed")
def daysInMonth(year, month): # Finding out days in months in common & leap year
days = 0
mo31 = [1,3,7,5,8,10,12]
if year % 4 == 0 :
days = 1
if year % 100 == 0 :
days = 0
if year % 400 == 0 :
days = 1
if month == 2 :
return 28 + days
if month in mo31 :
return 31
return 30
testYears = [1900, 2000, 2016, 1987] # Test Data as reference
testMonths = [2, 2, 1, 11]
testResults = [28, 29, 31, 30]
for i in range(len(testYears)):
yr = testYears[i]
mo = testMonths[i]
print(yr, mo, "->", end="")
result = daysInMonth(yr, mo)
if result == testResults[i]:
print("OK")
else:
print("Failed")
def dayOfYear(year, month, day):
doy = ["Sat","Sun","Mon","Tue","Wed","Thu","Fri"] # Days of week
monthvalue = [1,4,4,0,2,5,0,3,6,1,4,6] # Months value zellers rule
century = [1700,1800,1900,2000] # Zellers rule
value = [4,2,0,6] # Zellers rule
rem = 0 # Remainder Variable
r = [] # Empty List to compare remainder and to a doy
y = str(year) # Converting year into string
y = int(y[2:4]) # Taking last two digits of string & if used return the function ends
y = int(year) # here returning last two digits
m = int(month)
d = int(day)
mo = [] # Empty list for comparing month with monthly values
dd = 0
if dd == 0 :
for i in range(len(monthvalue)) :
mo.append(i) # Creating mo list
if m in mo:
mo[i] == monthvalue[i]
dd = y // 4 + d + m
if m >= 2 :
dd -= 1
dd += y
for i in range(len(value)) :
if y in century :
y = century[i] == value[i]
dd += y
rem = dd % 7
for i in range(len(doy)) :
r.append(i) # Creating r list
if rem in r :
rem = r[i] == doy[i]
print(rem)
print(dayOfYear(2000, 12, 31)) # Giving output False "\n None
Your code contains a lot of illogical statements and redundancies, that make the code hard to read/understand.
I'd recommend first looking into a few style guides or more basic python tutorials.
Some examples:
y = str(year) # Converting year into string
y = int(y[2:4]) # Taking last two digits of string & if used return the function ends
y = int(year) # here returning last two digits
While the first two statements don't have any effect, their comments makes me think you forgot about two lines of code in between.
dd = 0
if dd == 0 :
...
That if check will never evaluate to false, so it's redundant
for i in range(len(monthvalue)) :
mo.append(i) # Creating mo list
if m in mo:
mo[i] == monthvalue[i]
The mo variable/list is never used again
Please check your program flow and report back
I recognize this as a lab in the netacad cisco python course.
You were tasked with creating an is_year_leap() function in LAB 4.3.1.6, a days_in_month() function in LAB 4.3.1.7, and a day_of_year() function in LAB 4.3.1.8. The functions have one, two, three parameters respectively. Please see below code. Note that I excluded a code to return None if any of the arguments are invalid. I would like you to add that on your own as learning.
# from LAB 4.3.1.6
def is_year_leap(year):
if year % 4 == 0: # leap year occur every 4 years & is divisible by 4
return True
else:
return False
# from LAB 4.3.1.7
def days_in_month(year, month):
# Create list with month days for each month as advised in the LAB
month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if is_year_leap(year):
month_days[1] = 29 # 29 days for February on a leap year.
return month_days[month - 1] # month 1 corresponds with index 0 & so on.
# for LAB 4.3.1.8
def day_of_year(year, month, day):
total = 0 # initializing the total variable to add results
# create loop to add only days in the months before the month in the input/test data
for i in range(1, month):
result = days_in_month(year, i)
total += result
day_num = total + day # add the value of the day argument to get day of the year
return day_num
# test data
print(day_of_year(2000, 12, 31))
print(day_of_year(1999, 12, 31))
print(day_of_year(2021, 7, 29))
A point to note is the occurrence of days above the number of days of months.
def is_year_leap(year):
return year % 4 == 0 and not year % 100 == 0 or year % 400 == 0
def days_in_month(year, month):
days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if is_year_leap(year):
days[1] = 29
return days[month - 1]
def day_of_year(year, month, day):
if day <= days_in_month(year, month):
count = 0
for yr in range(1, month):
count += days_in_month(year, yr)
return count + day
The leap year should fulfil all its conditions for getting the day of the year.
if the year is divisible by 400 then is_leap_year,
else if the year is divisible by 100 then not_leap_year
else if the year is divisible by 4 then is_leap_year
else not_leap_year
The number of days should also be checked whether it exceeds the day in the month.
#Check for leap year
def is_year_leap(year):
if year%400==0 or (year%100 != 0 and year%4==0):
return True
else:
return False
#Check for number of days in month
def days_in_month(year, month):
month31=[1,3,5,7,8,10,12]
if month in month31:
return 31
elif(month == 2):
if(is_year_leap(year)):
return 29
else:
return 28
else:
return 30
#Check for corresponding day of the year
def day_of_year(year, month, day):
total = 0
if day <= days_in_month(year, month):
total = day
for i in range(month-1):
total += days_in_month(year, i)
return total
else:
return "Your month doesn't have that many days."
print(day_of_year(2000, 12, 31))
print(day_of_year(2001, 12, 31))
print(day_of_year(2008, 12, 31))
print(day_of_year(2000, 11, 31))
I am new to python and am currently trying to create a program that will create a list of yearly percentage changes in revenue.
This is what I have so far:
revs = {}
for year in range(14, 20):
revs[year] = float(input("Revenue in {0}: ".format(year)))
revs_change = []
for year in range(14, 20):
next_year = year + 1
revs_change.append((revs[next_year] - revs[year])/revs[year])
print(revs_change[0])
The error comes on the 8th line and it has something to do with using the variable next_year.
Thanks!
If you are going to print out the values of year and next_year the problem is that there is no value for revs[next_year=20].
One way is to do like this-
start = 14
end = 21
for year in range(start, end):
revs[year] = float(input("Revenue in {0}: ".format(year)))
revs_change = []
for year in range(start, end-1):
next_year = year + 1
print(f"Year: {year}, Next Year: {next_year}\n")
revs_change.append( (revs[next_year] - revs[year])/revs[year] )
print(revs_change[0])
In Python, the end limit for any range you give will be taken excluding that upper limit i.e if you set the upper limit as 20, it evaluates up to 19. Give the upper limit as 21 so that you'll get the desired output
This question already has answers here:
How can I select all of the Sundays for a year using Python?
(10 answers)
Closed 2 years ago.
I need to write a code to find which month in a year 2018 for example has 5 or more Sundays?
I want to use calendar module in Python and save the resulting months in abbreviated form.
I saw documentation for calendar module but couldnt figure out the code.
Here's one way. And also, go back to https://docs.python.org/3/library/calendar.html and try playing around with some of the things described in it.
import calendar
def find_five_sunday_months(year):
calendar.setfirstweekday(calendar.SUNDAY)
five_sunday_months = []
for month in range(1, 13):
calendar_month = calendar.monthcalendar(year, month)
# If you're counting Sunday as the first day of the week, then any month that extends into
# six weeks, or starts on a Sunday and extends into five weeks, will contain five Sundays.
if len(calendar_month) == 6 or (len(calendar_month) == 5 and calendar_month[0][0] == 1):
five_sunday_months.append(calendar.month_abbr[month])
return five_sunday_months
print (find_five_sunday_months(2018))
Thanks #TaneTachyon for the document link you shared. It helped me lot for exploring the calendar module.
I have come up with below code for the same task.
I know it's a bit long, but for a beginner, logic and learning to use different functions, this helped me a lot:
import calendar
calendar.setfirstweekday(calendar.SUNDAY)
year = 2018
a = ()
Sun_month = []
leap = calendar.isleap(year)
for i in range(1,13):
a = calendar.monthrange(year, i)
#print(a[1])
if a[1] == 30:
if (a[0] == 5 or a[0] == 6):
s = calendar.month_abbr[i]
Sun_month.append(s)
elif a[1] == 31:
if (a[0] == 4 or a[0] == 5 or a[0] == 6):
s = calendar.month_abbr[i]
Sun_month.append(s)
elif leap == True:
if (a[0] == 6):
s = calendar.month_abbr[i]
Sun_month.append(s)
print("The months having >= 5 sundays in {} is".format(year))
print(Sun_month)
import calendar as c
a = []
for i in range(1,13):
a.append(list(c.monthrange(2018,i)))
b = c.month_abbr[1:13]
c = []
for i in range(0,12):
if (a[i][0]>4 and a[i][1]==30) or (a[i][0]>=4 and a[i][1]==31):
c.append(b[i])
print(c)
import calendar
# here all the weeks are set to start from sunday for every month
calendar.setfirstweekday(calendar.SUNDAY)
l = list() # empty list
# the range will be from 1 to 12
for month in range(1, 13):
# for each month in 2018 month calendar is created
calendar_month = calendar.monthcalendar(2018, month)
# to count no.of sundays present in each month
c = 0
# len(calendar_month) for number of rows(i.e. weeks) in the month
for i in range(len(calendar_month)):
# calendar_month[i][0] first day(i.e. sunday) of ith week which is
#sunday if date is greater than 0
if calendar_month[i][0] > 0:
c += 1 # each sunday is counted
if c == 5:
# calendar.month_abbr[month] abbreviated form of month with 5 sundays
#is added to the list
l.append(calendar.month_abbr[month])
print(l)
#With Explanation
import calendar
def find_five_sunday_months(year):
calendar.setfirstweekday(calendar.SUNDAY)
five_sunday_months = []
for month in range(1, 13):
calendar_month = calendar.monthcalendar(year, month)
print('--------------------------------------------------------------------------------')
print('month :',calendar.month_name[month])
print('Count returned tuple as no. of weeks in a month :',calendar_month)
print('No. of weeks in a month:',len(calendar_month))
print('if we have 5 weeks and 5 sundays,it should print 1 else 0 :',calendar_month[0][0])
# If you're counting Sunday as the first day of the week, then any month that extends into
# six weeks, or starts on a Sunday and extends into five weeks, will contain five Sundays.
if len(calendar_month) == 6 or (len(calendar_month) == 5 and calendar_month[0][0] == 1):
print('Yay!')
five_sunday_months.append(calendar.month_abbr[month])
return five_sunday_months
print (find_five_sunday_months(2020))
I'm building out a forecast model in Python and need to calculate the number of remaining days for each day name of a month. For example, on October 25, 2017 there are no remaining Wednesdays in the current month and there is 1 remaining Thursday, Friday, Saturday, Sunday, Monday, and Tuesday.
I'm able to achieve the same result in R with:
first <- as.Date(cut(Sys.Date(), "month"))
last <- as.Date(cut(first + 31, "month")) - 1
sum(format(seq(Sys.Date(), last, "day"), "%w") == 0) -> Sunday
I'm trying to edit the following code block which was initially intended to count weekdays in a month for my purposes but not sure if I'm on the right track
import calendar
weekday_count = 0
cal = calendar.Calendar()
for week in cal.monthdayscalendar(2013, 8):
for i, day in enumerate(week):
# not this month's day or a weekend
if day == 0 or i >= 5:
continue
# or some other control if desired...
weekday_count += 1
print(weekday_count)
You might want to use this as a starting point. It will calculate the number of remaining Mondays given a day, month, year of your choosing.
from datetime import datetime, timedelta
# Monday = 0
def get_remaining_mondays(year, month, day):
count = 0
try:
d = datetime(year, month, day)
wday = d.weekday()
d += timedelta(days=7 - wday)
while d.month == month:
count += 1
d += timedelta(days=7)
except ValueError as v:
return v
return count
print(get_remaining_mondays(2017, 11, 7))
How can I get the numberof Sundays of the current month in Python?
Anyone got any idea about this?
This gives you the number of sundays in a current month as you wanted:
import calendar
from datetime import datetime
In [367]: len([1 for i in calendar.monthcalendar(datetime.now().year,
datetime.now().month) if i[6] != 0])
Out[367]: 4
I happened to need a solution for this, but was unsatisfactory with the solutions here, so I came up with my own:
import calendar
year = 2016
month = 3
day_to_count = calendar.SUNDAY
matrix = calendar.monthcalendar(year,month)
num_days = sum(1 for x in matrix if x[day_to_count] != 0)
I'd do it like this:
import datetime
today = datetime.date.today()
day = datetime.date(today.year, today.month, 1)
single_day = datetime.timedelta(days=1)
sundays = 0
while day.month == today.month:
if day.weekday() == 6:
sundays += 1
day += single_day
print 'Sundays:', sundays
My take: (saves having to worry about being in the right month etc...)
from calendar import weekday, monthrange, SUNDAY
y, m = 2012, 10
days = [weekday(y, m, d+1) for d in range(*monthrange(y, m))]
print days.count(SUNDAY)
Or, as #mgilson has pointed out, you can do away with the list-comp, and wrap it all up as a generator:
sum(1 for d in range(*monthrange(y,m)) if weekday(y,m,d+1)==SUNDAY)
And I suppose, you could throw in a:
from collections import Counter
days = Counter(weekday(y, m, d + 1) for d in range(*monthrange(y, m)))
print days[SUNDAY]
Another example using calendar and datetime:
import datetime
import calendar
today = datetime.date.today()
m = today.month
y = today.year
sum(1 for week in calendar.monthcalendar(y,m) if week[-1])
Perhaps a slightly faster way to do it would be:
first_day,month_len = monthrange(y,m)
date_of_first_sun = 1+6-first_day
print sum(1 for x in range(date_of_first_sun,month_len+1,7))
You can do this using ISO week numbers:
from datetime import date
bom = date.today().replace(day=1) # first day of current month
eom = (date(bom.year, 12, 31) if bom.month == 12 else
(bom.replace(month=bom.month + 1) - 1)) # last day of current month
_, b_week, _ = bom.isocalendar()
_, e_week, e_weekday = eom.isocalendar()
num_sundays = (e_week - b_week) + (1 if e_weekday == 7 else 0)
In general for a particular day of the week (1 = Monday, 7 = Sunday) the calculation is:
num_days = ((e_week - b_week) +
(-1 if b_weekday > day else 0) +
( 1 if e_weekday >= day else 0))
import calendar
MONTH = 10
sundays = 0
cal = calendar.Calendar()
for day in cal.itermonthdates(2012, MONTH):
if day.weekday() == 6 and day.month == MONTH:
sundays += 1
PAY ATTENTION:
Here are the Calendar.itermonthdates's docs:
Return an iterator for one month. The iterator will yield datetime.date
values and will always iterate through complete weeks, so it will yield
dates outside the specified month.
That's why day.month == MONTH is needed
If you want the weekdays to be in range 0-6, use day.weekday(),
if you want them to be in range 1-7, use day.isoweekday()
My solution.
The following was inspired by #Lingson's answer, but I think it does lesser loops.
import calendar
def get_number_of_weekdays(year: int, month: int) -> list:
main_calendar = calendar.monthcalendar(year, month)
number_of_weeks = len(main_calendar)
number_of_weekdays = []
for i in range(7):
number_of_weekday = number_of_weeks
if main_calendar[0][i] == 0:
number_of_weekday -= 1
if main_calendar[-1][i] == 0:
number_of_weekday -= 1
number_of_weekdays.append(number_of_weekday)
return sum(number_of_weekdays) # In my application I needed the number of each weekday, so you could return just the list to do that.