0

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.09.2016 08:21:33 - 07.09.2016 08:23: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:46: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:41:33
DOWN 10.11.2016 08:36:33 - 10.11.2016 08:39:33

code :

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

Above code prompts me to select date in format Date1.Month1.Year1,Date2.Month2.Year2 ... (depending on the number input for date.)

and returns output as :

 Total Downtime is x min from date1.month1.year1 xx:xx:xx(time1)
 Total Downtime is y min from date2.month2.year2 yy:yy:yy(time2)

Here I have the details of downtime in mins and i want to convert that in percentage till date. For example ->

user input :

1.9.2016,1.11.2016,1.1.2016

Output :

 Total Downtime is 30 min from 1.9.2016 08:21:33 & Availability percentage from selected date to till date : xx.xxx% 
 Total Downtime is 28 min from 1.11.2016 08:26:33 & Availability percentage from selected date to till date : yy.yyy%
 Total Downtime is 30 min from 1.11.2016 08:26:33 & Availability percentage from selected date to till date : zz.zzz%

logic behind availability calculation would be

total number of min down from date(which is retrieved)/total number of min till date * 100

I am stuck in this part, Is this achievable? Any help would be great!!

3
  • yes it achievable - you have to add all minutes first. Do you have problem to add minutes ? BTW: if you execut processText() with None instead of selected_date then you get "total number of all minutes". And then you can substract "total minutes from selected date" to get "total minutes till selected date" Commented Dec 26, 2017 at 19:50
  • You should provide a Minimal, Complete, and Verifiable example instead of your entire code. Commented Dec 26, 2017 at 19:52
  • Yes , I don't know how should I proceed to get total number of minutes till selected date. Commented Dec 26, 2017 at 19:57

1 Answer 1

1

If you run processText() with None instead of date then you get total number of minutes when it was down

total_down, start = processText(data, None)

and you can use it to calculate percentage.

percentage = (down/total_down) * 100

and you can use string formatting {:.2f} to display only two digits after dot

def calculate():

    all_dates = entry.get().split(',')
    print(all_dates)
    all_dates = [date.strip() for date in all_dates]

    # calculate total number of minutes when it was down
    total_down, start = processText(data, None) # <-- None

    print('total_down:', total_down)

    txt = ''

    for current_date in all_dates:
        down, start = processText(data, current_date)

        # calculate percetage
        percentage = (down/total_down) * 100

        # use string formatting {:.2f} to display only two digits after dot
        txt += "Total Downtime is {} min from {} ({:.2f}%)\n".format(down, start, percentage)

    textVar.set(txt)

enter image description here


If you want total number of minutes when it was down or up then you have to change processText and add new parameter (ie. word) which will check if direction is DOWN or UP or both (word = None)

def processText(lines, selected_date, word="DOWN"):

    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 not word or word == direction:

            # 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]

    # calculate total number of minutes when it was down and up
    total_down, start = processText(data, None, None)

    print('total_down:', total_down)

    txt = ''

    for current_date in all_dates:
        down, start = processText(data, current_date, "DOWN")
        percentage = (down/total_down) * 100
        txt += "Total Downtime is {} min from {} ({:.2f}%)\n".format(down, start, percentage)

    textVar.set(txt)
Sign up to request clarification or add additional context in comments.

7 Comments

see code - it calculate total_down and later it uses this value to calculate percentage and it uses {:.2f} to display percentage with two digits after dot.
here i have selected date > 12.9.2016 This provides down time as 2.07% but according to calculation logic it should provide 99.07%
screen shot that you have attached is for the 2nd answer or first answer ?
screenshot is for first version - so I put it after first code.
second version calculate total number of minutes when it was down and up - so it gives smaller value. But if you use word "DOWN" in total_down, start = processText(data, None, "DOWN") then you can get the same result. Second version is more universal and it is useful if you want also to calculate time when it was UP.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.