-1

Say for example, I have the following strings and an input 4.0, which represents seconds:

John Time Made 11:05:20 in 2010
5.001 Kelly #1
6.005 Josh #8

And would like the following result:

John Time Made 11:05:24 in 2010 #Input 4.0 is added to the seconds of 11:05:20
1.001 Kelly #1 #4.0 is subtracted from the first number 5.001 = 1.001
2.005 Josh #8 #4.0 is subtracted from the first number 5.001 = 2.005

How can I recognize the hours:minutes:seconds in the first line, and #.### in the rest to add/subtract the input number?

Thank you in advance and will accept/upvote answer

Jo Ko
  • 7,225
  • 15
  • 62
  • 120
  • try with regular expressions. – Yaman Jain Mar 09 '17 at 19:27
  • What do numbers on the second and third line represent? Also time or floating point numbers? – malana Mar 09 '17 at 19:29
  • @lordingtar split and strip but couldn't find the right answers. – Jo Ko Mar 09 '17 at 19:30
  • 2
    Don't try regular expressions. You need to parsed the HH:MM:SS parts into time objects, do the math on those and convert back to the same format. – malana Mar 09 '17 at 19:31
  • @lmichelbacher just seconds, so 1.001 is 1 second and 2.005 is 2 seconds. All the lines are strings, and was thinking we should convert to float then do the calculation, and convert it back to string. – Jo Ko Mar 09 '17 at 19:35
  • @lmichelbacher Could you show so I can accept the answer as well? – Jo Ko Mar 09 '17 at 19:35
  • I realize now that what you want to do, namely increment a time counter by a number of seconds and format its value in HH:MM:SS, isn't actually covered by Python's datetime module. I'm assuming your counter should just keeping going after 23:59:59 to something like 24:00:03 or should it switch to a different format? I think you'll have to find alternative to representing this time counter (either a library that supports it or create your own). – malana Mar 09 '17 at 19:50
  • @lmichelbacher It's just an input and not an actual counter, 4.0 in the example. In the case of 23:59:59, it would just increment to the HH:MM:SS like how the clock should and be 24:00:03 in the same format. – Jo Ko Mar 09 '17 at 19:55
  • @lmichelbacher Could you please provide your answer? Thank you – Jo Ko Mar 10 '17 at 17:54

2 Answers2

0

This solution should work if your complete data has the same format as this particular sample you provided. You should have the data in the input.txt file.

val_to_add = 4

with open('input.txt') as fin:
    # processing first line
    first_line = fin.readline().strip()
    splitted = first_line.split(' ')

    # get hour, minute, second corresponding to time (11:05:20)
    time_values = splitted[3].split(':')

    # seconds is the last element
    seconds = int(time_values[-1])

    # add the value
    new_seconds = seconds + val_to_add

    # doing simple math to avoid having values >= 60 for minute and second
    # this part probably can be solved with datetime or some other lib, but it's not that complex, so I did it in couple of lines
    seconds = new_seconds % 60 # if we get > 59 seconds we only put the modulo as second and the other part goes to minute
    new_minutes = int(time_values[1]) + new_seconds // 60 # if we have more than 60 s then here we'll add minutes produced by adding to the seconds
    minutes = new_minutes % 60 # similarly as for seconds
    hours = int(time_values[0]) + new_minutes // 60

    # here I convert again to string so we could easily apply join operation (operates only on strings) and additionaly add zero in front for 1 digit numbers
    time_values[0] = str(hours).rjust(2, '0')
    time_values[1] = str(minutes).rjust(2, '0')
    time_values[2] = str(seconds).rjust(2, '0')

    new_time_val = ':'.join(time_values)# join the values to follow the HH:MM:SS format
    splitted[3] = new_time_val# replace the old time with the new one (with the value added)
    first_line_modified = ' '.join(splitted)# just join the modified list

    print(first_line_modified)

    # processing othe lines
    for line in fin:
        # here we only get the first (0th) value and subtract the val_to_add and round to 3 digits the response (to avoid too many decimal places)
        stripped = line.strip()
        splitted = stripped.split(' ')
        splitted[0] = str(round(float(splitted[0]) - val_to_add, 3))
        modified_line = ' '.join(splitted)
        print(modified_line)
giliev
  • 2,938
  • 4
  • 27
  • 47
  • Before I upvote/accept answer, could you briefly comment for clarification and learning purposes? – Jo Ko Mar 09 '17 at 20:55
  • Appreciate it! In round(float(splitted[0]) - val_to_add, 3), it shows 3 decimals but on some, if it ends with 0, it gets cut off and shows only 2. How can I make it so that even if it has trailing 0's, it still shows? – Jo Ko Mar 10 '17 at 22:33
0

Although regex was discouraged in the comments, regex can be used to parse the time objects into datetime.time objects, perform the necessary calculations on them, then print them in the required format:

# datetime module for time calculations
import datetime
# regex module
import re

# seconds to add to time
myinp = 4

# List of data strings
# data = 'John Time Made 11:05:20 in 2010', '5.001 Kelly', '6.005 Josh'

