user9119815
user9119815

Reputation:

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

Upvotes: 0

Views: 556

Answers (1)

furas
furas

Reputation: 142641

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()

Upvotes: 3

Related Questions