Does anyone know if there is an "easy" function which will convert the following elapsed time string to seconds?
2d1h39m53s
Depending on how much time has elapsed, not all the fields will be present.
I've looked at strptime and datetime but nothing seemed to fit the bill without writing my own function for this. Just looking to save some time.
Thx
I wrote it to days before to clearly verify the runtime. After the two defs below just write 'tic()' at the start point in your code where you want count and 'toc()' at the end point, and it will give you a clear time data to read. Hope it helps.
import time
import math
def tic():
global startTime_for_tictoc
startTime_for_tictoc = time.time()
def toc():
if 'startTime_for_tictoc' in globals():
tf = time.time() - startTime_for_tictoc;
if tf < 60:
print("\nElapsed time: %f seconds.\n" % tf)
elif 60 < tf < 3600:
mm = math.floor(tf/60)
ss = tf - (60*mm)
print("\nElapsed time: %d minute(s) and %f seconds.\n" % (mm, ss))
elif 3600 < tf < 86400:
hh = math.floor(tf/3600)
mm = math.floor((tf-(hh*3600))/60)
ss = tf - (hh*3600) - (60*mm)
print("\nElapsed time: %d hour(s) %d minute(s) and %f seconds.\n" % (hh, mm, ss))
elif tf > 86400:
dd = math.floor(tf/86400)
hh = math.floor((tf-(dd*86400))/3600)
mm = math.floor((tf-(dd*86400)-(hh*3600))/60)
ss = tf - (86400*dd) - (hh*3600) - (60*mm)
print("\nElapsed time: %d day(s) %d hour(s) %d minute(s) and %f seconds.\n" % (dd, hh, mm, ss))
else:
print("\nToc: start time not set")
Not sure if there is a function out there but this will get the job done. Will work with values such as "2d1h53s" as well.
d = []
h = []
m = []
s = []
sd = 0
sh = 0
sm = 0
ss = 0
str = "2d1h39m53s"
i = 0
if str.find("d") > 0:
i = str.find("d")
d.append(str[0:i])
str = str[i:]
if str.find("h") > 0:
i = str.find("h")
h.append(str[1:i])
str = str[i:]
if str.find("m") > 0:
i = str.find("m")
m.append(str[1:i])
str = str[i:]
if str.find("s") > 0:
i = str.find("s")
s.append(str[1:i])
str = str[i:]
try:
sd = float(d[0]) * 24 * 60 * 60
except:
sd = 0
try:
sh = float(h[0]) * 60 * 60
except:
sh = 0
try:
sm = float(m[0]) * 60
except:
sm = 0
try:
ss = float(s[0])
except:
ss = 0
print("seconds")
sec = sd + sh + sm + ss
print(sec)
If your datetime has exactly the given format you could do the following:
import re
import numpy as np
from functools import reduce
split_strings = ['D', 'h','m','s']
def datestring_to_seconds(datestring):
values_and_units = [(int(string[:-1]), string[-1]) for string in [re.search(f"([0-9]+){split_string}",
f"{datestring}".replace('d', 'D')).group(0) for split_string in split_strings]]
return reduce(lambda x,y : x+y, [np.timedelta64(*x) for x in values_and_units])/np.timedelta64(1, 's')
result
datestring_to_seconds("2d1h39m53s")
178793.0
Some explanation:
First search in the string for any to a match of up to two digits in front of one of the split_strings (e.g. 39m) then we convert this to a tuple (39, "m"). We perform this operation with every string in split_strings and save the result in the list values_and_units, which looks in our special case like this:
[(2, 'D'), (1, 'h'), (39, 'm'), (53, 's')]
Each element of these can now be casted to a numpy timedelta64. The reduce operation adds up all the timedeltas and dividing by a np.timedelta64(1, 's') gives us a float with the desired seconds.
Here is a pure python solution.
import re
s = '2d1h39m53s'
d = {'d':86400,'h':3600, 'm':60, 's':1}
secs = 0
m = re.match(r'(\d+)([dhms])', s)
while m is not None:
secs += int(m.group(1)) * d[m.group(2)]
s = re.sub(r'\d+[dhms]', '', s, 1)
m = re.match(r'(\d+)([dhms])', s)
print(secs)
print(secs)
Prints: 178793
EDIT: To use match.end() to locate beginning of next search. Not destructive of string, s, and a cleaner solution.
import re
s = '2d1h39m53s'
d = {'d':86400,'h':3600, 'm':60, 's':1}
secs = 0
pat = re.compile('(\d+)([dhms])')
m = pat.search(s)
while m is not None:
pos = m.end()
secs += int(m.group(1)) * d[m.group(2)]
m = pat.search(s, pos)
print(secs)
Related
In this code, it translates a 24-hour time to a 12-hour time.
How would I disallow numbers that don't make sense? Ex: 25:60:60/3495:3413:3144
The hours shouldn't be over 24, and the minutes/seconds shouldn't be over 59
`# Python program to convert time from 24 hour
# to 12 hour format
# Convert Function which takes in
# 24hour time and convert it to
# 12 hour format
def convert12(str):
# Get Hours
h1 = ord(str[0]) - ord('0')
h2 = ord(str[1]) - ord('0')
hh = h1 * 10 + h2
# Finding out the Meridien of time
# ie. AM or PM
Meridien=""
if (hh < 12):
Meridien = "AM"
else:
Meridien = "PM"
hh %= 12
# Handle 00 and 12 case separately
if (hh == 0):
print("12", end = "")
# Printing minutes and seconds
for i in range(2, 8):
print(str[i], end = "")
else:
print(hh,end="")
# Printing minutes and seconds
for i in range(2, 8):
print(str[i], end = "")
# After time is printed
# cout Meridien
print(" " + Meridien)
# Driver code
if __name__ == '__main__':
# 24 hour format
str = input(str("Please enter the time, in format 00:00:00: "))
convert12(str)
`
I've tried things like,
if "25" in str:
I am looking to combine 10 audio samples in various manners (format - wav probably, but this can be changed to any format as they will be pre-recorded).
from pydub import AudioSegment
sounds = []
sound1 = AudioSegment.from_wav("Dropbox/PIREAD/1.wav")
sound2 = AudioSegment.from_wav("Dropbox/PIREAD/2.wav")
sound3 = AudioSegment.from_wav("Dropbox/PIREAD/3.wav")
sound4 = AudioSegment.from_wav("Dropbox/PIREAD/4.wav")
sound5 = AudioSegment.from_wav("Dropbox/PIREAD/5.wav")
sound6 = AudioSegment.from_wav("Dropbox/PIREAD/6.wav")
sound7 = AudioSegment.from_wav("Dropbox/PIREAD/7.wav")
sound8 = AudioSegment.from_wav("Dropbox/PIREAD/8.wav")
sound9 = AudioSegment.from_wav("Dropbox/PIREAD/9.wav")
sound0 = AudioSegment.from_wav("Dropbox/PIREAD/0.wav")
sounds=[sound1,sound2,sound3,sound4,sound5,sound6,sound7,sound8,sound9,sound0]
combined_sounds = AudioSegment.empty()
for x in range(10):
for y in range(10):
combined_sounds += sounds[y]
combined_sounds.export("Dropbox/PIREAD/joinedFile.wav", format="wav")
This is literally me reading the numbers 0-9 and assembling them into one overall wav file.
It works - but it is slow once the loop is extended x=100, x=1000.
Q: How can I speed things up?
The actual order of the numbers will be read from a text$ - for example "354224848179261915075" which happens to be the 100th Fibonacci number.
Cheers
Glen
I believe it's slow because when you loop over x, you repeat operations (the loop over y) which could be computed before the loop over x, then assembled.
I looked into AudioSegment and found potentially useful method for you namely from_mono_audiosegments but it is limited to mono sounds and you will need to test if it is faster than += please compare time-wise these options, i.e.
import time
from pydub import AudioSegment
sounds = []
sound1 = AudioSegment.from_wav("Dropbox/PIREAD/1.wav")
sound2 = AudioSegment.from_wav("Dropbox/PIREAD/2.wav")
sound3 = AudioSegment.from_wav("Dropbox/PIREAD/3.wav")
sound4 = AudioSegment.from_wav("Dropbox/PIREAD/4.wav")
sound5 = AudioSegment.from_wav("Dropbox/PIREAD/5.wav")
sound6 = AudioSegment.from_wav("Dropbox/PIREAD/6.wav")
sound7 = AudioSegment.from_wav("Dropbox/PIREAD/7.wav")
sound8 = AudioSegment.from_wav("Dropbox/PIREAD/8.wav")
sound9 = AudioSegment.from_wav("Dropbox/PIREAD/9.wav")
sound0 = AudioSegment.from_wav("Dropbox/PIREAD/0.wav")
sounds=[sound1,sound2,sound3,sound4,sound5,sound6,sound7,sound8,sound9,sound0]
# option1 using +=
t1 = time.time()
combined_sounds1 = AudioSegment.empty()
for s in sounds
combined_sounds1 += s
t2 = time.time()
# end of option1
# option2 using from_mono_audiosegments
t3 = time.time()
combined_sounds2 = AudioSegment.from_mono_audiosegments(*sounds)
t4 = time.time()
# end of option2
print('option1 (seconds):',t2-t1)
print('option2 (seconds):',t4-t3)
Thanks for the suggestions and advice above. This is the final code I used and link to the resultant video (with ffmpeg visualisation):
# Program to display the Fibonacci sequence up to n-th term
from pydub import AudioSegment
combined_sounds = ""
sound1 = AudioSegment.from_wav("1_2.wav")
sound2 = AudioSegment.from_wav("2_2.wav")
sound3 = AudioSegment.from_wav("3_2.wav")
sound4 = AudioSegment.from_wav("4_2.wav")
sound5 = AudioSegment.from_wav("5_2.wav")
sound6 = AudioSegment.from_wav("6_2.wav")
sound7 = AudioSegment.from_wav("7_2.wav")
sound8 = AudioSegment.from_wav("8_2.wav")
sound9 = AudioSegment.from_wav("9_2.wav")
sound0 = AudioSegment.from_wav("0_2.wav")
nterms=1000
# first two terms
n1, n2 = 0, 1
count = 0
fib = ""
# check if the number of terms is valid
if nterms <= 0:
print("Please enter a positive integer")
# if there is only one term, return n1
elif nterms == 1:
print("Fibonacci sequence upto",nterms,":")
print(n1)
# generate fibonacci sequence
else:
print("Fibonacci sequence:")
while count < nterms:
#print(n1)
fib += str(n1)
nth = n1 + n2
# update values
n1 = n2
n2 = nth
count += 1
i=-36
j=0
fibs = [fib[i:i+1000] for i in range(0, len(fib), 1000)]
seg = 0
for a in fibs:
if seg == 2:
break
combined_sounds = AudioSegment.empty()
seg +=1
for x in a:
i,j = -36,0
s = eval("sound"+str(x))
s = s.apply_gain_stereo(i,j)
combined_sounds += s
i,j = j,i
combined_sounds.export("joinedFile"+str(seg)+".wav", format="wav")
This splits the output into 1000 digit wav files. The first 1000 Fibonacci terms produces nearly 15Gb of wavs!
Uploaded to YouTube: https://www.youtube.com/watch?v=U7Z_HOGqjlE
Thanks all.
I have a program in which I am just printing to a csv and I want exactly 100 sample points every second but I have no clue where to start with this or how to do it!!! Please help!
from datetime import datetime
import pandas as pd
i = 0
data = []
filename = 'Data.csv'
hz = 0
count = 0
while True:
#start = process_time()
if i == 0:
Emptydf = pd.DataFrame([], columns = ['COUNT', 'TIME'])
(Emptydf).to_csv('Data.csv', index = False)
curr_time = datetime.now()
str_milli = curr_time.strftime("%f")[:2]
milliseconds = int(str_milli)
timestamp = curr_time.strftime("%H:%M:%S.%f")
datarow = {'Count': i, 'TIME' : timestamp}
#diff = curr_time - past time of 0.01 milli seconds
#if diff >= 0.01:
data.append(datarow)
#time.sleep(.006)
if i%10 == 0:
dataframe = pd.DataFrame(data)
(dataframe).to_csv('Data.csv', mode = 'a', header = False, index = False)
#print(dataframe)
data.clear()
i += 1
Here is an example that increments a counter 100 times per second:
import time
FREQ_HZ = 100.
count = 0
start_time = time.time()
try:
while True:
count += 1
time.sleep(count / FREQ_HZ - (time.time() - start_time))
except:
print("%.2f iter/second\n" % (count / (time.time() - start_time)))
To test, let it run for a bit and then hit ^C.
Basically, what you do is the following;
import time
cycletime = 0.01 # seconds
while True:
start = time.monotonic()
# << Do whatever you need to do here. >>
delta = time.monotonic() - start
if delta < cycletime: # Did we finish in time?
time.sleep(cycletime - delta) # Sleep the rest of the time.
else:
print('WARNING: cycle too long!')
Note that for such applications time.monotonic is preferred over time.time because the latter can decrease when the system clock is changed.
I want to write a program that allows the user to enter in a start time hour, end time hour, and number of divisions.
So they might enter 9, 10, and 4 which should mean a start time of 9:00AM, end of 10:00AM and to split the range 4 times, resulting in an output of 9:00, 9:15, 9:30, 9:45.
I've tried using the time module and datetime, but cannot get the addition of time to work. I do not care about date.
I can calculate the time split, but the actual addition to the start time is evading me.
I have a hodge-podge of code, and the following is mostly me experimenting trying to figure out how to make this work. I've tried adding the minutes, tried converting to seconds, delved into datetime, tried the time module, but can't seem to get it to work. There are plenty of examples of how to "add 15 minutes to now" but the issue is I don't want to start at the "now", but rather let the user decide start time.
Thank you.
time_start = "9"
time_end = "10"
time_split = "4"
if len(time_start) == 1:
time_start = "0" + str(time_start) + ":00"
else:
time_start = str(time_start) + ":00"
if len(time_end) == 1:
time_end = "0" + str(time_end) + ":00"
else:
time_end = str(time_end) + ":00"
print time_start
print time_end
s1 = time_start + ':00'
s2 = time_end + ':00'
FMT = '%H:%M:%S'
tdelta = datetime.strptime(s2, FMT) - datetime.strptime(s1, FMT)
divided = tdelta / int(time_split)
print tdelta
print divided
s3 = str(divided)
print "s1 time start: " + str(s1)
print "s2 time end: " + str(s2)
print "s3 time divided: " + str(s3)
ftr = [3600,60,1]
add_seconds = sum([a*b for a,b in zip(ftr, map(int,s3.split(':')))])
print "s3 time divided seconds: " + str(add_seconds)
print "time delta: " + str(tdelta)
EDIT: I did a small bit of research and found a much better solution that elegantly handles resolution to the millisecond. Please implement this code instead (though I will save the old code for posterity)
import datetime
start_time = 9 # per user input
end_time = 10 # per user input
divisions = 7 # per user input
total_time = end_time - start_time
start_time = datetime.datetime.combine(datetime.date.today(),datetime.time(start_time))
end_time = start_time + datetime.timedelta(hours=total_time)
increment = total_time*3600000//divisions # resolution in ms
times = [(start_time+datetime.timedelta(milliseconds=increment*i)).time()
for i in range(divisions)]
from pprint import pprint
pprint(list(map(str,times)))
# ['09:00:00',
# '09:08:34.285000',
# '09:17:08.570000',
# '09:25:42.855000',
# '09:34:17.140000',
# '09:42:51.425000',
# '09:51:25.710000']
If I were you, I'd do my math as raw minutes and use datetime.time only to save the results as something more portable.
Try this:
import datetime
start_time = 9 # per user input
end_time = 10 # per user input
divisions = 4 # per user input
total_minutes = (end_time-start_time)*60
increment = total_minutes // divisions
minutes = [start_time*60]
while minutes[-1] < end_time*60:
# < end_time*60 - increment to exclude end_time from result
minutes.append(minutes[-1] + increment)
times = [datetime.time(c//60,c%60) for c in minutes]
# [09:00:00,
# 09:15:00,
# 09:30:00,
# 09:45:00,
# 10:00:00]
In python how do I sum up the following time?
0:00:00
0:00:15
9:30:56
It depends on the form you have these times in, for example if you already have them as datetime.timedeltas, then you could just sum them up:
>>> s = datetime.timedelta(seconds=0) + datetime.timedelta(seconds=15) + datetime.timedelta(hours=9, minutes=30, seconds=56)
>>> str(s)
'9:31:11'
Using timedeltas (tested in Python 3.9):
import datetime
timeList = ['0:00:00', '0:00:15', '9:30:56']
mysum = datetime.timedelta()
for i in timeList:
(h, m, s) = i.split(':')
d = datetime.timedelta(hours=int(h), minutes=int(m), seconds=int(s))
mysum += d
print(str(mysum))
Result:
9:31:11
As a list of strings?
timeList = [ '0:00:00', '0:00:15', '9:30:56' ]
totalSecs = 0
for tm in timeList:
timeParts = [int(s) for s in tm.split(':')]
totalSecs += (timeParts[0] * 60 + timeParts[1]) * 60 + timeParts[2]
totalSecs, sec = divmod(totalSecs, 60)
hr, min = divmod(totalSecs, 60)
print "%d:%02d:%02d" % (hr, min, sec)
Result:
9:31:11
I'm really disappointed if there is not any more pythonic solution... :(
Horrible one ->
timeList = [ '0:00:00', '0:00:15', '9:30:56' ]
ttt = [map(int,i.split()[-1].split(':')) for i in timeList]
seconds=reduce(lambda x,y:x+y[0]*3600+y[1]*60+y[2],ttt,0)
#seconds == 34271
This one looks horrible too ->
zero_time = datetime.datetime.strptime('0:0:0', '%H:%M:%S')
ttt=[datetime.datetime.strptime(i, '%H:%M:%S')-zero_time for i in timeList]
delta=sum(ttt,zero_time)-zero_time
# delta==datetime.timedelta(0, 34271)
# str(delta)=='9:31:11' # this seems good, but
# if we have more than 1 day we get for example str(delta)=='1 day, 1:05:22'
Really frustrating is also this ->
sum(ttt,zero_time).strftime('%H:%M:%S') # it is only "modulo" 24 :(
I really like to see one-liner so, I tried to make one in python3 :P (good result but horrible look)
import functools
timeList = ['0:00:00','0:00:15','9:30:56','21:00:00'] # notice additional 21 hours!
sum_fnc=lambda ttt:(lambda a:'%02d:%02d:%02d' % (divmod(divmod(a,60)[0],60)+(divmod(a,60)[1],)))((lambda a:functools.reduce(lambda x,y:x+y[0]*3600+y[1]*60+y[2],a,0))((lambda a:[list(map(int,i.split()[-1].split(':'))) for i in a])(ttt)))
# sum_fnc(timeList) -> '30:40:11'
lines = ["0:00:00", "0:00:15", "9:30:56"]
total = 0
for line in lines:
h, m, s = map(int, line.split(":"))
total += 3600*h + 60*m + s
print "%02d:%02d:%02d" % (total / 3600, total / 60 % 60, total % 60)
Assuming you want to add up the seconds for a total time:
def parse_time(s):
hour, min, sec = s.split(':')
try:
hour = int(hour)
min = int(min)
sec = int(sec)
except ValueError:
# handle errors here, but this isn't a bad default to ignore errors
return 0
return hour * 60 * 60 + min * 60 + sec
print parse_time('0:00:00') + parse_time('0:00:15') + parse_time('9:30:56')
from datetime import timedelta
h = ['3:00:00','1:07:00', '4:00:00', '4:05:00', '4:10:00', '4:03:00']
def to_td(h):
ho, mi, se = h.split(':')
return timedelta(hours=int(ho), minutes=int(mi), seconds=int(se))
print(str(sum(map(to_td, h), timedelta())))
# Out[31]: 20:25:00
Naive approach (without exception handling):
#!/usr/bin/env python
def sumup(*times):
cumulative = 0
for t in times:
hours, minutes, seconds = t.split(":")
cumulative += 3600 * int(hours) + 60 * int(minutes) + int(seconds)
return cumulative
def hms(seconds):
"""Turn seconds into hh:mm:ss"""
hours = seconds / 3600
seconds -= 3600*hours
minutes = seconds / 60
seconds -= 60*minutes
return "%02d:%02d:%02d" % (hours, minutes, seconds)
if __name__ == '__main__':
print hms(sumup(*("0:00:00", "0:00:15", "9:30:56")))
# will print: 09:31:11
Bellow is a solution using list comprehension:
from datetime import timedelta
def time_sum(time: List[str]) -> timedelta:
"""
Calculates time from list of time hh:mm:ss format
"""
return sum(
[
timedelta(hours=int(ms[0]), minutes=int(ms[1]), seconds=int(ms[2]))
for t in time
for ms in [t.split(":")]
],
timedelta(),
)
Example:
time_list = ["0:00:00", "0:00:15", "9:30:56"]
total = time_sum(time_list)
print(f"Total time: {total}")