Subtract two time codes
Clash Royale CLAN TAG#URR8PPP
up vote
0
down vote
favorite
I need to subtract two time codes from each other, I have multiple in an array and the output looks like this:
**Input:**
echo $arr3[0]
echo $arr3[1]
**Output:**
00:00:22.180 --> 00:00:25.600
00:00:24.070 --> 00:00:27.790
In this example the following equation needs to take place 00:00:25.600 - 00:00:22.180 = output into array
and 00:00:27.790 - 00:00:24.070 = output into the same array
It needs to be in the same format so can use it in FFMPEG.
I also need the first timecode of each array entry, so:
00:00:22.180
00:00:24.070
in another array so I can use these inputs in ffmpeg as well.
I have no clue as in how I can do this.
Thanks for your help in advance.
EDIT:
I'll use the data as follows
time=$(The first timecode of the array)
duration=$(Timecodes subtracted)
ffmpeg -i movie.mp4 -ss $time -t $duration -async 1 cut.mp4
bash shell-script date ffmpeg
add a comment |Â
up vote
0
down vote
favorite
I need to subtract two time codes from each other, I have multiple in an array and the output looks like this:
**Input:**
echo $arr3[0]
echo $arr3[1]
**Output:**
00:00:22.180 --> 00:00:25.600
00:00:24.070 --> 00:00:27.790
In this example the following equation needs to take place 00:00:25.600 - 00:00:22.180 = output into array
and 00:00:27.790 - 00:00:24.070 = output into the same array
It needs to be in the same format so can use it in FFMPEG.
I also need the first timecode of each array entry, so:
00:00:22.180
00:00:24.070
in another array so I can use these inputs in ffmpeg as well.
I have no clue as in how I can do this.
Thanks for your help in advance.
EDIT:
I'll use the data as follows
time=$(The first timecode of the array)
duration=$(Timecodes subtracted)
ffmpeg -i movie.mp4 -ss $time -t $duration -async 1 cut.mp4
bash shell-script date ffmpeg
I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
â Jeff Schaller
Feb 26 at 16:27
The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
â symcbean
Feb 26 at 17:30
1
@symcbeandate (GNU coreutils) 8.25
allows nanosecond accuracy.
â Fiximan
Feb 26 at 17:51
@Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
â symcbean
Feb 26 at 21:07
@symcbean See my answer below - I found no entry ininfo
regarding a nanosecond time -> human readable conversion, thus relied onbash
integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.
â Fiximan
Feb 26 at 22:19
add a comment |Â
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I need to subtract two time codes from each other, I have multiple in an array and the output looks like this:
**Input:**
echo $arr3[0]
echo $arr3[1]
**Output:**
00:00:22.180 --> 00:00:25.600
00:00:24.070 --> 00:00:27.790
In this example the following equation needs to take place 00:00:25.600 - 00:00:22.180 = output into array
and 00:00:27.790 - 00:00:24.070 = output into the same array
It needs to be in the same format so can use it in FFMPEG.
I also need the first timecode of each array entry, so:
00:00:22.180
00:00:24.070
in another array so I can use these inputs in ffmpeg as well.
I have no clue as in how I can do this.
Thanks for your help in advance.
EDIT:
I'll use the data as follows
time=$(The first timecode of the array)
duration=$(Timecodes subtracted)
ffmpeg -i movie.mp4 -ss $time -t $duration -async 1 cut.mp4
bash shell-script date ffmpeg
I need to subtract two time codes from each other, I have multiple in an array and the output looks like this:
**Input:**
echo $arr3[0]
echo $arr3[1]
**Output:**
00:00:22.180 --> 00:00:25.600
00:00:24.070 --> 00:00:27.790
In this example the following equation needs to take place 00:00:25.600 - 00:00:22.180 = output into array
and 00:00:27.790 - 00:00:24.070 = output into the same array
It needs to be in the same format so can use it in FFMPEG.
I also need the first timecode of each array entry, so:
00:00:22.180
00:00:24.070
in another array so I can use these inputs in ffmpeg as well.
I have no clue as in how I can do this.
Thanks for your help in advance.
EDIT:
I'll use the data as follows
time=$(The first timecode of the array)
duration=$(Timecodes subtracted)
ffmpeg -i movie.mp4 -ss $time -t $duration -async 1 cut.mp4
bash shell-script date ffmpeg
edited Feb 26 at 16:32
asked Feb 26 at 16:14
tjallo
176
176
I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
â Jeff Schaller
Feb 26 at 16:27
The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
â symcbean
Feb 26 at 17:30
1
@symcbeandate (GNU coreutils) 8.25
allows nanosecond accuracy.
â Fiximan
Feb 26 at 17:51
@Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
â symcbean
Feb 26 at 21:07
@symcbean See my answer below - I found no entry ininfo
regarding a nanosecond time -> human readable conversion, thus relied onbash
integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.
â Fiximan
Feb 26 at 22:19
add a comment |Â
I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
â Jeff Schaller
Feb 26 at 16:27
The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
â symcbean
Feb 26 at 17:30
1
@symcbeandate (GNU coreutils) 8.25
allows nanosecond accuracy.
â Fiximan
Feb 26 at 17:51
@Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
â symcbean
Feb 26 at 21:07
@symcbean See my answer below - I found no entry ininfo
regarding a nanosecond time -> human readable conversion, thus relied onbash
integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.
â Fiximan
Feb 26 at 22:19
I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
â Jeff Schaller
Feb 26 at 16:27
I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
â Jeff Schaller
Feb 26 at 16:27
The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
â symcbean
Feb 26 at 17:30
The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
â symcbean
Feb 26 at 17:30
1
1
@symcbean
date (GNU coreutils) 8.25
allows nanosecond accuracy.â Fiximan
Feb 26 at 17:51
@symcbean
date (GNU coreutils) 8.25
allows nanosecond accuracy.â Fiximan
Feb 26 at 17:51
@Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
â symcbean
Feb 26 at 21:07
@Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
â symcbean
Feb 26 at 21:07
@symcbean See my answer below - I found no entry in
info
regarding a nanosecond time -> human readable conversion, thus relied on bash
integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.â Fiximan
Feb 26 at 22:19
@symcbean See my answer below - I found no entry in
info
regarding a nanosecond time -> human readable conversion, thus relied on bash
integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.â Fiximan
Feb 26 at 22:19
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
Given an array arr3 that contains sample data:
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.
# converts HH:MM:SS.sss to fractional seconds
codes2seconds() (
local hh=$1%%:*
local rest=$1#*:
local mm=$rest%%:*
local ss=$rest#*:
printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss")
)
# converts fractional seconds to HH:MM:SS.sss
seconds2codes() (
local seconds=$1
local hh=$(bc <<< "scale=0; $seconds / 3600")
local remainder=$(bc <<< "$seconds % 3600")
local mm=$(bc <<< "scale=0; $remainder / 60")
local ss=$(bc <<< "$remainder % 60")
printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss"
)
subtracttimes() (
local t1sec=$(codes2seconds "$1")
local t2sec=$(codes2seconds "$2")
printf "%s" $(bc <<< "$t2sec - $t1sec")
)
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
for range in "$arr3[@]"
do
duration=$(subtracttimes "$range%% -->*" "$range##*--> ")
printf "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
done
The codes2seconds
function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc
for the conversion into total number of seconds.
The seconds2codes
function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.
The subtracttimes
function converts the two parameters to fractional seconds then asks bc
for their difference.
The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg
call to match your sample output.
Results:
ffmpeg -i movie.mp4 -ss 00:00:22.180 -t 3.420 -async 1 cut.mp4
ffmpeg -i movie.mp4 -ss 00:00:24.070 -t 3.720 -async 1 cut.mp4
add a comment |Â
up vote
1
down vote
Well, for time codes date
usually pops into my mind. Not the most elegant script, but it does the job...
I assume from your question, that you have beginning and end times already read into respective arrays and will use start
and end
as these values here and do it step by step:
#!/bin/bash
start=00:00:22.180
end=00:00:24.070
#convert timestamps to epoch time in nano seconds
start_ns="$(date -u -d"$start" +%s%N)"
end_ns="$(date -u -d"$end" +%s%N)"
difference="$(($end_ns-$start_ns))"
#date does not read epoch time in nanoseconds,
#so it must be converted by division vith 10^9 before display
#date_diff is accurate up to full seconds
#use UTC time (-u) to avoid problems with time zones
date_diff="$( date -u -d@$((difference/1000000000)) +%H:%M:%S )"
#take care of milliseconds as remainder of division by 10^9 and correction by 10^6
ms_diff="$(( $difference%1000000000/1000000 ))"
#combine output to create desired format
echo "$date_diff"."$ms_diff"
Result
bash script.sh
00:00:01.890
All in one line
echo "$(date -u -d@"$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))/1000000000 ))" +%H:%M:%S)"."$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))%1000000000/1000000 ))"
Please note that I am not aware if nanosecond time in date
is a POSIX standard feature.
Thanks for the solution, worked for me!
â tjallo
Feb 26 at 19:11
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Given an array arr3 that contains sample data:
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.
# converts HH:MM:SS.sss to fractional seconds
codes2seconds() (
local hh=$1%%:*
local rest=$1#*:
local mm=$rest%%:*
local ss=$rest#*:
printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss")
)
# converts fractional seconds to HH:MM:SS.sss
seconds2codes() (
local seconds=$1
local hh=$(bc <<< "scale=0; $seconds / 3600")
local remainder=$(bc <<< "$seconds % 3600")
local mm=$(bc <<< "scale=0; $remainder / 60")
local ss=$(bc <<< "$remainder % 60")
printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss"
)
subtracttimes() (
local t1sec=$(codes2seconds "$1")
local t2sec=$(codes2seconds "$2")
printf "%s" $(bc <<< "$t2sec - $t1sec")
)
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
for range in "$arr3[@]"
do
duration=$(subtracttimes "$range%% -->*" "$range##*--> ")
printf "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
done
The codes2seconds
function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc
for the conversion into total number of seconds.
The seconds2codes
function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.
The subtracttimes
function converts the two parameters to fractional seconds then asks bc
for their difference.
The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg
call to match your sample output.
Results:
ffmpeg -i movie.mp4 -ss 00:00:22.180 -t 3.420 -async 1 cut.mp4
ffmpeg -i movie.mp4 -ss 00:00:24.070 -t 3.720 -async 1 cut.mp4
add a comment |Â
up vote
1
down vote
accepted
Given an array arr3 that contains sample data:
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.
# converts HH:MM:SS.sss to fractional seconds
codes2seconds() (
local hh=$1%%:*
local rest=$1#*:
local mm=$rest%%:*
local ss=$rest#*:
printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss")
)
# converts fractional seconds to HH:MM:SS.sss
seconds2codes() (
local seconds=$1
local hh=$(bc <<< "scale=0; $seconds / 3600")
local remainder=$(bc <<< "$seconds % 3600")
local mm=$(bc <<< "scale=0; $remainder / 60")
local ss=$(bc <<< "$remainder % 60")
printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss"
)
subtracttimes() (
local t1sec=$(codes2seconds "$1")
local t2sec=$(codes2seconds "$2")
printf "%s" $(bc <<< "$t2sec - $t1sec")
)
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
for range in "$arr3[@]"
do
duration=$(subtracttimes "$range%% -->*" "$range##*--> ")
printf "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
done
The codes2seconds
function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc
for the conversion into total number of seconds.
The seconds2codes
function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.
The subtracttimes
function converts the two parameters to fractional seconds then asks bc
for their difference.
The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg
call to match your sample output.
Results:
ffmpeg -i movie.mp4 -ss 00:00:22.180 -t 3.420 -async 1 cut.mp4
ffmpeg -i movie.mp4 -ss 00:00:24.070 -t 3.720 -async 1 cut.mp4
add a comment |Â
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Given an array arr3 that contains sample data:
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.
# converts HH:MM:SS.sss to fractional seconds
codes2seconds() (
local hh=$1%%:*
local rest=$1#*:
local mm=$rest%%:*
local ss=$rest#*:
printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss")
)
# converts fractional seconds to HH:MM:SS.sss
seconds2codes() (
local seconds=$1
local hh=$(bc <<< "scale=0; $seconds / 3600")
local remainder=$(bc <<< "$seconds % 3600")
local mm=$(bc <<< "scale=0; $remainder / 60")
local ss=$(bc <<< "$remainder % 60")
printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss"
)
subtracttimes() (
local t1sec=$(codes2seconds "$1")
local t2sec=$(codes2seconds "$2")
printf "%s" $(bc <<< "$t2sec - $t1sec")
)
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
for range in "$arr3[@]"
do
duration=$(subtracttimes "$range%% -->*" "$range##*--> ")
printf "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
done
The codes2seconds
function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc
for the conversion into total number of seconds.
The seconds2codes
function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.
The subtracttimes
function converts the two parameters to fractional seconds then asks bc
for their difference.
The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg
call to match your sample output.
Results:
ffmpeg -i movie.mp4 -ss 00:00:22.180 -t 3.420 -async 1 cut.mp4
ffmpeg -i movie.mp4 -ss 00:00:24.070 -t 3.720 -async 1 cut.mp4
Given an array arr3 that contains sample data:
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.
# converts HH:MM:SS.sss to fractional seconds
codes2seconds() (
local hh=$1%%:*
local rest=$1#*:
local mm=$rest%%:*
local ss=$rest#*:
printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss")
)
# converts fractional seconds to HH:MM:SS.sss
seconds2codes() (
local seconds=$1
local hh=$(bc <<< "scale=0; $seconds / 3600")
local remainder=$(bc <<< "$seconds % 3600")
local mm=$(bc <<< "scale=0; $remainder / 60")
local ss=$(bc <<< "$remainder % 60")
printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss"
)
subtracttimes() (
local t1sec=$(codes2seconds "$1")
local t2sec=$(codes2seconds "$2")
printf "%s" $(bc <<< "$t2sec - $t1sec")
)
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
for range in "$arr3[@]"
do
duration=$(subtracttimes "$range%% -->*" "$range##*--> ")
printf "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
done
The codes2seconds
function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc
for the conversion into total number of seconds.
The seconds2codes
function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.
The subtracttimes
function converts the two parameters to fractional seconds then asks bc
for their difference.
The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg
call to match your sample output.
Results:
ffmpeg -i movie.mp4 -ss 00:00:22.180 -t 3.420 -async 1 cut.mp4
ffmpeg -i movie.mp4 -ss 00:00:24.070 -t 3.720 -async 1 cut.mp4
answered Feb 27 at 2:00
Jeff Schaller
31.2k846105
31.2k846105
add a comment |Â
add a comment |Â
up vote
1
down vote
Well, for time codes date
usually pops into my mind. Not the most elegant script, but it does the job...
I assume from your question, that you have beginning and end times already read into respective arrays and will use start
and end
as these values here and do it step by step:
#!/bin/bash
start=00:00:22.180
end=00:00:24.070
#convert timestamps to epoch time in nano seconds
start_ns="$(date -u -d"$start" +%s%N)"
end_ns="$(date -u -d"$end" +%s%N)"
difference="$(($end_ns-$start_ns))"
#date does not read epoch time in nanoseconds,
#so it must be converted by division vith 10^9 before display
#date_diff is accurate up to full seconds
#use UTC time (-u) to avoid problems with time zones
date_diff="$( date -u -d@$((difference/1000000000)) +%H:%M:%S )"
#take care of milliseconds as remainder of division by 10^9 and correction by 10^6
ms_diff="$(( $difference%1000000000/1000000 ))"
#combine output to create desired format
echo "$date_diff"."$ms_diff"
Result
bash script.sh
00:00:01.890
All in one line
echo "$(date -u -d@"$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))/1000000000 ))" +%H:%M:%S)"."$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))%1000000000/1000000 ))"
Please note that I am not aware if nanosecond time in date
is a POSIX standard feature.
Thanks for the solution, worked for me!
â tjallo
Feb 26 at 19:11
add a comment |Â
up vote
1
down vote
Well, for time codes date
usually pops into my mind. Not the most elegant script, but it does the job...
I assume from your question, that you have beginning and end times already read into respective arrays and will use start
and end
as these values here and do it step by step:
#!/bin/bash
start=00:00:22.180
end=00:00:24.070
#convert timestamps to epoch time in nano seconds
start_ns="$(date -u -d"$start" +%s%N)"
end_ns="$(date -u -d"$end" +%s%N)"
difference="$(($end_ns-$start_ns))"
#date does not read epoch time in nanoseconds,
#so it must be converted by division vith 10^9 before display
#date_diff is accurate up to full seconds
#use UTC time (-u) to avoid problems with time zones
date_diff="$( date -u -d@$((difference/1000000000)) +%H:%M:%S )"
#take care of milliseconds as remainder of division by 10^9 and correction by 10^6
ms_diff="$(( $difference%1000000000/1000000 ))"
#combine output to create desired format
echo "$date_diff"."$ms_diff"
Result
bash script.sh
00:00:01.890
All in one line
echo "$(date -u -d@"$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))/1000000000 ))" +%H:%M:%S)"."$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))%1000000000/1000000 ))"
Please note that I am not aware if nanosecond time in date
is a POSIX standard feature.
Thanks for the solution, worked for me!
â tjallo
Feb 26 at 19:11
add a comment |Â
up vote
1
down vote
up vote
1
down vote
Well, for time codes date
usually pops into my mind. Not the most elegant script, but it does the job...
I assume from your question, that you have beginning and end times already read into respective arrays and will use start
and end
as these values here and do it step by step:
#!/bin/bash
start=00:00:22.180
end=00:00:24.070
#convert timestamps to epoch time in nano seconds
start_ns="$(date -u -d"$start" +%s%N)"
end_ns="$(date -u -d"$end" +%s%N)"
difference="$(($end_ns-$start_ns))"
#date does not read epoch time in nanoseconds,
#so it must be converted by division vith 10^9 before display
#date_diff is accurate up to full seconds
#use UTC time (-u) to avoid problems with time zones
date_diff="$( date -u -d@$((difference/1000000000)) +%H:%M:%S )"
#take care of milliseconds as remainder of division by 10^9 and correction by 10^6
ms_diff="$(( $difference%1000000000/1000000 ))"
#combine output to create desired format
echo "$date_diff"."$ms_diff"
Result
bash script.sh
00:00:01.890
All in one line
echo "$(date -u -d@"$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))/1000000000 ))" +%H:%M:%S)"."$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))%1000000000/1000000 ))"
Please note that I am not aware if nanosecond time in date
is a POSIX standard feature.
Well, for time codes date
usually pops into my mind. Not the most elegant script, but it does the job...
I assume from your question, that you have beginning and end times already read into respective arrays and will use start
and end
as these values here and do it step by step:
#!/bin/bash
start=00:00:22.180
end=00:00:24.070
#convert timestamps to epoch time in nano seconds
start_ns="$(date -u -d"$start" +%s%N)"
end_ns="$(date -u -d"$end" +%s%N)"
difference="$(($end_ns-$start_ns))"
#date does not read epoch time in nanoseconds,
#so it must be converted by division vith 10^9 before display
#date_diff is accurate up to full seconds
#use UTC time (-u) to avoid problems with time zones
date_diff="$( date -u -d@$((difference/1000000000)) +%H:%M:%S )"
#take care of milliseconds as remainder of division by 10^9 and correction by 10^6
ms_diff="$(( $difference%1000000000/1000000 ))"
#combine output to create desired format
echo "$date_diff"."$ms_diff"
Result
bash script.sh
00:00:01.890
All in one line
echo "$(date -u -d@"$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))/1000000000 ))" +%H:%M:%S)"."$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))%1000000000/1000000 ))"
Please note that I am not aware if nanosecond time in date
is a POSIX standard feature.
answered Feb 26 at 17:40
Fiximan
2,941422
2,941422
Thanks for the solution, worked for me!
â tjallo
Feb 26 at 19:11
add a comment |Â
Thanks for the solution, worked for me!
â tjallo
Feb 26 at 19:11
Thanks for the solution, worked for me!
â tjallo
Feb 26 at 19:11
Thanks for the solution, worked for me!
â tjallo
Feb 26 at 19:11
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f426724%2fsubtract-two-time-codes%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
â Jeff Schaller
Feb 26 at 16:27
The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
â symcbean
Feb 26 at 17:30
1
@symcbean
date (GNU coreutils) 8.25
allows nanosecond accuracy.â Fiximan
Feb 26 at 17:51
@Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
â symcbean
Feb 26 at 21:07
@symcbean See my answer below - I found no entry in
info
regarding a nanosecond time -> human readable conversion, thus relied onbash
integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.â Fiximan
Feb 26 at 22:19