How to compare dates (in string)? - python

I want to determine the cost by specific rules between two dates. The problem is that the input is in not in a date format but as:
6 6 2020
9 9 2020
The conditions are as follows:
If same day, there is a fixed cost of 20.
If after a day but still within a month cost = 30 * (the number of days).
If after a month but still within a year, the cost = 1000 * (the number of months).
If after a year in which it was created,then there is a fixed cost of 20000.
How do I compare them by changing only the cost( ) ?
what I have tried is far from perfect and already uses too many branches:
def cost(d1, m1, y1, d2, m2, y2):
yd=0
md=0
dd = 0
if (y1==y2):
yd=0
else: yd=abs(y1-y2)
if (m1==m2):
md=0
else: md=abs(m1-m2)
if (d1==d2):
dd=0
else: dd=abs(d1-d2)
cost = int()
if (md>11 or yd>0):
cost = 20000
elif (md>0 and md<12):
cost = 1000*md
elif (dd==0 and md==0 and yd==0):
cost = 20
elif (dd>0 and md==0 and yd==0):
cost = dd*30
print("yd=",yd)
print("md=",md)
print("dd=",dd)
return cost
if __name__ == '__main__':
#d1M1Y1 = input().split()
d1M1Y1 = [6,1,2020]
d1 = int(d1M1Y1[0])
m1 = int(d1M1Y1[1])
y1 = int(d1M1Y1[2])
#d2M2Y2 = input().split()
d2M2Y2 = [4,1,2021]
d2 = int(d2M2Y2[0])
m2 = int(d2M2Y2[1])
y2 = int(d2M2Y2[2])
result = server_cost(d1, m1, y1, d2, m2, y2)
print(str(result) + '\n')

