Issue with code related to deltatime in python - python

The following code's aim was to convert a date to corresponding day. I took 2nd October 2017 as the reference and hence proceeded. I don't entirely understand deltatime and guessing the problem might be with how I used it. Hope someone could help me.
import datetime
ans = 'Y'
today = datetime.date(2017, 10, 2)
while ans is 'Y' or ans is 'y':
d = input("Enter a date (DD/MM/YYYY)")
day = int(d[:2])
month = int(d[3:5])
year = int(d[6:])
thatday = datetime.date(year, month, day)
deltat = thatday - today
dif = int(deltat.days/7)
if dif is 6:
print("Sunday")
elif dif is 1:
print("Tuesday")
elif dif is 2:
print ("Wednesday")
elif dif is 3:
print("Thursday")
elif dif is 4:
print("Friday")
elif dif is 5:
print("Saturday")
else:
print("Monday")
ans = input("One more time, eh? (y/n)")

I started of trying to help you but got lost when I didn't really understood what you need.
Basically I think you need to read about strftime which prints a datetime object in a specific way: e.g. datetime.strftime("%A") gives weekday. You also need strptime which reads a date from a string, e.g. datetime.strptime("31/12/1999","%d/%m/%Y")
Look at your modified code below:
import datetime
ans = 'Y'
today = datetime.datetime.now().date()
while ans.title() == 'Y':
d = input("Enter a date (DD/MM/YYYY)")
thatday = datetime.datetime.strptime(d,"%d/%m/%Y").date()
deltat = thatday - today # timedelta
dif = int(deltat.days/7) # timedelta/7? What is this?
print(thatday.strftime("%A")) # Here you get the weekday of thatday
ans = input("One more time, eh? (y/n)")

if you're just looking for the day of the week you can also do this. The weekday() returns an integer value, with Monday being 0 and Sunday being 6
from datetime import *
weekdays = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']
d = date(2017, 10, 2).weekday()
print(weekdays[d])
That date returns Monday

Related

How to make a loop that validates the user-input dates based on the functions created?

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.")

How to subtract from a value if the day is a certain day

I'm new to python, and I'm trying to make a pocket money/ saving calculator, where it assumes you get money every week and a set amount of money on birthdays/christmas and tell you how long it will take to reach the amount you are trying to save up for. It works well in counting the weeks it would take to reach the goal, but it seems to ignore the special dates. Is there a way I can change the code so that it would take them into account?
import datetime as dt
import math as mt
current_balance = float(input("What is your current balance?: £"))
pocket_money = float(input("How much pocket money do you get per week?: £"))
goal = float(input("How much money do you need?: £"))
today = dt.date.today()
if goal <= current_balance:
print(f"You already have enough money and you will have £{current_balance-goal} left.")
else:
money_needed = goal - current_balance
datetest = today
d = dt.timedelta(days=1)
counter = 0
birthday = dt.datetime(datetest.year, 5, 16)
christmas = dt.datetime(datetest.year, 12, 25)
while money_needed > 0:
if datetest.weekday() == 0:
money_needed = money_needed - 5
counter += 1
datetest += d
elif datetest == birthday or datetest == christmas: #<-- This bit seems to do nothing
money_needed = money_needed - 200
if datetest.weekday() == 0:
counter += 1
datetest += d
else:
datetest += d
print(counter)
e.g. if the first three inputs were 10, 5, and 500, it would return 98, which is the number of weeks it would take if the birthday/christmas was ignored.
A few issues:
You're not using pocket_money at all in your script, you're just using money_needed = money_needed - 5 each week, so the calculation is messed up even before trying to consider christmas and birthdays.
datetest += d runs inside every possible date, so no need to repeat that 3 times in the loop
There's also no need to repeat counter += 1 as it always happens on the same weekday regardless of holidays
Lastly, the most important issue: If you print out today you will see it's equal to 2021-09-06 but if you print out your birthday for example, you will see it is equal to 2021-05-16 00:00:00. Notice a different in their format? They can never be equal! One is a datetime object and the other just a date object. To fix that, compare the date directly (day and month) or just use date instead of datetime when defining them
To implement all of that:
import datetime as dt
import math as mt
current_balance = float(input("What is your current balance?: £"))
pocket_money = float(input("How much pocket money do you get per week?: £"))
goal = float(input("How much money do you need?: £"))
today = dt.date.today()
if goal <= current_balance:
print(f"You already have enough money and you will have £{current_balance-goal} left.")
else:
money_needed = goal - current_balance
datetest = today
d = dt.timedelta(days=1)
counter = 0
birthday = dt.date(datetest.year, 5, 16)
christmas = dt.date(datetest.year, 12, 25)
while money_needed > 0:
datetest += d
if datetest.weekday() == 0:
money_needed = money_needed - pocket_money
counter += 1
if datetest == birthday or datetest == christmas:
money_needed = money_needed - 200
print(counter)

