Python date validation with no input/invalid input - python

The goal of the program is to:
validate inputs formats, and the date range should not be more than 2 months
No input/invalid input -> return the first or second half of the current month based on the day of the month
For the first half is from day 1 to day 15 for the second half is from day 16 till the end of the month
The hardcode, which will be the first code snippet, works as expected with the correct output, however the date validation in the second code snippet does not jump to the method indicated in the except block, which is causing me problems and not displaying correct output.
import os, sys
import datetime as dt
if __name__ == '__main__':
validate_range('2003/12/23', '2003/12/22')
validate_range('2003/10/23', '2003/11/22')
validate_range('2003/12/23', '2003/10/22')
validate_range('2003/7/23', '2003/10/22')
Code snippet with correct output (does not check if dates are correct format):
def validate_range(first_date, second_date):
start_date = dt.datetime.strptime(first_date, '%Y/%m/%d') # Get first date
end_date = dt.datetime.strptime(second_date, '%Y/%m/%d') # Get second date
num_months = (end_date.year - start_date.year) * 12 + (
end_date.month - start_date.month) # Get year/month within 2 months
if num_months >= 0 and num_months <= 2:
print("In Range")
else:
current_day = dt.datetime.today().day
if current_day >= 1 and current_day <= 15:
print("First half")
if current_day >= 16 and current_day <= 32:
print("Second half")
Correct Output:
In Range
In Range
First half
First half
Code snippet that does not display correct output (with date validation):
def read_args(first_date, second_date):
try:
start_date = dt.datetime.strptime(first_date, '%Y/%m/%d') # Get first date
end_date = dt.datetime.strptime(second_date, '%Y/%m/%d') # Get second date
v_range(start_date, end_date)
except:
w_range()
def v_range(first_date, second_date):
num_months = (second_date.year - first_date.year) * 12 + (
second_date.month - first_date.month) # Get year/month within 2 months
if num_months >= 0 and num_months <= 2:
print("In Range")
def w_range():
current_day = dt.datetime.today().day
if current_day >= 1 and current_day <= 15:
print("First half")
if current_day >= 16 and current_day <= 32:
print("Second half")
Output:
In Range
In Range

Keeping with your use of try / except, might need some improvement, but this example demonstrates it is possible:
import os, sys
import datetime as dt
def read_args(first_date, second_date):
try:
start_date = dt.datetime.strptime(first_date, '%Y/%m/%d') # Get first date
end_date = dt.datetime.strptime(second_date, '%Y/%m/%d') # Get second date
result = v_range(start_date, end_date)
except:
pass
# w_range()
def v_range(first_date, second_date):
num_months = (second_date.year - first_date.year) * 12 + (
second_date.month - first_date.month) # Get year/month within 2 months
if num_months >= 0 and num_months <= 2:
print("In Range")
else:
w_range()
def w_range():
current_day = dt.datetime.today().day
if current_day >= 1 and current_day <= 15:
print("First half")
if current_day >= 16 and current_day <= 32:
print("Second half")
if __name__ == '__main__':
read_args('2003/12/23', '2003/12/22')
read_args('2003/10/23', '2003/11/22')
read_args('2003/12/23', '2003/10/22')
read_args('2003/7/23', '2003/10/22')

Related

How to find day difference between two dates?

I was trying to make a simple program that finds the day difference between 2 dates that are inputted.
This is the code:
#program to find the day difference between one date and another
import calendar
date1Y = int(input("input year of date 1")) #putting the input from user to an list in order
date1M = int(input("input month of date 1")) #I don't know how to do this efficiently
date1D = int(input("input day of date 1"))
date2Y = int(input("input year of date 2"))
date2M = int(input("input month of date 2"))
date2D = int(input("input day of date 2"))
list_date1 = [date1Y, date1M, date1D] #lists of the first and second date in order Y/M/D
list_date2 = [date2Y, date2M, date2D]
days = 0
if list_date1(0) < list_date2(0) or (list_date1(0) == list_date2(0) and list_date1(1) < list_date2(1)):
while (list_date1(0) != list_date2(0) and list_date1(1) != list_date2(1)):
while (list_date1(1) <= 12):
a = calendar.monthrange(list_date1(0), list_date1(1))
days_month = a[1]
days += a[1]
list_date1(1) += 1
else :
list_date1(0) += 1
list_date1(1) = 0
elif list_date2(0) < list_date1(0) or (list_date1(0) == list_date2(0) and list_date2(1) < list_date1(1)):
while (list_date1(0) != list_date2(0) and list_date1(1) != list_date2(1)):
while (list_date2(1) <= 12):
a = calendar.monthrange(list_date2(0), list_date2(1))
days_month = a[1]
days += a[1]
list_date2(1) += 1
else :
list_date2(0) += 1
list_date2(1) = 0
if (date1D > date2D): #adding the day differences of the 2 dates
days = days + (date1D-date2D)
else :
days = days + (date2D-date1D)
print("the number of days difference =", str(days))
Since both list_date1 and list_date2 are lists, accessing an element from it would use square brackets instead of regular ones. Try changing all of your list_date#(#) to list_date#[#]
For example, with a list x = [1, 2, 3]
printing x[1] would print 2, because list indexes start at 0.

What's the simplest way to add '0' for month and day which are integers?

I have inputs month and day which are both int type, I want to pass them to a function to construct a path, and if month or day are numbers below 10, we add a 0 in front of the number:
def construct_path(year, month, day):
if month >= 10 or day >= 10:
path = f"xxx/{year}/{month}/{day}"
elif month < 10 and day >= 10:
path = f"xxx/{year}/0{month}/{day}"
elif month >=10 and day <10:
path = f"xxx/{year}/{month}/0{day}"
else:
path = f"xxx/{year}/0{month}/0{day}"
return path
So construct_path(2021, 5, 2) should return xxx/2021/05/02.
The code works but looks complicated, is there a better way to achieve this?
You can use :02d with formatting to allocate two spaces for a digit, and fill it up with 0 if the space remains empty.
def construct_path(year, month, day):
return f'xxx/{year}/{month:02d}/{day:02d}'
You could cast to a datetime format, then cast to a string format:
from datetime import datetime
def construct_path(year, month, day):
dt = datetime(year=year, month=month, day=day)
dt_as_path = dt.strftime('xxx/%Y/%m/%d')
return dt_as_path

Python get days in a month output 0

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.

Given input dates as strings find Age in Days

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.

My code is not giving output , I expected some number

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

Categories