import datetime
def cost(d1, m1, y1, d2, m2, y2):
date1 = datetime.datetime(y1, m1, d1)
date2 = datetime.datetime(y2, m2, d2)
delta = date2 - date1
if delta.days <= 1:
return 20
elif delta.days < 30:
return 30 * delta.days
elif delta.days < 365:
return 1000 * (delta.days//12) # use a function that suits your def of months
else:
return 20000

As mentioned in comment, best to convert to datetime
E.g.
import datetime
d1M1Y1 = [6,1,2020]
d1 = int(d1M1Y1[0])
m1 = int(d1M1Y1[1])
y1 = int(d1M1Y1[2])
#d2M2Y2 = input().split()
d2M2Y2 = [4,1,2021]
d2 = int(d2M2Y2[0])
m2 = int(d2M2Y2[1])
y2 = int(d2M2Y2[2])
date1 = datetime.datetime(y1, m1, d1)
date2 = datetime.datetime(y2, m2, d2)
print(date1)
print(date2)
EDIT: Demo for working with datetime differences
dateTimeDifference = date2 - date1
# Datedifferene in days
daysDifference = dateTimeDifference.total_seconds() / 86400
print(daysDifference)
if daysDifference > 365:
print ("More than a year")
else:
print("Less than a year")

import time
import datetime
def str_to_date(str):
fmt = '%d %m %Y'
time_tuple = time.strptime(str, fmt)
day, month, year = time_tuple[:3]
a_date = datetime.date(day, month, year)
return a_date
a = str_to_date('22 7 2020')
b = str_to_date('5 8 2019')
c = abs(a-b)
if c.days<=1:
cost=20
elif c.days<30:
cost=30*c.days
elif c.days<365:
cost=1000*(c.days//30)
else:
cost=20000
print(cost)

Related

Issues with naming variables for zellers congruence project

i'm working on making a program in python that uses arrays since it's the new chapter i'm learning. The goal of my program will ask the user for month day and day and I seem to have it almost done except that i have an issue with 2 lines in this whole code. I will write a comment in where i'm getting the errors.
def calc_zellers_congruence(get_day: int, get_year: int, get_month: int) -> str:
# Calculates the month day and year
days = [""] * 7
day_Of_Week = 0
day_of_month = 0
century = 0
year_of_the_century = get_year % 100
days[1] = "Sunday"
days[2] = "Monday"
days[3] = "Tuesday"
days[4] = "Wednessday"
days[5] = "Thursday"
days[6] = "Friday"
days[0] = "Saturday"
dayOfWeek = day_of_month + 13 * get_month + int(1) / 5 + year_of_the_century + int(year_of_the_century) / 4 + int(
century) / 4 + 5 * century % 7
name_of_day = days[day_Of_Week]
return name_of_day
def displayResults():
print("Result" + day)
def get_day():
print("Enter a Day")
get_day = int(input())
return get_day
def get_month():
print("Enter a Month")
month = int(input())
return month
def get_year():
print("Enter a Year")
get_year: int(input())
return year
# Main
# This program will calculate birthdays using arrays and zellers congruence
# References...Programming Fundamentals WiKi, J Robinson, GeeksForGeek.com
year = get_year()
month = get_month()
day = get_day()
calc_Zeller_Congruence: calc_zellers_congruence(get_year, get_month, get_day)
displayResults(calc_zellers_congruence)
I've tried renaming them but have gotten more errors after switching them from uppercase to lowercase and also adding snake cases.

How to check given date is exactly a month ago : python

I need to check if a given date is exactly a month ago from today, for example, if today is 01-Nov-2021 then exactly a month ago will be 01-Oct-2021 (not exactly 30 days.)
I wrote a code and it works fine
today = fields.Date.from_string(fields.Date.today())
if today.month == 1:
one_month_ago = today.replace(year=today.year - 1, month=12)
else:
extra_days = 0
while True:
try:
one_month_ago = today.replace(month=today.month - 1, day=today.day -
extra_days)
break
except ValueError:
extra_days += 1
if one_month_ago == given_date:
# do something
else:
# do something
It handles well mostly all the cases but mishandles some cases. For example, the given date is 31-March-2021 and today date is 30-April-2021 and 31-April-2021 will not come to compare. I need my code to run daily and check something. It also mishandles cases of 29-31 January because 29-31 February will not come to compare.
From the given date, you can find the previous month and year and using these two obtained values, find the length of the previous month. The last thing to be done will be to compare the day of the given date with the length of the previous month and accordingly, return the desired date.
Demo:
from datetime import date
from calendar import monthrange
def date_a_month_ago(today):
x = today.month - 1
previous_month = 12 if x == 0 else x
year = today.year - 1 if x == 0 else today.year
last_day_of_previous_month = monthrange(year, previous_month)[1]
day = last_day_of_previous_month if today.day > last_day_of_previous_month else today.day
return date(year, previous_month, day)
# Tests
print(date_a_month_ago(date(2021, 11, 1)))
print(date_a_month_ago(date(2021, 1, 31)))
print(date_a_month_ago(date(2021, 12, 31)))
print(date_a_month_ago(date(2021, 3, 29)))
print(date_a_month_ago(date(2020, 3, 29)))
print(date_a_month_ago(date(2021, 3, 30)))
print(date_a_month_ago(date(2020, 3, 30)))
Output:
2021-10-01
2020-12-31
2021-11-30
2021-02-28
2020-02-29
2021-02-28
2020-02-29
ONLINE DEMO
May be like this:
from typing import Tuple
def last_month(year: int, month: int) -> Tuple[int, int]:
y, m = year, month - 1
if m == 0:
y, m = y - 1, 12
return y, m
def one_month_ago(today: datetime) -> datetime:
y, m = last_month(today.year, today.month)
dt = today.replace(year=y, month=m)
for day in range(today.day, 0, -1):
try:
return dt.replace(day=day)
except ValueError:
...
I did this and it's giving me the required output:
from datetime import date
from calendar import monthrange
def is_one_month(given_date, today):
x = today.month - 1
previous_month = 12 if x == 0 else x
year = today.year - 1 if x == 0 else today.year
last_day_of_previous_month = monthrange(year, previous_month)[1]
day = last_day_of_previous_month if today.day > last_day_of_previous_month else today.day
one_month_ago = date(year, previous_month, day)
if today.month == 2:
if given_date.month == today.month-1 and given_date.year == today.year and given_date.day >= 28:
return 'it is one month before'
if today.month == 4 or today.month == 6 or today.month == 9 or today.month == 11:
if given_date.month == today.month-1 and given_date.day == 31:
return 'it is one month before'
if one_month_ago == given_date:
return 'it is one month before'
else:
return 'it is NOT one month before'
print(is_one_month(date(2021, 1, 30), date(2021, 2, 28)))
Output:
it is one month before

Change time from 12-h to 24-h format

I want to convert a time from 12-h format to 24-h format
This is my code:
def change_time(time):
import datetime as dt
FMT12 = '%H:%M:%S %p'
FMT24 = '%H:%M:%S'
# time is a string
if time.find('PM') != -1: # if exists
t1 = dt.datetime.strptime(time, FMT12)
t2 = dt.datetime.strptime('12:00:00', FMT24)
time_zero = dt.datetime.strptime('00:00:00', FMT24)
return (t1 - time_zero + t2).time()
else:
return dt.datetime.strptime(time, FMT12).time()
This is the output :
print(change_time('09:52:08 PM')) # -> 21:52:08
So, this code is working, but I want a better version of it.
Here is a much faster working method:
from datetime import datetime
def change_time(time):
in_time = datetime.strptime(time, "%I:%M:%S %p")
new_time = datetime.strftime(in_time, "%H:%M:%S")
print(new_time)
change_time('09:52:08 PM')
Output:
>>> 21:52:08
def t12_to_24(time):
am_or_pm = time[-2] + time[-1]
time_update = ''
if am_or_pm == 'am' or am_or_pm == 'AM':
for i in time[0:-3]:
time_update += i
elif am_or_pm == 'pm' or am_or_pm == 'PM':
change = ''
for i in time[0:2]:
change += i
c = 12 + int(change)
if c >= 24:
c = 24 - c
c = list(str(c))
for i1 in c:
time_update += i1
for i2 in time[2:-3]:
time_update += i2
print(time_update)
time = list(input())
t12_to_24(time)

Python daysBetweenDate

I think I might have an infinite loop because I keep getting back an error message whenever I run the code, it says "program shut down for using 13 CPU seconds."
The entire code, should take a date as input and output the next day, this code assumes all months are 30 days. Aside from the daysBetweenDates function, everything else seems to be working fine. Does anyone have any suggestions? Or maybe someone can tell me what I'm missing?
def daysInMonth(year, month):
return 30
def nextDay(year, month, day):
if day < 30:
return year, month, day + 1
else:
if month == 12:
return year + 1, 1, 1
else:
return year, month + 1, 1
return
def dateIsBefore(year1, month1, day1, year2, month2, day2):
if year1 < year2:
return True
def daysBetweenDates(year1, month1, day1, year2, month2, day2):
days = 0
while dateIsBefore(year1, month1, day1, year2, month2, day2):
days += 1
return days
def test():
test_cases = [((2012,1,1,2012,2,28), 58),
((2012,1,1,2012,3,1), 60),
((2011,6,30,2012,6,30), 366),
((2011,1,1,2012,8,8), 585 ),
((1900,1,1,1999,12,31), 36523)]
for (args, answer) in test_cases:
result = daysBetweenDates(*args)
if result != answer:
print "Test with data:", args, "failed"
print result
else:
print "Test case passed!"
test()
Your daysBetweenDates() algorithm does indeed have an infinite loop.
while dateIsBefore(year1, month1, day1, year2, month2, day2):
days += 1
You never modify any of the year/month/day values here in the loop, so if the condition is true once, it will be true forever.
The solution, in concept, would be to decrease day2 by one every time, so when the two dates become equal, days will be the day difference between them. However, since you said you made the assumption that each month has 30 days, you're overcomplicating things for yourself. You can find the day difference between two dates by converting the (year, month, day) tuple to a day value. For example,
def days_between_dates(y1, m1, d1, y2, m2, d2):
date1 = y1*360 + (m1-1)*30 + d1
date2 = y2*360 + (m2-1)*30 + d2
# assuming you want to return 0 if date2 is before date1
return date2 - date1 if date2 >= date1 else 0
This solution counts daysInMonth correctly, doesn't involve any kind of infinite loop, counts correct dates in a leap year and provides an exact answer to inputs.
The solution is written in Python.
def daysInMonth(m,y):
if m == 1 or m == 3 or m == 5 or m == 7 or m == 8 or m ==10 or m == 12:
return 31
else :
if m == 2:
if isLeapYear(y):
return 29
return 28
return 30
def nextDay(y,m,d):
if d < daysInMonth(m,y):
return y, m, d+1
else:
if m == 12:
return y + 1, 1, 1
else:
return y, m + 1, 1
def isLeapYear(y):
if y % 400 == 0:
return True
elif y % 4 == 0:
return True
else:
if y % 100 == 0:
return False
return False
def dateIsBefore(y1, m1, d1, y2, m2, d2):
days = 0
if y1 < y2 :
return True
if y1 == y2:
if m1 < m2:
return True
if m1 == m2:
return d1<d2
return False
def daysbetweendates(y1, m1, d1, y2, m2, d2):
days = 0
while dateIsBefore(y1, m1, d1, y2, m2, d2):
y1, m1, d1 = nextDay(y1, m1, d1)
days = days + 1
return days
def test():
test_cases = [((2012,1,1,2012,2,28), 58),
((2012,1,1,2012,3,1), 60),
((2011,6,30,2012,6,30), 366),
((2011,1,1,2012,8,8), 585 ),
((1900,1,1,1999,12,31), 36523)]
for (args, answer) in test_cases:
result = daysbetweendates(*args)
if result != answer:
print "Test with data:", args, "failed"
print result
else:
print "Test case passed!"
test()
The function dateIsBefore is incomplete.
def dateIsBefore(year1, month1, day1, year2, month2, day2):
if year1 < year2:
return True
if year1 == year2 and month1 < month2:
return True
if year1 == year2 and month1 == month2 and day1 < day2:
return True
return False
(It could be simplified, but I left it like this for clarity. Also, of course, you could use datetime.date--someone else already made that comment; see also other answer that tells you to increment year1,month1, and day1)
dateIsBefore will always return True.

Python program saying variable 'dateNumber' is not defined

def dateCalculationNorm(year):
a = year%19
b = year%4
c = year%7
d = (19*a + 24)%30
e = (2*b + 4*c + 6*d + 5)%7
dateNumber = 22 + d + e
return dateNumber
def dateCalculationSpecial(year):
a = year%19
b = year%4
c = year%7
d = (19*a + 24)%30
e = (2*b + 4*c + 6*d + 5)%7
dateNumber = 15 + d + e
return dateNumber
def dateOutput(year, date):
print("The date of Easter in the year {0} is {1}.".format(year, date))
def main():
print("Easter Date Calculator")
print()
year = eval(input("Enter the year: "))
if year >= 1900 and year <= 2099:
dateCalculationNorm(year)
if dateNumber > 31:
date = "April " + str(dateNumber - 31)
dateOutput(year, date)
else:
date = "March " + str(dateNumber)
dateOutput(year, date)
elif year == 1954 or year == 1981 or year == 2049 or year == 2076:
dateCalculationSpecial(year)
if dateNumber > 31:
date = "April " + str(dateNumber - 31)
dateOutput(year, date)
else:
date = "March " + str(dateNumber)
dateOutput(year, date)
else:
print("Sorry, but that year is not in the range of this program.")
if __name__ == '__main__':
main()
I am having trouble getting main() to accept dateNumber in the line following
(if year >= 1900 and year <=2099) Python is saying that dateNumber is not defined. I tried making dateNumber global at the beginning of the program and that worked (albeit with a warning from Python), but I know that's the sloppy way to get this program working.
Any help is very much appreciated.
You need to instantiate dateNumber.
if year >= 1900 and year <= 2099:
dateNumber = dateCalculationNorm(year) # Instantiate here.
if dateNumber > 31:
date = "April " + str(dateNumber - 31)
dateOutput(year, date)
else:
date = "March " + str(dateNumber)
dateOutput(year, date)
As it stands, there's nothing like that inside your main() function. There's no need to set it to a global either.

Categories