Python - convert elapsed time to seconds when format is not consistent - python

I am trying to identify the number of seconds that have elapsed given a time string. These time strings are not always consistent.
Examples:
'01:02' = 1 minute, 2 seconds = 62 seconds
'1-11:01:02' = 1 day, 11 hours, 1 minute, 2 seconds = 126062 seconds
I have tried time.strptime, but I didn't see a way to elegantly perform this operation. Any ideas?

One way to go about it is to gather all possible formats in an array and check the time_str against them:
time_formats = ["%m-%d:%H:%M","%H:%M"]
time_val = None
for fmt in time_formats:
try:
time_val = time.strptime(time_str,fmt)
except:
pass
if time_val is None:
print "No matching format found"
This try-catch structure is consistent with the EAFP principle in python. http://docs.python.org/2/glossary.html

Related

An accurate stop watch using Python for logging minutes and hours worked. What's the best way to go about it? [duplicate]

This question already has answers here:
How to increase sleep/pause timing accuracy in python?
(4 answers)
Closed 5 months ago.
I've tried a few solutions from here with no luck. My Python timers are 10-30 seconds behind my smartphone stop watch after 10 minutes. I've tried the following:
def background3():
while True:
second = 0
minute = 0
hours = 0
while(True):
print('%d : %d : %d'%(hours,minute,second))
time.sleep(1)
second+=1
if(second == 60):
second = 0
minute+=1
if(minute == 60):
minute = 0
hour+=1;
and I also tried this:
def showCounter(self):
# Check the value of startWatch variable to start or stop the Stop Watch
if self.startWatch:
# Increment counter by 1
self.counter += 1
# Count and set the time counter value
cnt = int((self.counter/10 - int(self.counter/10))*10)
self.count = '0' + str(cnt)
# Set the second value
if int(self.counter/10) < 10 :
self.second = '0' + str(int(self.counter / 10))
else:
self.second = str(int(self.counter / 10))
# Set the minute value
if self.counter / 10 == 60.0 :
self.second == '00'
self.counter = 0
min = int(self.minute) + 1
if min < 10 :
self.minute = '0' + str(min)
else:
self.minute = str(min)
# Merge the mintue, second and count values
text = self.minute + ':' + self.second
# Display the stop watch values in the label
self.label.setText('<h1 style="color:white">' + text + '</h1>')
I'd like to be able to update a pyqt5 qlabel as time goes by every second, and I'd like to be able to display hours, minutes, and seconds in the qlabel. This has to be accurate as it is for work logging purposes. Eventually, I want to implement a qlabel that takes my overtime rate into consideration, and updates $ earned as time goes by. Does anybody have an example of what this may look like in pyqt5 using perhaps OS time ? Or is there some better way to do this?
EDIT:
This question is not a duplicate. The suggested articles were not helpful. I essentially need a way to count up from 0 using datetime. I tried replacing datetime.now but that did not work. The solutions suggested do not update my value in real time. They just take a stamp at the beginning, and subtract it from the end time. this is not what I am looking for. Does anybody know how I can watch seconds, minutes, and hours go by in real time through a pyqt5 qlabel?
def showCounter(self):
if self.startWatch:
text = str(datetime.now().strftime("%H:%M:%S"))
self.label.setText('<h1 style="color:white">' + str(text) + '</h1>')
Here's some code that prints every passing second without accumulating any lag. Just check the built-in clock at least once per second and update if the second has changed.
from datetime import datetime
import time
def time_to_str(time):
return str(time.hour) + ':' + str(time.minute) + ':' + str(time.second)
cur_time = datetime.now()
cur_str = time_to_str(cur_time)
while True:
time.sleep(0.2) # 200 ms, arbitrary
new_time = datetime.now()
new_str = time_to_str(new_time)
if new_str != cur_str:
print(new_str)
cur_str = new_str
The more often you check the time, the faster you can respond to the start of a new second. You'll never accrue lag regardless because you only print the time immediately after getting it from the system.
You should not expect a manufactured timer that relies on sleep() to be accurate for accrued time (stopwatch). Even if sleep() were 100% accurate, you are losing time outside of that in all of the function calls and other parts of the loop, which adds up over time (pun intended.)
The system time should be used. You can either use:
time.time()
or
datetime.now()
both have methods to peel out H:M:S.
As far as your "update loop"... well that is another story, you could use sleep there or whatever PyQt has to offer to refresh, but when you need to pull the time, do it as above.
If you want to use either as a "stopwatch" just capture the start time, do the subtraction. If you do this with datetime objects, the delta is a timedelta object that you can query. Do a little googling on timedelta and datetime.
Example:
In [1]: from datetime import datetime, timedelta
In [2]: tic = datetime.now()
In [3]: toc = datetime.now()
In [4]: td = toc - tic
In [5]: type(td)
Out[5]: datetime.timedelta
In [6]: td.seconds
Out[6]: 8