with open('data.txt') as f:
    data = f.readlines()

new_data = []

#iterate through the list of data strings
for time in data:
    try:
        # First check for 'HH:MM:SS' time format in data string
        #   regex taken from this question: http://stackoverflow.com/questions/8318236/regex-pattern-for-hhmmss-time-string
        match = re.findall("([0-1]?\d|2[0-3]):([0-5]?\d):([0-5]?\d)", time)
        # this regex returns a list of tuples as strings "[('HH', 'MM', 'SS')]", 
        #   which we join back together with ':' (colon) separators 
        t = ':'.join(match[0])
        # create a Datetime object from indexing the first matched time in the list,
        #   taken from this answer http://stackoverflow.com/questions/100210/what-is-the-standard-way-to-add-n-seconds-to-datetime-time-in-python
        # May create an IndexError exception, which we catch in the `except` clause below
        orig = datetime.datetime(100,1,1,int(match[0][0]), int(match[0][1]), int(match[0][2]))
        # Add the number of seconds to the Datetime object,
        #   taken from this answer: http://stackoverflow.com/questions/656297/python-time-timedelta-equivalent
        newtime = (orig + datetime.timedelta(0, myinp)).time()
        # replace the time in the original data string with the newtime and print
        new_data.append(time.replace(t, str(newtime)))
    # catch an IndexError Exception, which we look for float-formatted seconds only
    except IndexError:
        # look for float-formatted seconds (s.xxx)      
        #   taken from this answer: http://stackoverflow.com/questions/4703390/how-to-extract-a-floating-number-from-a-string 
        match = re.findall("\d+\.\d+", time)
        # create a Datetime object from indexing the first matched time in the list,
        #   specifying only seconds, and microseconds, which we convert to milliseconds (micro*1000)
        orig = datetime.datetime(100,1,1,second=int(match[0].split('.')[0]),microsecond=int(match[0].split('.')[1])*1000)
        # Subtract the seconds from the Datetime object, similiar to the time addtion in the `try` clause above
        newtime = orig - datetime.timedelta(0, myinp)
        # format the newtime as `seconds` concatenated with the milliseconds converted from microseconds
        newtime_fmt = newtime.second + newtime.microsecond/1000000.
        # Get the seconds value (first value(index 0)) from splitting the original string at the `space` between the `seconds` and `name` strings 
        t = time.split(' ')[0]
        # replace the time in the original data string with the newtime and print
        new_data.append(time.replace(t , str(newtime_fmt)))


with open('new_data.txt', 'w') as nf:
    for newline in new_data:
        nf.write(newline)

new_data.txt file contents should read as:

John Time Made 11:05:24 in 2010
1.001 Kelly
2.005 Josh
  • for learning purposes and understanding, could you briefly comment? Thank you in advance! – Jo Ko Mar 09 '17 at 23:41
  • Done. Sure, glad to help! – chickity china chinese chicken Mar 10 '17 at 00:14
  • Appreciate it! But I'll actually be reading a file off, which contains that content as an example. – Jo Ko Mar 10 '17 at 17:20
  • Sure, you didn't mention that in your question, you said you are already working with strings. But just the same, read the data from the file into a `list`: `with open('data.txt') as f: data = f.readlines()` then iterate over your `list` of `data` as usual. – chickity china chinese chicken Mar 10 '17 at 17:40
  • Sorry but do you mind showing the whole? Gave it a go but no good. – Jo Ko Mar 10 '17 at 17:41
  • Thank you! But seems like the new lines are not copied to a new file? – Jo Ko Mar 10 '17 at 17:46
  • 1
    What new lines copied to the file? Where did you mention that in your *original question*? What is the *complete task* you are trying to do? Each step we complete you have another task, none of which are mentioned in your *original question* – chickity china chinese chicken Mar 10 '17 at 17:47
  • So the newly modified data that we are printing, you simply want to save it into a file? – chickity china chinese chicken Mar 10 '17 at 17:49
  • Yes save to a new file. Sorry thought it was automatically assumed that the content was received as a file and the new lines would be copied to a new file. – Jo Ko Mar 10 '17 at 17:55
  • 1
    No, we can not ever automatically assume anything, the data can come from many sources and the new data can be used however *you specify*, in coding you need to be explicit. Assumptions can only cause confusion, as you see. – chickity china chinese chicken Mar 10 '17 at 17:58
  • I updated the code to save the data to a new file `new_data.txt`, of course change it, or anything else, to suit your needs. – chickity china chinese chicken Mar 10 '17 at 17:58
  • @JoKo you are not serious. You should have stated explicitly what exactly needs to be done. The main challenge in your problem was to modify the text. That issue was solved in both answers you got. You only needed to redirect the output to a file. You can google that quiet easily, instead of asking further questions. – giliev Mar 10 '17 at 18:05
  • @JoKo, as giliev said most of your question is answered in **other similiar** questions from this site (as you can see by the comments in my code). Including, saving the data [Writing a list to a file with Python](http://stackoverflow.com/questions/899103/writing-a-list-to-a-file-with-python) – chickity china chinese chicken Mar 10 '17 at 18:10