Day 2 of 100 - Datetime and Timedelta Day 2 of 3

Datetime and Timedelta Day 2 of 3

Day 2 of 100

Today was more about figuring out really simple things (like lists and strings) as much as it was about dates and datetime. The project for today was to write two functions for a log file that looks like this:

ERROR 2014-07-03T23:24:31 supybot Invalid user dictionary file, resetting to empty.
ERROR 2014-07-03T23:24:31 supybot Exact error: IOError: [Errno 2] No such file or directory: 'conf/users.conf'
ERROR 2014-07-03T23:24:31 supybot Invalid channel database, resetting to empty.
ERROR 2014-07-03T23:24:31 supybot Exact error: IOError: [Errno 2] No such file or directory: 'conf/channels.conf'
WARNING 2014-07-03T23:24:31 supybot Couldn't open ignore database: [Errno 2] No such file or directory: 'conf/ignores.conf'
INFO 2014-07-03T23:27:51 supybot Shutdown initiated.
...

The first function was supposed to return a datetime object when one of the lines from the log file is passed to it. The approach I took was pretty ham-fisted and does not really represent dynamic code. I created two lists, one to store the elements of the line populated using the split() method to split the line into a list using the space as a delimiter. The second list was an empty one to store the elements I needed to create the datetime object. To get the elements I needed into the list to create the datetime object I had to hard code splitting the element that contained the timestamp at specific character counts. The challenge for me was that the timestamp element was delimited by multiple characters: "-" for the date, "T" between the date and time, and ":" between the time. I could have split the timestamp multiple times and appended it to the list of elements, which might have made the code slightly more dynamic but more complex and probably just as long. Then, I have to convert each element to ints when creating the datetime object, which I also know is not great code - but it worked and it passed the tests. I had already spent multiple hours watching YouTube and reading blogs to remind me how to use strings and lists. Anyway, here is the completed function:

def convert_to_datetime(line):
    datetime_list = []
    loglines_split = (str.split(line))
    datetime_list.append(loglines_split[1][0:4])
    datetime_list.append(loglines_split[1][5:7])
    datetime_list.append(loglines_split[1][8:10])
    datetime_list.append(loglines_split[1][11:13])
    datetime_list.append(loglines_split[1][14:16])
    datetime_list.append(loglines_split[1][17:19])
    return datetime(int(datetime_list[0]), int(datetime_list[1]), int(datetime_list[2]),
             int(datetime_list[3]), int(datetime_list[4]), int(datetime_list[5]))

The second problem was similar to the first. I had to iterate over the logfile and identify how much time had passed between the first and last shutdown event. I used much the same code from the first function, adding a conditional to check if the event matched Shutdown initiated.. If the event matched, then the timestamp would be written to an empty list and finally, the first and second elements of the events list would be subtracted to give the timedelta between the events. Again, I hard coded the list objects to return the timedelta and probably should have used the first and last elements, but this worked because the sample log file had only two shutdown events:

    shutdown_events = []
    for line in loglines:
        loglines_split = line.split(" ", 3)
        if loglines_split[3] == 'Shutdown initiated.\n':
            # print('event')
            shutdown_list = []
            shutdown_list.append(loglines_split[1][0:4])
            shutdown_list.append(loglines_split[1][5:7])
            shutdown_list.append(loglines_split[1][8:10])
            shutdown_list.append(loglines_split[1][11:13])
            shutdown_list.append(loglines_split[1][14:16])
            shutdown_list.append(loglines_split[1][17:19])
            shutdown_events.append(datetime(int(shutdown_list[0]), int(shutdown_list[1]),
                                            int(shutdown_list[2]), int(shutdown_list[3]),
                                            int(shutdown_list[4]), int(shutdown_list[5])))
    return(shutdown_events[1] - shutdown_events[0])

Today is only day two and I'm already spending lots of time on background, basic elements of Python which are just not at the front of my brain at this time, having not coded much for a long time. It was also an example of being done, rather than spending more time getting the to best or most clever code. I know it can be done better and I would bet a lot of money there are better functions built into Python and certainly packages that would do this for me, but it still feels good to come up with my own solution that works, even if it isn't the best.