Search code examples
pythonpython-3.xpython-2.7tkintertkinter-entry

providing user input tkinter


I have a scenario where I am uploading a text file then providing a user input and then according to the user input processing further.

Sample file :

DOWN 07.11.2016 08:21:33 - 07.11.2016 08:22:33
UP   07.11.2016 09:41:07 - 09.11.2016 09:20:33
DOWN 09.11.2016 08:26:33 - 09.11.2016 08:35:33
UP   09.11.2016 08:23:33 - 09.11.2016 08:25:33
DOWN 09.11.2016 08:36:33 - 09.11.2016 08:38:33
DOWN 10.11.2016 08:36:33 - 10.11.2016 08:38:33

code :

try:
    import Tkinter as Tk
    import tkFileDialog as fileDialog
except ImportError:
    import tkinter as Tk
    fileDialog = Tk.filedialog

import datetime

def user_input():
current_date = my_entry.get()

def processText(lines):
    total = 0
    start = None
    for k, line in enumerate(lines):
        direction, date1, time1, _, date2, time2 = line.split()
        if direction != "Down": continue
        if start==None: start = date1 + ' ' + time1
        # 1
        D1, M1, Y1 = date1.split('.')
        h1, m1, s1 = time1.split(':')
        # 2
        D2, M2, Y2 = date2.split('.')
        h2, m2, s2 = time2.split(':')
        # Timestamps
        t1 = datetime.datetime(*map(int, [Y1, M1, D1, h1, m1, s1])).timestamp()
        t2 = datetime.datetime(*map(int, [Y2, M2, D2, h2, m2, s2])).timestamp()
        total += (t2-t1)
    return total, start

def openFile():
    filename = fileDialog.askopenfilename()

    fileHandle = open(filename, 'r')
    down, start = processText(fileHandle.readlines())
    txt = "Total Downtime is {0} min from {1}".format(down//60, start)
    textVar.set(txt)

    fileHandle.close()

root = Tk.Tk()

button = Tk.Button(root, text="Open", command=openFile)
button.grid(column=1, row=1)

textVar = Tk.StringVar(root)
label = Tk.Label(root, textvariable=textVar)
label.grid(column=1, row=2)

root.mainloop()

Above gives me output as Total Downtime is

12 min from 07.11.2016 08:21:33

but here I am trying to introduce the user input for DATE and for example if I want to get the downtime from 09.11.2016 then it should prompt me for selecting a date and output(total downtime) should be from the selected date.

Any help would be great!!

EDIT 1 (Added o/p):

traceback :

Exception in Tkinter callback
Traceback (most recent call last):
 File "C:\Program Files (x86)\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
 File "C:/Users/angelina/Desktop/test2/tinkteruser.py", line 34, in read_data
t1 = datetime.datetime.strptime(dt1, "%d.%m.%Y %H:%M:%S")
File "C:\Program Files (x86)\Python36-32\lib\_strptime.py", line 565, in     _strptime_datetime
tt, fraction = _strptime(data_string, format)
File "C:\Program Files (x86)\Python36-32\lib\_strptime.py", line 362, in _strptime
(data_string, format))
ValueError: time data 'able   22.06.2017 1' does not match format  '%d.%m.%Y %H:%M:%S

