0

I'm new to python and I wanted to know why my program is not working. The error is "IndexError: list index out of range" for line 23 (This program is for my best friend's birthday that's tomorrow)

import datetime
import tkinter
from tkinter import *

t = Tk()
t.resizable(0, 0)
t.title("Sana's birthday!!!")
t.geometry('200x200')

current_date = datetime.date.today().strftime('%Y-%m-%d')
current_date_lst = current_date.split('-')

l1 = Label(t, text='Sana enter your birthday in yyyy-mm-dd format:').grid(row=1, column=1)
l2 = Label(t, text='Name of your birthday legend?:').grid(row=2, column=1)

b_date = tkinter.Entry(t)
b_date.grid(row=1, column=2)
name = tkinter.Entry(t)
name.grid(row=1, column=2)

b_date = b_date.get().split( '-' )

if current_date_lst[1] == b_date[1] and current_date_lst[2] == b_date[2]:
    age = int(current_date_lst[0]) - int(b_date[0])
    ordinal_suffix = {1: 'st', 2:'nd', 3:'rd', 11:'th', 12:'th', 13:'th'}.get(age % 10 if not 10<age<=13 else age % 14, 'th')
    print(f" It's {name}'s {age}{ordinal_suffix} Birthday!")
else:
    print('Sorry, today is not your birthday:(')

mainloop()

The error:

if current_date_lst[1] == b_date[1] and current_date_lst[2] == b_date[2]:
IndexError: list index out of range
Yangelixx
  • 53
  • 9

2 Answers2

1

There are two problems with your code:

  • When doing b_date.get().split( '-' ), no text has been entered on entry yet, so you always get an empty string, from here the IndexError
  • b_date and name have been both gridded on row 1, column 2. Thus, even if you think you are writing on b_date entry, you are actually writing on name entry.

Second problem is trivially solved by name.grid(row=2, column=2). To solve first problem, instead, you need to ensure entry is only read after some text has been written.

One possible solution: force user to push a button after having entered some text. An approach I like more: for each character entered, check if string is ok and do something if it is.

Here some sample code:

import datetime
import tkinter
from tkinter import *

t = Tk()
t.resizable(0, 0)
t.title("Sana's birthday!!!")
t.geometry('200x200')

current_date = datetime.date.today().strftime('%Y-%m-%d')
current_date_lst = current_date.split('-')

l1 = Label(t, text='Sana enter your birthday in yyyy-mm-dd format:').grid(row=1, column=1)
l2 = Label(t, text='Name of your birthday legend?:').grid(row=2, column=1)

b_date = tkinter.Entry(t)
b_date.grid(row=1, column=2)
name = tkinter.Entry(t)
name.grid(row=2, column=2)

t.bind("<KeyRelease>", lambda e: show_string(b_date, name))

def show_string(b_date, name):
    
    b_date = b_date.get().split( '-' )
    name = name.get()
    
    if len(b_date)==3:
        if current_date_lst[1] == b_date[1] and current_date_lst[2] == b_date[2]:
            age = int(current_date_lst[0]) - int(b_date[0])
            ordinal_suffix = {1: 'st', 2:'nd', 3:'rd', 11:'th', 12:'th', 13:'th'}.get(age % 10 if not 10<age<=13 else age % 14, 'th')
            print(f"It's {name}'s {age}{ordinal_suffix} Birthday!")
        else:
            print('Sorry, today is not your birthday:(')

mainloop()

What is happening:

  • You bind key pressed (actually key released, to ensure you are looking for the actual entered string) to a checker function show_string. See how to bind events to functions in tkinter, such as this answer
  • You split your string as usual
  • You ensure to only continue with your elaboration if string matches a given format. Trivial approach: ensure there are at least two "-" characters. Best approach: check if string is in format "yyyy-mm-dd"
  • Note that you were also printing name. You should print name.get() instead. Furthermore, you are printing it on the console, while you might be interested into updating a label in tkinter instead

Good luck and happy birthday to your friend

ALai
  • 739
  • 9
  • 18
0

So at this line in your program: b_date = b_date.get().split( '-' ) your GUI is not running, so b_date is likely an empty list.

You may need to add a Button to trigger the code which does this splitting, and testing.

Also note that any print() functions will print to the terminal and not on the GUI.

quamrana
  • 37,849
  • 12
  • 53
  • 71