Difficulties with implementing persian calendar rules with Python - python

I am writing a code that somehow resembles the Persian calendar. there are 3 drop down lists for year, month and day. Here are the rules I'd like to include:
Months 1 to 6 have 31 days
Months 7 to 11 have 30 days
Month 12 has 29 days every 4 years
12th month has 30 days (leap year)
If the user chooses one of the (1 - 2 - 3 - 4 - 5 - 6) months, the drop down list for days must have 31 days.
If the user chooses one of the (7 - 8 - 9 - 10 - 11 ) months, the drop down list for days must have 30 days.
If the user chooses the 12th month, the drop down list for days must have 29 days.
If the user chooses one of (1375 – 1379 – 1383 – 1387 – 1391 – 1395) year and if he chooses the 12th month, the drop down list for days must have 30 days.
Here is the code I have written so far but my code doesn't work, please help me with it.
from tkinter import *
x=StringVar()
def ok():
if months == months[0:5]:
x = dayoptions1
if months == months[6:10]:
x = dayoptions2
if months == months[11] and years == 1375 or 1379 or 1383 or 1387 or 1391 or 1395:
x = dayoptions3
root = Tk()
label1 = Label(root, text="year",width=15)
label1.grid(row=0, column=0)
yearoptions = ["1397", "1396","1395","1394","1393","1392","1391","1390","1389","1388","1387","1386","1385","1384","1383","1382","1381","1380","1379","1378","1377","1376","1375"]
yearvariable = StringVar(root)
yearvariable.set(yearoptions[0])
years = OptionMenu(root, yearvariable, *yearoptions)
years.grid(row=0,column=1,padx=5, pady=5)
label2 = Label(root, text="month",width=15)
label2.grid(row=0, column=2)
monthoptions = ["1", "2","3","4","5","6","7","8","9","10","11","12"]
monthvariable = StringVar(root)
monthvariable.set(monthoptions[0])
months = OptionMenu(root, monthvariable, *monthoptions)
months.grid(row=0,column=3,padx=5, pady=5)
label1 = Label(root, text="day",width=15)
label1.grid(row=0, column=4)
dayoptions1 = ["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","31"]
dayoptions2 = ["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"]
dayoptions3 = ["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"]
dayvariable = StringVar(root)
dayvariable.set("1")
days = OptionMenu(root, dayvariable, *x)
days.grid(row=0,column=5,padx=5, pady=5)
root.mainloop()

Okay I don't tkinter, so I wrote a function but it works. Days depends on what month & year user choose. So scenario is, user choose 1383 - 12 (Year 1383 of Month 12), you need to find if 1383 is a leap year and then fill up the day list with 30 days, or else it would be 29 days. If use choose between month 1 to 6, fill the array with 31 days and the rest of the month has 30 days. I have written a short helper function to check this out and I think it works.
def persian_calender():
user_input = input("year - month:: ")
date_list = user_input.split("-")
leap_year = [1375, 1379 ,1383, 1387 ,1391 ,1395]
year = int(date_list[0])
month = int (date_list[1])
if year in leap_year:
is_leap = True
else:
is_leap = False
if month >= 1 and month <= 6:
number_of_days = "31"
elif month >= 7 and month <= 11:
number_of_days = "30"
else:
if is_leap:
number_of_days = "30"
else:
number_of_days = "29"
print ("Year: " + date_list[0] + " Month: "+ date_list[1] + " Days: "
+ number_of_days)
Check the code file in here
Hope it helps. Cheers!
[Edit 2]
You wrote a helper function Ok that finds out what month it is. Instead writing your list manually, just declare the number of days in there. When you want to or it's time to fill up the drop down list of days, run and fill up the list with equivalent number of days. Do I make sense?!

Related

How can I price Digital option with short maturity