Solution

  • You can read file once and calculate for different dates.

    enter image description here

    btw: as extension it could get few dates in Entry (separated by space or comma) and calculate total for every date, or calculate in range of two dates


    In read_data() it loads all data and convert to datetimes using

    datetime.datetime.strptime(date1 + ' ' + time1, "%d.%m.%Y %H:%M:%S")
    

    In calculate it get data from Entry and execute processText() with data from file and date from entry.

    It convert string with data from Entry into datetime. String may have incorrect date or in unexpeted format so I use try/except.

    It use t1 <= selected_date to compare two datetime.

    It uses (t2-t1).seconds to get seconds between two dates (without using timestamp()). It could do this even in read_data().

    Full code:

    Problem can be except Exception as ex: which is incorrect in Python 2.

    try:
        import Tkinter as Tk
        import tkFileDialog as fileDialog
    except ImportError:
        import tkinter as Tk
        import tkinter.filedialog as fileDialog
    
    import datetime
    
    
    
    def read_data():
        '''
        Read data from file and convert to list with datetime
        which can be used to calculate time and display.
        '''
        global data
    
        filename = fileDialog.askopenfilename()
    
        if filename:
            # read all lines
            with open(filename) as fileHandle:
                lines = fileHandle.readlines()
    
            # convert to `datetime` (not `timestamp`)
            data = []        
            for line in lines:
                direction, date1, time1, _, date2, time2 = line.split()
    
                t1 = datetime.datetime.strptime(date1 + ' ' + time1, "%d.%m.%Y %H:%M:%S")
                t2 = datetime.datetime.strptime(date2 + ' ' + time2, "%d.%m.%Y %H:%M:%S")
    
                data.append([direction, t1, t2])
    
            print(data)
    
    
    def processText(lines, selected_date):
    
        total = 0
        start = None
    
        # if there is `selected_date` then convert to `datetime`
        if selected_date:
            try:
                selected_date = datetime.datetime.strptime(selected_date, "%d.%m.%Y")
            except Exception as ex:
                print("ERROR:", ex)
                selected_date = None
    
        # calculate time
        for direction, t1, t2 in lines:
    
            if direction == "DOWN":
    
                # if `selected_date` then filter times
                if selected_date and t1 <= selected_date:
                    continue
    
                if not start:
                    start = t1
    
                total += (t2-t1).seconds//60
    
        return total, start.strftime("%d.%m.%Y %H:%M:%S")
    
    def calculate():
    
        current_date = entry.get().strip()
    
        down, start = processText(data, current_date)
    
        txt = "Total Downtime is {0} min from {1}".format(down, start)
        textVar.set(txt)
    
    # --- main ---
    
    data = None # to keep data from file
    
    # -
    
    root = Tk.Tk()
    
    button = Tk.Button(root, text="Open", command=read_data)
    button.grid(column=1, row=1)
    
    textVar = Tk.StringVar(root)
    
    label = Tk.Label(root, textvariable=textVar)
    label.grid(column=1, row=2)
    
    entry = Tk.Entry(root)
    entry.grid(column=1, row=3)
    
    button2 = Tk.Button(root, text="Calculate", command=calculate)
    button2.grid(column=1, row=4)
    
    root.mainloop()
    

    EDIT: other changes (keep previous version for comparing)

    Now it calculate (t2-t1).seconds in read_data and it keeps it in data

    And it convert into minutes after it adds all seconds so it can gives few minutes more.

    Now it can calculate for many dates in entry (separated by comma).

    It also uses slicing to get elements from lines.
    I assumed that all data has format like in sample file.

    DOWN 07.11.2016 08:21:33 - 07.11.2016 08:22:33
    UP   07.11.2016 09:41:07 - 09.11.2016 09:20:33
    DOWN 09.11.2016 08:26:33 - 09.11.2016 08:35:33
    UP   09.11.2016 08:23:33 - 09.11.2016 08:25:33
    DOWN 09.11.2016 08:36:33 - 09.11.2016 08:38:33
    DOWN 10.11.2016 08:36:33 - 10.11.2016 08:38:33
    

    EDIT: it seems file can have longer values than "DOWN" and "UP " so slicing will not work so I use again split() instead of slicing

    enter image description here

    try:
        import Tkinter as Tk
        import tkFileDialog as fileDialog
    except ImportError:
        import tkinter as Tk
        import tkinter.filedialog as fileDialog
    
    import datetime
    
    
    
    def read_data():
        '''
        Read data from file and convert to list with datetime
        which can be used to calculate time and display.
        '''
        global data
    
        filename = fileDialog.askopenfilename()
    
        if filename:
            # read all lines
            with open(filename) as fileHandle:
                lines = fileHandle.readlines()
    
            # convert to `datetime` (not `timestamp`)
            data = []        
            for line in lines:
                #direction = line[:4].strip()
                #dt1 = line[5:24]
                #dt2 = line[27:46]
    
                direction, d1, t1, _, d2, t2 = line.split()
                dt1 = d1 + ' ' + t1
                dt2 = d2 + ' ' + t2 
    
                t1 = datetime.datetime.strptime(dt1, "%d.%m.%Y %H:%M:%S")
                t2 = datetime.datetime.strptime(dt2, "%d.%m.%Y %H:%M:%S")
    
                seconds = (t2-t1).seconds
    
                data.append([direction, t1, t2, seconds])
    
            print(data)
    
    
    def processText(lines, selected_date):
    
        total = 0
        start = None
    
        print(selected_date)
        # if there is `selected_date` then convert to `datetime`
        if selected_date:
            try:
                selected_date = datetime.datetime.strptime(selected_date, "%d.%m.%Y")
            except AttributeError as ex:
                print("ERROR:", ex)
                selected_date = None
    
        # calculate time
        for direction, t1, t2, seconds in lines:
    
            if direction == "DOWN":
    
                # if `selected_date` then filter times
                if selected_date and t1 <= selected_date:
                    continue
    
                if not start:
                    start = t1.strftime("%d.%m.%Y %H:%M:%S")
    
                total += seconds
    
        # convert to minutes after summing all second
        total = total//60
    
        return total, start
    
    def calculate():
    
        all_dates = entry.get().split(',')
        print(all_dates)
        all_dates = [date.strip() for date in all_dates]
    
        txt = ''
    
        for current_date in all_dates:
            down, start = processText(data, current_date)
            txt += "Total Downtime is {0} min from {1}\n".format(down, start)
    
        textVar.set(txt)
    
    # --- main ---
    
    data = None # to keep data from file
    
    # -
    
    root = Tk.Tk()
    
    button = Tk.Button(root, text="Open", command=read_data)
    button.grid(column=1, row=1)
    
    textVar = Tk.StringVar(root)
    
    label = Tk.Label(root, textvariable=textVar)
    label.grid(column=1, row=2)
    
    entry = Tk.Entry(root)
    entry.grid(column=1, row=3)
    
    button2 = Tk.Button(root, text="Calculate", command=calculate)
    button2.grid(column=1, row=4)
    
    root.mainloop()