Make a string based on timeframe

I am trying to understand how to make a string based on the current time, and time ranges in Python. So, if it's between 8am and 11am, for Python to identofy what time it is, and automatically return a "breakfast" string; and if its between 11am to 4pm --> return a lunch string
First of all, please, try to be clear when asking and bring some examples that you tried before.
Getting the time is easy as:
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time)
You can see more information about datetime module here
So, current_time brings a string with the time. To select minutes or hours you need to pick up the position that they're at.
For example:
myTime = "12:34:56"
seconds = myTime[-2:]
print(seconds)
56
For more examples on slicing strings, here
You want integers instead of strings?
seconds = int(seconds)

How to convert time written "h.mm" to decimal form with Python?

I prompt the user to input what time they start and finish their job. Then I need to calculate what they will earn (given a 97 currency/hour salary). The answer should also not have any decimals (so it should be rounded off). I can't seem to get it to work though.
As shown below, I tried taking the difference between the two inputs from the user and then splitting them to hours and minutes. After that just doing the calculations.
difference = round(float(finishing_time)-float(start_time), 2)
hours, minutes = str(difference).split(".")
salary_hours = int(hours)*97
salary_minutes = int(minutes)//60*97
salary = salary_hours + salary_minutes
So if start_time = 8.30 and finishing_time = 11.15 the salary should be 267, but I get 291 currency.
A couple of things to be careful of, is the rounding off that occurs at every level, which also occurs when you do math by hand and pencil! There is a reason why when you perform calculations one typically does the rounding off when the entire calculation has been performed otherwise one would come up with a vastly different answer as you pointed out.
I'd tackle this perhaps by doing something like this
from datetime import datetime
# quick way to generate a datetime object with start time would be like
start_time = datetime.now()
# replace the hours and minutes you want in your case its
start_time = start_time.replace(hour=8, minute=30)
end_time = start_time.replace(hour=11, minute=15)
# calling replace returns a new distinct datetime object
def calculate_salary(start_time, finish_time, pay_rate):
# will be in seconds
delta_seconds = finish_time - start_time
# convert to hours
hours_worked = (delta_seconds.seconds) / 3600
# calculate pay
pay = hours_worked * pay_rate
return pay
In this case calling the function gives a value of
In [1]: calculate_salary(start_time, end_time, 97)
Out[1]: 266.75
While i dont advocate doing calculations on time without a time module. I assume you know what your doing and that your calculations are simple I.E they wont rolle over midnight and the finish time will always be greater than the start time and finish on the same day. With that in mind the following code should produce your result without using a datetime module. However like #william bright answer, a datetime module would be my prefernce for code like this.
def get_hours(time_string):
time_split = time_string.split(".")
whole_hours = int(time_split[0])
fraction_hours = int(time_split[1]) / 60
return whole_hours + fraction_hours
start_time=input("start time: ")
finish_time=input("finish_time: ")
total_hours = get_hours(finish_time)-get_hours(start_time)
salary = total_hours*97
print(round(salary))
OUTPUT
start time: 8.30
finish_time: 11.15
267
So, my bad for perhaps being unclear in my statement, but since this is a work in progress for the next couple weeks/months, what I came up with was the following:
starting_time = input("At what time did you start working? ")
finishing_time = input("At what time did you finish working? ")
hours1, minutes1 = starting_time.split(".")
hours2, minutes2 = finishing_time.split(".")
minutes1 = float(minutes1)/60
starting_time_new = float(hours1)+minutes1
minutes2 = float(minutes2)/60
finishing_time_new = float(hours2)+minutes2
salary = round((finishing_time_new-starting_time_new)*97)
print("Started working at:",b)
print("Stopped working at:",s)
print("Your salary is",salary,"currency.")
The solution from where I started was to just focus on changing the minutes to the correct decimals instead of focusing on the hours too.
I am well aware that it is far from perfect, in fact, it is probably really bad. However, I am new to programming in Python and taking a course to be better.