I am trying to price a Digital Call option using Quantlib Python package, but I have an inconsistent result. I am trying to price a deep ITM option with a 1 day maturity. The thing is that it returns me 0, which doesn't make sense. Could you please help me?
def Digital_Call(s0: float,
strike: float,
risk_free: float,
vol: float,
today: datetime,
maturity: datetime,
cash_payoff: float):
"Output: option_npv"
dividend_yield = 0
riskFreeTS = ql.YieldTermStructureHandle(ql.FlatForward(today, risk_free, ql.ActualActual()))
dividendTS = ql.YieldTermStructureHandle(ql.FlatForward(today, dividend_yield, ql.ActualActual()))
volatility = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(today, ql.NullCalendar(), vol, ql.ActualActual()))
initialValue = ql.QuoteHandle(ql.SimpleQuote(s0))
process = ql.BlackScholesMertonProcess(initialValue, dividendTS, riskFreeTS, volatility)
engine = ql.AnalyticEuropeanEngine(process)
option_type = ql.Option.Call
option = ql.VanillaOption(ql.CashOrNothingPayoff(option_type, strike, cash_payoff), ql.EuropeanExercise(maturity))
option.setPricingEngine(engine)
return option
s0=150
strike = 14.36
risk_free = 0.0302373913
#risk_free = 0
vol = 0.2567723271
today = datetime(2022,9,28)
maturity = datetime(2022,9,30) #it doesn't work with Maturity of both 1 & 2 days
cash_payoff = 30
It returns 0.
Thank You

how dynamically update listbox entry in Tkinter?

I am trying to update a listbox line, based on a condition, but get this error:
_tkinter.TclError: bad listbox index "Wednesday 15 April 2020 ": must be active, anchor, end, #x,y, or a number
These are the script lines. I get the same error when I use i, or tk.END with listboxMain.delete
for i, dt in enumerate(daterange(date1, date2)):
holiday = us_holidays.get(dt)
if not holiday:
holiday = ""
day, date, month, year = dt.strftime('%A %d %B %Y').split()
line = f'{day:10s} {date} {month:>10s} {year:>7} {holiday}'
if (datetime.date.today() - dt).days == 0:
TODAY_INDEX = i
listboxMain.insert(tk.END, line)
for b in list_birthdays:
if b == dt:
listboxMain.delete(i, line) <====== Error is here.
listboxMain.insert(i, line + " Birthday of ")
listboxMain.itemconfig(i, {'bg': '#999966'})
listboxMain.itemconfig(i, {'fg': '#000066'})
break
listboxMain.itemconfig(TODAY_INDEX, {'bg': '#cc9900'})
listboxMain.itemconfig(TODAY_INDEX, {'fg': '#000099'})

tkinter - Can a radio button control multiple variables?

I am writing a calendar program using the tkinter module and clicking on each day on the grid will print out the current day's date (month/day/year). However, I also want to add another section at the bottom that will show what day of the year it is. Like this:
For example, January 1, 2020 would be the first day of the year, March 20 will be the 80th day of the year, etc. I want my radio buttons to be able to control both of these variables, the date as a string, and the day of the year as an integer. Is this possible?
strDate = StringVar()
labelDate = Label(frameDay, textvariable=strDate, width=28,
font=("Consolas", "15", "bold")).grid(row=1, column=1)
# Creating the calendar grid
while day <= self.returnMaxDay():
currentDay = Date(self.month, day, self.year)
radDay = Radiobutton(frameCalendar, text=str(day),
font=("Consolas", "15", "bold"), indicatoron=0, width=4, height=1,
variable=strDate, value=str(currentDay.returnDayName()) + ", "
+ str(currentDay.returnMonthName()) + " "
+ str(day) + ", " + str(currentDay.year))
radDay.grid(row=row, column=weekDay)
day += 1
weekDay += 1
if weekDay == 7:
row += 1
weekDay = 0
labelDayOfYear = Label(window, text=str(self.dayOfYear()), font=("Consolas", "20")).pack()
It is simple example which uses command= in Radiobutton to run function which changes text it three Labels.
Normally command= expect function's name without () and arguments so I use lambda to assing function with arguments.
command=lambda d=current_day:on_click(d))
I also use d=current_day to create new variable d for every function. Without d=current_day all functions would use reference to the same variable current_day and all functions would use the same (last) value in current_day.
import tkinter as tk
import datetime
# --- functions ---
def on_click(value):
print(value)
label_date['text'] = value.strftime('%a, %b %d, %Y')
label_day['text'] = value.strftime('Day: %d')
label_weekday['text'] = value.strftime('Weekday: %a')
# --- main ---
root = tk.Tk()
radiobutton_var = tk.StringVar()
year = 2020
month = 4
row = 0
for day in range(1, 32):
try:
current_day = datetime.datetime(year, month, day)
date_str = current_day.strftime('%a, %m %d, %Y')
weekday = current_day.weekday()
radiobutton_day = tk.Radiobutton(root,
text=str(day),
indicatoron=0,
variable=radiobutton_var,
value=date_str,
#value=day,
command=lambda x=current_day:on_click(x))
radiobutton_day.grid(row=row, column=weekday, sticky='we')
if weekday == 6:
row += 1
radiobutton_day['bg'] = '#faa'
except ValueError as ex:
print(ex)
break
label_date = tk.Label(root, text='?')
label_date.grid(row=10, columnspan=10)
label_day = tk.Label(root, text='Day: ?')
label_day.grid(row=11, columnspan=10)
label_weekday = tk.Label(root, text='Weekday: ?')
label_weekday.grid(row=12, columnspan=10)
root.mainloop()
BTW: I use datetime to generate dates and try/except to catch error when date is incorrect.
I also use strftime to format date - see more on page strftime.org

