When ever I ran this the output is always 0 where i was expecting like 29 or 30.
import datetime
def days_in_month(year, month):
"""
Inputs:
year - an integer between datetime.MINYEAR and datetime.MAXYEAR
representing the year
month - an integer between 1 and 12 representing the month
Returns:
The number of days in the input month.
"""
#if month is december, we proceed to next year
def month_december(month):
if month == 12:
return 1
else:
return month
#if month is december, we proceed to next year
def year_december(year, month):
if month == 12:
return new_year + 1
else:
return year
#verify if month/year is valid
if (month < 1) or (month > 12):
print ("please enter a valid month")
elif (year < 1) or (year > 9999):
print ("please enter a valid year between 1 - 9999")
else:
#subtract current month from next month then get days
date1 = (datetime.date(year_december(year, month), month_december(month), 1) - datetime.date(year, month, 1)).days
print (date1)
days_in_month(1997, 1)
As daniel told there is a standard library method. It is always better to reuse than reinvent.
import calender
def days_in_month(year, month):
if (month < 1) or (month > 12):
print ("please enter a valid month")
elif (year < 1) or (year > 9999):
print ("please enter a valid year between 1 - 9999")
else:
return calendar.monthrange(year, month)[1]
You forgot to add one month at first parameter.
Your codes:
datetime.date(year_december(year, month), month_december(month), 1)
= datetime.date(year, month, 1)
New codes:
date1 = (datetime.date(year_december(year, month+1), month_december(month+1), 1) - datetime.date(year, month, 1)).days
But pay an attention on the result will be wrong if December, you need to improve it like below:
Full codes:
import datetime
def days_in_month(year, month):
"""
Inputs:
year - an integer between datetime.MINYEAR and datetime.MAXYEAR
representing the year
month - an integer between 1 and 12 representing the month
Returns:
The number of days in the input month.
"""
#if month is december, we proceed to next year
def month_december(month):
if month > 12:
return month-12 #minus 12 if cross year.
else:
return month
#if month is december, we proceed to next year
def year_december(year, month):
if month > 12:
return year + 1
else:
return year
#verify if month/year is valid
if (month < 1) or (month > 12):
print ("please enter a valid month")
elif (year < 1) or (year > 9999):
print ("please enter a valid year between 1 - 9999")
else:
#subtract current month from next month then get days
date1 = (datetime.date(year_december(year, month+1), month_december(month+1), 1) - datetime.date(year, month, 1)).days
print (date1)
days_in_month(1997, 12)
days_in_month(1998, 1)
days_in_month(1998, 2)
Test Case
days_in_month(1997, 12)
days_in_month(1998, 1)
days_in_month(1998, 2)
Output
31
31
28
[Finished in 0.187s]
There is a really cool method I like, and you don't have to import anything. You just need to have two one-line functions. For input you need the year (as integer) and month (as integer) - which both comes from the date it self.
So:
function: check if it's a leap year or not.
function: create a list of the days (corrected with leap year) and call the item of it with the month.
def is_leap_year(year):
return ((year % 4 == 0) and (year % 100 != 0)) or (year % 400 == 0)
def get_days_in_month(year, month):
return [31, (29 if is_leap_year(year) else 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1]
Check it out.
Related
I'm writing a code that gives the user the day of the week, depending on which ever date (between the year 1583 and 9999) the user puts in. My problem is leap years. Leap years can be mathematically calculated with Zellers congruence: https://en.wikipedia.org/wiki/Zeller%27s_congruence
You can boil down the formula to the following statement:
It is a leap year if the year is evenly divisible by 400, or if it is evenly divisible by 4 but not evenly divisible by 100.
My code does a fine job with this, unless the year is true in both if-statements. For example: 2016. It is a leap year, which makes the first if-statement true. But it´s also NOT evenly divisible by 400. Which makes it true in the second if-statement. So when I run the program I get prompted with "Day: " twice.
Any tips on how to fix this?
The code in question:
if (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0)):
day = int(input("Day: "))
while day < 1 or day > 29:
print("Out of allowed range 1 to 29")
day = int(input("Day: "))
continue
if ((year % 4 != 0) and (year % 100 == 0)) or (year % 400 != 0):
day = int(input("Day: "))
while day < 1 or day > 28:
print("Out of allowed range 1 to 28")
day = int(input("Day: "))
continue
I´ve tried changing the 'or' operator to 'and' but that doesn´t really do anything
if ((year % 4 != 0) and (year % 100 == 0)) or (year % 400 != 0):
if ((year % 4 != 0) and (year % 100 == 0)) and (year % 400 != 0):
I've also tried manually putting in the leap years that are similar to 2016. But that doesn't really solve my problem.
The entire code:
x = [1,3,5,7,8,10,12]
y = [4,6,9,11]
year = int(input("Year: "))
while year < 1583 or year > 9999:
print("Out of allowed range 1583 to 9999")
year = int(input("Year: "))
month = int(input("Month: "))
while month < 1 or month >12:
print("Out of allowed range 1 to 12")
month = int(input("Month: "))
if month in x:
day = int(input("Day: "))
while day < 1 or day > 31:
print("Out of allowed range 1 to 31")
day = int(input("Day: "))
elif month in y:
day = int(input("Day: "))
while day < 1 or day > 30:
print("Out of allowed range 1 to 30")
day = int(input("Day: "))
elif month == 2:
if (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0)):
day = int(input("Day: "))
while day < 1 or day > 29:
print("Out of allowed range 1 to 29")
day = int(input("Day: "))
continue
if ((year % 4 != 0) and (year % 100 == 0)) or (year % 400 != 0):
day = int(input("Day: "))
while day < 1 or day > 28:
print("Out of allowed range 1 to 28")
day = int(input("Day: "))
continue
if month == 1 or month == 2:
month += 12
year -= 1
weekday = (( day + 13*(month+1)//5 + year + year//4
- year//100 + year//400 ) % 7)
print("It is a", end = ' ')
if weekday == 0:
print("Saturday")
elif weekday == 1:
print("Sunday")
elif weekday == 2:
print("Monday")
elif weekday == 3:
print("Tuesday")
elif weekday == 4:
print("Wednesday")
elif weekday == 5:
print("Thursday")
elif weekday == 6:
print("Friday")
The condition in your first if is correct:
(year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0))
But from De Morgan's law,
the opposite condition is
(year % 400 != 0) and ((year % 4 != 0) or (year % 100 == 0))
So you want to use that as the condition in your second if for February.
Or to be more clear, you can make a function for determining if it's a leap year:
def is_leap_year(year):
return (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0))
And then for February:
if is_leap_year(year):
# Get a day between 1 and 29
else:
# Get a day between 1 and 28
There area bunch of built-in modules in Python that are really useful, one of them is the datetime module which makes calculations with dates much easier. Your solution could be condensed into this code:
import datetime
while True:
try:
year=int(input('Year:'))
month=int(input('Month:'))
day=int(input('Day:'))
date = datetime.datetime(year,month,day)
print(date.strftime('%A'))
break
except ValueError as e:
print(e)
The ValueError will have the reason why it failed to create a datetime from the input parameters. You can still check for additional constraints, like the year and raise a ValueError(<your message>) when it's out of range.
I am trying to write a code that will accept any of the months of the year and output the month entered plus a list of the days in the month. But if February is entered it should ask for the birth year and check if that is a leap year and output February plus the days in February.
Where did I go wrong?
month = input("Enter any month of the year: ")
for n in month:
if (n == "January" or
n == "March" or
n == "April" or
n == "May" or
n == "June" or
n == "July" or
n == "August" or
n == "September" or
n == "October" or
n == "November" or
n == "December"):
print (n + range(1, 32))
elif n == "February" :
year = input("Enter a year")
for i in year:
if i % 4 == 0:
print (year + range(1,29))
I will advise you to simply use the built-in calendar module
# Program to display calendar of the given month and year
# importing calendar module
import calendar
yy = 2014 # year
mm = 11 # month
# To take month and year input from the user
# yy = int(input("Enter year: "))
# mm = int(input("Enter month: "))
# display the calendar
print(calendar.month(yy, mm))
# output
# November 2014
#Mo Tu We Th Fr Sa Su
# 1 2
# 3 4 5 6 7 8 9
#10 11 12 13 14 15 16
#17 18 19 20 21 22 23
#24 25 26 27 28 29 30
Assuming your intent is to learn how to program (such as for a educational assignment), the following should help. If it's just to do the job, you should probably use some of the built-in Python modules (like datetime or calendar) since they'll do a lot of the hard work for you.
First, input returns a string and, when you iterate over a string (for n in month), you'll get one character at a time. So iterating over "May" will give you "M", "a", and "y", none of which are equal to "May". Don't iterate, just compare the entire string:
if month == "January" ...
Second, not all those months have 31 days, you'll need to distinguish those that have 30:
if month == "February":
doFebStuff()
elif month in ['September', 'April', 'June', 'November']:
do30DayStuff()
else:
do31DayStuff()
Third, you can't concatenate a string and a range, you'll need to do something like:
print(month, end='')
for i in range(1, 32):
print(f" {i}", end='')
print()
Fourth, again for the year, input gives you a string and you don't want to iterate over it. You also want to make it an integer if you're going to do mathematical calculations on it, something like:
year = int(input("Enter a year: "))
Fifth, the rules for leap years are slightly more complex than every four years, specifically:
if it's a multiple of 400, it's a leap year; else
if it's a multiple of 100, it's not; else
if it's a multiple of 4, it is; else
it's not.
Taking all that into account, here's one way to do it, with added checks for validity (month name and year):
Days30 = ["September", "April", "June", "November"]
Days31 = ["January", "March", "May", "July", "August", "October", "December"]
lastDay = None
month = input("Enter any month of the year: ")
if month == "February":
lastDay = 28
year = -1
while year < 0:
try:
year = int(input("Enter the year: "))
except:
year = -1
if year % 400 == 0 or (year % 100 != 0 and year % 4 == 0):
lastDay = 29
elif month in Days30:
lastDay = 30
elif month in Days31:
lastDay = 31
if lastDay is None:
print(f"I don't know the month {month}")
else:
print(f"{month}:", end="")
for day in range(1, lastDay + 1):
print(f" {day}", end="")
print()
I wouldn't try to pass that off as your own work (you'll almost certainly be pinged for plagiarism) but it's a good bit of code for getting some ideas.
If you are asking where did you go wrong, there are some places:
Your if and elif are not indented properly, they do not align.
When you write for n in month:, n takes value of every letter in the month inputed. e.g. if you entered "July", n would be iterating as "J", "u", "l", and "y". So comparing n to full names of months will always evaluate to False. Just compare the month instead of iterating over it.
When taking input, python stores the value entered by user as string (year = input("Enter a year")). So when you are iterating over the variable year (for i in year) you are iterating over a string of numbers and not the number. Furthermore, modulus operator won't work for strings (i % 4) as i in this case is a string. Just do year = int(input("Enter a year")) to convert year to ineger and do not iterate over it, check for remainder with 4 directly.
You can refer to the code by paxdiablo to get a working code.
def isMagicDate(day,month,year):
if day* month == year %100:
return True
return False
def magic():
for year in range(1900,2000):
for month in range(1,13):
for day in range(1,month,year+1):
if isMagicDate(day,month,year):
print("%02d/%02d/%04d is a magic date "%(day,month,year))
magic()
I need to fix this code he's not giving all magic dates in 1900 to 2000
Using monthRange to adjust for the different days by month (i.e. Feb vs. January)
from calendar import monthrange
def isMagicDate(day, month, year):
return True if day*month == year % 100 else False
def main():
for year in range(1900, 2000):
for month in range(1, 13):
for day in range(1, monthrange(year, month)[1] + 1):
if isMagicDate(day, month, year):
print(f"{day:02d}/{month:02d}/{year:04d} is magic date.")
main()
def isMagicDate(day,month,year):
if day* month == year %100:
return True
else:
return False
def magic():
for year in range(1900,2000):
for month in range(1,13):
for day in range(1,30):
if isMagicDate(day,month,year):
print("%02d/%02d/%04d is a magic date "%(day,month,year))
magic()
TRY THIS!!
U have to put else after the if statement or the second statement will be excuted always,and also every month has 30 or 31 days(my code only take 30 days for every month).
I have a procedure that calculates age in days. I am thinking of using it to help me calculate my pay days.
I want it to ask for date 1 and then date 2, which would also be the current date.
However, I want it to be fancier and not even ask for date 2.
I want to use (time.strftime('%Y,%-m,%-d')) for the input of the second set of dates when I run this code.
I already have the code built for calculating my total net income from my 3 jobs.
y1,m1,d1 = 1994,4,1 #Birth_Date
y2,m2,d2 = 2014,1,1 #Current_Date
print daysBetweenDates(y1,m1,d1,y2,m2,d2)
My problem is that if I made y2,m2,d2 = (time.strftime('%Y,%-m,%-d'))
it will print it out with quotes at end so --> '2014,2,3'
and then everything just falls apart. I have been looking everywhere to find the solution
and everyone keeps talking about the datetime stuff but my problem with that is that is returns
datetime.strptime('2014-12-04', '%Y-%m-%d').date()
datetime.date(2014, 2, 3)
not only the date but also the datetime.date
I then tried
s = datetime.strptime('2014-12-04', '%Y-%m-%d').date()
s = string [16:-1] #
to remove all excess stuff but that didn't work also.
Please help me figure this one out guys.
I want y2,m2,d2 = current date without quotations.
You could calculate age in day(days between date) with the following:
import datetime
start_date = datetime.datetime.strptime('1975-10-03', '%Y-%m-%d').date()
end_date = datetime.datetime.strptime('2014-12-05', '%Y-%m-%d').date()
day_between_dates = (end_date - start_date).days
>> 14307
Intro to Computer Science Problem: Age in Days
I should have informed everyone of the constraints of: No Imports
I apologize for that, it was my first question I ever posed and had no idea how to pose them correctly.
My solution below without any imports:
def isLeapYear(year):
if year % 4 == 0:
if year % 100 != 0:
return True
else:
if year % 400 == 0:
return True
return False
def daysInMonth(year,month):
if month == 1:
return 31
if month == 2:
if isLeapYear(year) == True:
return 29
return 28
if month == 3:
return 31
if month == 4:
return 30
if month == 5:
return 31
if month == 6:
return 30
if month == 7:
return 31
if month == 8:
return 31
if month == 9:
return 30
if month == 10:
return 31
if month == 11:
return 30
if month == 12:
return 31
def nextDay(year, month, day):
"""Simple version: assume every month has 30 days"""
if day < daysInMonth(year,month):
return year, month, day + 1
else:
if month == 12:
return year + 1, 1, 1
else:
return year, month + 1, 1
def dateIsAfter(year1, month1, day1, year2, month2, day2):
"""Returns True if year1-month1-day1 is after year2-month2-day2. Otherwise, returns False."""
if year1 > year2:
return True
if year1 == year2:
if month1 > month2:
return True
if month1 == month2:
return day1 > day2
return False
def daysBetweenDates(year1, month1, day1, year2, month2, day2):
"""Returns the number of days between year1/month1/day1
and year2/month2/day2. Assumes inputs are valid dates
in Gregorian calendar."""
# program defensively! Add an assertion if the input is not valid!
assert dateIsAfter(year2, month2, day2, year1, month1, day1)
days = 0
while dateIsAfter(year2, month2, day2, year1, month1, day1):
days += 1
(year1, month1, day1) = nextDay(year1, month1, day1)
return (days)
y1,m1,d1 = 1994,7,14 #Birth_Date
y2,m2,d2 = 2014,1,1 #Current_Date
print daysBetweenDates(y1,m1,d1,y2,m2,d2)
My answer: 1 Year & 7 Months later :).
I had solved it, but just forgot to post it as an answer in the community.
I am leaving this here if anyone else might find this useful to learn from.
P.S However, thank you #user3277225 for your answer. It is a very elegant and simple solution that I might use later when I need to.
I am expecting some number as output from the above code,but I am not getting it out.
I am new to python but started coding with PHP.
Sorry if I go wrong some where.thanks
# By Websten from forums
#
# Given your birthday and the current date, calculate your age in days.
# Compensate for leap days.
# Assume that the birthday and current date are correct dates (and no time travel).
# Simply put, if you were born 1 Jan 2012 and todays date is 2 Jan 2012
# you are 1 day old.
#
# Hint
# A whole year is 365 days, 366 if a leap year.
def nextDay(year, month, day):
"""Simple version: assume every month has 30 days"""
if day < 30:
return year, month, day + 1
else:
if month == 12:
return year + 1, 1, 1
else:
return year, month + 1, 1
def daysBetweenDates(year1, month1, day1, year2, month2, day2):
"""Returns the number of days between year1/month1/day1
and year2/month2/day2. Assumes inputs are valid dates
in Gergorian calendar, and the first date is not after
the second."""
num = 0
# YOUR CODE HERE!
yearx = year1
monthx = month1
dayx = day1
while ((year2 >= year1 ) and ( month2 >= month1 ) and ( day2 >= day1 ) ) :
yearx,monthx,dayx = nextDay(yearx,monthx,dayx)
num = num + 1
num = '5'
return num
print daysBetweenDates(2012,9,30,2012,10,30)
You need to change the line:
while ((year2 >= year1 ) and ( month2 >= month1 ) and ( day2 >= day1 ) ) :
to:
while ((year2 >= yearx ) and ( month2 >= monthx ) and ( day2 >= dayx ) ) :
because you are not changing the value of month1 in your code but that of monthx.
Also, I think your while loop will break when dayx is greather that day2, so your measurement will be off by 1.
I have never mastered the while statement in Python but I think that is your infinite loop it is always true that day2 > day1 etc. So that condition remains true therefore you are stuck with num increasing
What does happen - do you get any error message?
if I were doing this I would set functions to determine
if the years are the same
if the years are the same then calculate the days between them
if the years are not the same calculate the number of days between the first date and the end of the year for that particular year
Calculate the number of days between the beginning of the year of the second date to the second date
Calculate the number of years difference between the end of the first year and the beginning of the second year and convert that into days
It may be clunky but it should get you home
Here is my solution in just one function
def daysBetweenDates(year1, month1, day1, year2, month2, day2):
##
# Your code here.
##
a1=str(month1)+'/'+str(day1)+'/'+str(year1)
date1 = datetime.strptime(a1, '%m/%d/%Y')
a2=str(month2)+'/'+str(day2)+'/'+str(year2)
date2 = datetime.strptime(a2, '%m/%d/%Y')
result= (date2 - date1).days
return result