How can I process complex user input in python?

I'm a pretty new python user, working on a project that will be used by people who won't really understand how picky python can be about inputs. For the program, I need to get user input telling me how long a video is(minutes and seconds), and then I need to subtract a minute and eight seconds from that length, then print it. Is there a way I could process an input such as "5 minutes and 30 seconds"?
One possibility is to check each substring in the user's input and assign them to values:
s = input("video length? ")
minutes, seconds = [int(x) for x in s.split() if x.isdigit()]
The cast int(x) will save them as integers if desired:
print(minutes) # 5
print(seconds) # 30
Or a regular expression solution may be:
import re
minutes, seconds = map(int, re.findall('\d+', s))
print(minutes) # 5
print(seconds) # 30
Now you have the values to perform the resulting time calculation:
import datetime
# here, 100,1,1 are just placeholder values for year, month, day that are required to create a datetime object
usertime = datetime.datetime(100,1,1, minute=minutes, second=seconds)
calculation = usertime - datetime.timedelta(minutes=1, seconds=8)
Now you can display the result of the time calculation however you like:
print('{minutes} minutes and {seconds} seconds'.format(minutes=calculation.minute, seconds=calculation.second))
# 4 minutes and 22 seconds
You could use a regular expression if the format will always be the same (but it probably will not), then convert the appropriate string to an integer/ double.
I think that you are going about this incorrectly. It would be best to have two separate input fields that only accept integers. One for minutes and one for seconds. If you want more precision (i.e milliseconds) then just include another input field.
The main problem here is the format in which you will accept the input. You could force the user to input the time in just one format, for example, hours:minutes:seconds, in that case, the code below will calculate the total seconds:
inp = input('Video duration: ').split(':')
hours = 0
mins = 0
secs = 0
if len(inp) >= 3:
hours = int(inp[-3])
if len(inp) >= 2:
mins = int(inp[-2])
secs = int(inp[-1])
total_secs = hours * 3600 + mins * 60 + secs - 68
I oversimplified the code, it doesnt avoid user errors and edge cases
You can try :
import re
from datetime import datetime, timedelta
question = "How long is the video (mm:ss)? "
how_long = input(question).strip()
while not re.match(r"^[0-5]?\d:[0-5]?\d$", how_long): # regex to check if mm:ss digits are in range 0-5
how_long = input("Wrong format. " + question).strip()
mm_ss = how_long.split(":")
how_long_obj = datetime.strptime(f"{mm_ss[0]}:{mm_ss[1]}", '%M:%S')
print(f"{how_long_obj - timedelta(seconds=68):%M:%S}")
Output:
How long is the video (mm:ss)? 22:33
21:25
Python3 Demo - (Please turn Interactive mode On)

Printing a timestamp with padded time values

I have this code for my alarm clock program, which checks if the input is of the form HH:MM:SS.
def testing():
try:
alarm = input("> ")
hour = int(alarm[0:2])
minute = int(alarm[3:5])
second = int(alarm[6:8])
if len(alarm) == 8:
print(("\nsets to %s:%s:%s\n" % (hour, minute, second)))
except ValueError:
print("format must be HH:MM:SS")
testing()
testing()
It works fine unless, for example, the input is "00:00:00", in which case the output is "0:0:0" instead of the expected output with each unit padded to two digits. Why is this happening?
Consider the line hour = int(alarm[0:2]) when alarm is "00:00:00":
alarm[0:2] will be "00" and int("00") is the integer 0.
The same happens for minute and second. When you interpolate the values of hour, minute, and second, then the result is "0:0:0".
You can pad the hour, minute, and second values to two digits by changing your print statement to
print(("\nsets to %02d:%02d:%02d\n" % (hour, minute, second)))
Since you are formatting the values into strings, you could do without the conversion from strings to integers:
hour = alarm[0:2]
minute = alarm[3:5]
second = alarm[6:8]
Also, instead of the % operator, I would use str.format() which is a more powerful string formatting method:
print("\nsets to {}:{}:{}\n".format(hour, minute, second))
Change from print(("\nsets to %s:%s:%s\n" % (hour, minute, second)))
Into this format print(("\nsets to %02d:%02d:%02d\n" % (hour, minute, second)))
Now instead of printing 2:0:0 or 0:0:0 you will print 02:00:00 or 00:00:00

Categories