how to incorporate some Persian rules as drop down lists in python tkinter

I am writing a code that somehow resembles the Persian calendar. there are 3 drop down lists for year,month and day. here are the rules I'd like to include:
months 1 to 6 have 31 days
months 7 to 11 have 30 days
month 12 has 29 days
every 4 years, 12th month has 30 days(leap year)
if the user chooses on of the (1 - 2 - 3 - 4 - 5 - 6) months, the drop down list for days must have 31 days
if the user chooses on of the (7 - 8 - 9 - 10 - 11 ) months, the drop down list for days must have 30 days
if the user chooses the 12th month, the drop down list for days must have 29 days
if the user chooses one of (1375 – 1379 – 1383 – 1387 – 1391 – 1395) year and if he chooses the 12th month, the drop down list for days must have 30 days
here is the code I have written so far but my code doesn't work, please help me with it.
from tkinter import *
x=StringVar()
def ok():
if months == months[0:5]:
x = dayoptions1
if months == months[6:10]:
x = dayoptions2
if months == months[11] and years == 1375 or 1379 or 1383 or 1387 or 1391 or 1395:
x = dayoptions3
root = Tk()
label1 = Label(root, text="year",width=15)
label1.grid(row=0, column=0)
yearoptions = ["1397", "1396","1395","1394","1393","1392","1391","1390","1389","1388","1387","1386","1385","1384","1383","1382","1381","1380","1379","1378","1377","1376","1375"]
yearvariable = StringVar(root)
yearvariable.set(yearoptions[0])
years = OptionMenu(root, yearvariable, *yearoptions)
years.grid(row=0,column=1,padx=5, pady=5)
label2 = Label(root, text="month",width=15)
label2.grid(row=0, column=2)
monthoptions = ["1", "2","3","4","5","6","7","8","9","10","11","12"]
monthvariable = StringVar(root)
monthvariable.set(monthoptions[0])
months = OptionMenu(root, monthvariable, *monthoptions)
months.grid(row=0,column=3,padx=5, pady=5)
label1 = Label(root, text="day",width=15)
label1.grid(row=0, column=4)
dayoptions1 = ["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","31"]
dayoptions2 = ["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"]
dayoptions3 = ["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"]
dayvariable = StringVar(root)
dayvariable.set("1")
days = OptionMenu(root, dayvariable, *x)
days.grid(row=0,column=5,padx=5, pady=5)
root.mainloop()