How to solve the weekday function problem Python

I am very new to Python and we were told to write the weekday function without any modules like e.g. daytime etc.
But it doesn't work and i am not sure where is a problem
def weekDay (day,month,year):
global y0
global m0
global x
y0 = 0
m0 = 0
day,month,year = int(input("Enter a day: "))
month = int(input("Enter a month: "))
year = int(input("Enter a year:"))
a = (day + x + (31 * m0) // 12) % 7
for m0 in a:
m0 = month + 12 * ((14 - month) // 12) - 2
for x in a:
x = y0 + y0 // 4 - y0 // 100 + y0 // 400
for y0 in x:
y0 = year - ((14 - month) // 12)
if a == 0:
print("Sunday")
elif a == 1:
print("Monday")
elif a == 2:
print("Tuesday")
elif a == 3:
print("Wednesday")
elif a == 4:
print("Thursday")
elif a == 5:
print("Friday")
else:
print("Error")
return weekDay(a)
'''
here is the formula we were given:
[![formula][1]][1]
[1]: https://i.stack.imgur.com/iBv30.png
This should help:
>>> import datetime
>>> now = datetime.datetime.now()
>>> now.strftime('%A')
'Friday'
>>>
Global variables not defined anywhere and I am not able to understand the logic you are trying to write. So written a function based on a aptitude trick.
def weekday(day,month,year):
"""
This function is written based upon aptitude trick
to obtain day from given a date.
Input date example : 15-5-2020
Link for logic : https://www.youtube.com/watch?v=rJ0_GWDTdD4
"""
# for different months we are assigning specific number to that month
months = {1:1, 2:4, 3:4, 4:0, 5:2, 6:5, 7:0, 8:3, 9:6, 10:1, 11:4, 12:6}
# assigning days to a number
day_name = {1:'Sunday', 2:'Monday', 3:'Tuesday', 4:'Wednesday', 5:'Thursday',
6:'Friday', 0:'Saturday'}
# to get the year in between 1600 and 2000. since we are assiging values
# for the years also
while year not in range(1600,2000):
if year>2000:
year-=400
if year<1600:
year+=400
# assigning values to years
if year in range(1600,1700):
yr = 6
if year in range(1700,1800):
yr = 4
if year in range(1800,1900):
yr = 2
if year in range(1900,2000):
yr = 0
# assigning last two numbers of year to last
first = year//100
last = year - (first * 100)
# obtaining remainder
res = (day + months[month] + yr + last + (last//4))%7
#returning the day_name
return day_name[res]
day,month,year = list(map(int,input("Enter date in format dd-mm-yyyy : ").split('-')))
print(weekday(day,month,year))
Hope, you are satisfied with logic.

finding astrology signs according to your month and date, simpler way to do it? instead of 12 if function

if month == 12:
if 0 < date < 23:
return 'SAG'
if 23 <= date < 32:
return 'CAP'
if month == 1:
if 0 < date < 21:
return 'CAP'
if 21 <= date < 32:
return 'AQU'
if month == 2:
if 0 < date < 20:
return 'AQU'
if 20 <= date < 30:
return 'PIS'
if month == 3:
if 0 < date < 21:
return 'PIS'
if 21 <= date < 32:
return 'ARI'
I am looking for a simpler and more effective way of completing my function of finding astrological sign according to month and date, is there a more effective method or is using 12 if loops a must?
You're right to think there's a better way. Use the datetime package. Set up a list of start dates and check the appropriate range for the given date. Since Capricorn spans the calendar year, you'll have two entries for that one:
import datetime
from datetime import date
signs = [ # start date, abbreviation
(date(month=1, day=1), "CAP"),
(date(month=1, day=20), "AQU"),
(date(month=2, day=18), "PIC"),
...
(date(month=12, day=19), "CAP"),
(date(month=12, day=31), "end of year"),
]
Now, you build a date from the given month and year. Iterate through the list, looking for the a given date being greater than the current date, and less than the next one. When you find that entry, you report/return the sign abbreviation.
Does that get you moving?
Dates are always tough to work with and mapping the lunar calendar to the solar calendar present special problems. It becomes easier if you approach it from a days in the year problem instead of a dates problem.
import numpy as np
from datetime import datetime as dt
def getSign(birthDate):
#get day of year of birth
dayOfBirth = (birthDate - dt(birthDate.year, 1, 1)).days
#adjust for leap years
if birthDate.year%4==0 and dayOfBirth > 60:
dayOfBirth -= 1
#build dict of max day for each sign. capricorn is set twice due to straddling of solar year
signs = {20:'Capricorn', 49:'Aquarius', 79:'Pisces', 109:'Aries', 140:'Taurus', 171:'Genini', 203:'Cancer', 234:'Leo', 265:'Virgo', 295:'Libra', 325:'Scorpio', 355:'Sagitarius', 365:'Capricorn'}
#create numpy array of maximum days
daysArray = np.array(list(signs.keys()))
#get sign max days closest to but larger than dayOfBirth
maxDayCount = min(daysArray[daysArray >= dayOfBirth])
return signs[maxDayCount]
>>> getSign(dt(2000, 3, 22))
'Aries'
>>> getSign(dt(2000, 1, 1))
'Capricorn'
>>> getSign(dt(2000, 12, 22))
'Sagitarius'
>>> getSign(dt(2000, 12, 31))
'Capricorn'

Making a time adding function in python

I'm trying to build a function that recieves a date and adds days, updating everything in case it changes, so far i've come up with this:
def addnewDate(date, numberOfDays):
date = date.split(":")
day = int(date[0])
month = int(date[1])
year = int(date[2])
new_days = 0
l = 0
l1 = 28
l2 = 30
l3 = 31
#l's are the accordingly days of the month
while numberOfDays > l:
numberOfDays = numberOfDays - l
if month != 12:
month += 1
else:
month = 1
year += 1
if month in [1, 3, 5, 7, 8, 10, 12]:
l = l3
elif month in [4, 6, 9, 11]:
l = l2
else:
l = l1
return str(day) + ':' + str(month) + ':' + str(year) #i'll deal
#with fact that it doesn't put the 0's in the < 10 digits later
Desired output:
addnewDate('29:12:2016', 5):
'03:01:2017'
I think the problem is with either the variables, or the position i'm using them in, kinda lost though..
Thanks in advance!
p.s I can't use python build in functions :)
Since you cannot use standard library, here's my attempt. I hope I did not forget anything.
define a table for month lengths
tweak it if leap year detected (every 4 year, but special cases)
work on zero-indexed days & months, much easier
add the number of days. If lesser that current month number of days, end, else, substract current month number of days and retry (while loop)
when last month reached, increase year
add 1 to day and month in the end
code:
def addnewDate(date, numberOfDays):
month_days = [31,28,31,30,31,30,31,31,30,31,30,31]
date = date.split(":")
day = int(date[0])-1
month = int(date[1])-1
year = int(date[2])
if year%4==0 and year%400!=0:
month_days[1]+=1
new_days = 0
#l's are the accordingly days of the month
day += numberOfDays
nb_days_month = month_days[month]
done = False # since you don't want to use break, let's create a flag
while not done:
nb_days_month = month_days[month]
if day < nb_days_month:
done = True
else:
day -= nb_days_month
month += 1
if month==12:
year += 1
month = 0
return "{:02}:{:02}:{:04}".format(day+1,month+1,year)
test (may be not exhaustive):
for i in ("28:02:2000","28:02:2004","28:02:2005","31:12:2012","03:02:2015"):
print(addnewDate(i,2))
print(addnewDate(i,31))
result:
02:03:2000
31:03:2000
01:03:2004
30:03:2004
02:03:2005
31:03:2005
02:01:2013
31:01:2013
05:02:2015
06:03:2015
of course, this is just for fun. Else use time or datetime modules!

Categories

Resources