difference between two dates python [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
from datetime import date
future = input("Enter a date(dd/mm/yyyy): ")
daystring = future[0:2]
monthstring = future[3:5]
yearstring = future[6:10]
today = (date.today())
month = date.today().month
year = date.today().year
day = date.today().day
if monthstring == "01" or "03" or "05" or "07" or "08" or "10" or "12":
if daystring > "31":
print("Invalid Date Entered")
if monthstring == "04" or "06" or "09" or "11":
if daystring > "30":
print("Invalid Date Entered")
months = ["Jan", "Feb", "Mar", "Apr", "May", "June",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
daysinmonth = [31, 29, 31, 30, 31, 30, 31, 31, 30,
31, 30, 31]
if future < today or monthstring > "12":
print("Invalid Date Entered")
else:
layout = "%d/%m/%Y"
a = datetime.strptime(future, layout)
b = datetime.strptime(today, layout)
delta = a - b
print ("The difference between the inputted date and todays date is: ",delta.days, "days")
This code is to ask the user to input a date in the future and then the code should use that input and subtract the current date from it.
For example, today is 01/11/2014 and if the user inputs 03/11/2014 the output should be that the difference is 2 days.
However, I'm getting an error every time I input the future date.
import dateutil.parser as parser
import datetime
date1 = parser.parse(input("Enter Date:"))
print( (datetime.datetime.now() - date1).days )
dateutil is very good at parsing natural date strings ...
you will probably need to install dateutil
easy_install python-dateutil
if you want to not use dateutil as mentioned you can use strptime
def get_user_date(prompt="Enter Date:"):
while True:
try:
return datetime.datetime.strptime("%m/%d/%y",input(prompt))
except ValueError:
print( "Invalid Input!" )
this code I think will work in python 3
There are different things to be considered. Try to take in considerations these points
Check if the user is entering right datetime. You can use regular expression to do that. You can use RE module.
mat=re.match('(\d{2})[/](\d{2})[/](\d{4})$', str(future))
You should filter values between 1-12 for months, and between 1-31 for days. Then distinguish between months, and don't forget February in both cases (leap year or no). You can use calender module to check that.
t= calendar.monthrange(int(yearstring), 2) # This is to check if February has 29 or 28 (is leap year or no), you can do that by checking the day number of "datetime.date (int(yearstring), 3, 1) - datetime.timedelta (days = 1)"
Then, compare between two dates, you should use right time format for every date.
a = date.datetime.strptime(future, "%d/%m/%Y").date()
b = date.datetime.strptime(today, "%Y-%m-%d").date()
delta = a-b
Your code would look like:
import datetime as date
import re
import calendar
future = input("Enter a date(dd/mm/yyyy): ")
#eg: future="02/03/2015"
#print future
mat=re.match('(\d{2})[/](\d{2})[/](\d{4})$', str(future))
if mat is None:
print("Invalid Date Entered, try to enter a date in this form(dd/mm/yyyy) ")
else:
daystring,monthstring,yearstring= mat.groups()
today= str(date.datetime.now()).split(" ")[0]
year, month, day = today.split("-")
months = ["Jan", "Feb", "Mar", "Apr", "May", "June","Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
daysinmonth = [31, 29, 31, 30, 31, 30, 31, 31, 30,31, 30, 31]
if int(daystring)>0 and int(daystring)<=31 and int(monthstring)>0 and int(monthstring) <= 12 and int(yearstring)>0:
if monthstring in ["01", "03", "05" ,"07","08","10", "12"]:
if int(daystring) > 31:
print("Invalid Date Entered - Number of days can't exceed 31.")
if monthstring in ["04","06","09","11"]:
if int(daystring) > 30:
print("Invalid Date Entered - Number of days can't exceed 31.")
if monthstring == "02":
t= calendar.monthrange(int(yearstring), 2) # This is to check if February has 29 or 28 (is leap year or no), you can do that by checking the day number of "datetime.date (int(yearstring), 3, 1) - datetime.timedelta (days = 1)"
if int(daystring) !=t: #You forget faberuary
print("Invalid Date Entered - of days can't exceed 28 or 29")
a = date.datetime.strptime(future, "%d/%m/%Y").date()
b = date.datetime.strptime(today, "%Y-%m-%d").date()
delta = a-b # The future - Today ::> to get a positive number
if delta.days >0:
print ("The difference between the inputted date and todays date is: ",delta.days, "days")
else:
print("Date is in the past")
else:
print("Invalid Date Entered")

Categories

Resources