Subtract time using bash?
Is it possible to use bash to subtract variables containing 24-hour time?
#!/bin/bash
var1="23:30" # 11:30pm
var2="20:00" # 08:00pm
echo "$(expr $var1 - $var2)"
Running it produces the following error.
./test
expr: non-integer argument
I need the output to appear in decimal form, for example:
./test
3.5
bash date variable arithmetic
New contributor
user328302 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
Is it possible to use bash to subtract variables containing 24-hour time?
#!/bin/bash
var1="23:30" # 11:30pm
var2="20:00" # 08:00pm
echo "$(expr $var1 - $var2)"
Running it produces the following error.
./test
expr: non-integer argument
I need the output to appear in decimal form, for example:
./test
3.5
bash date variable arithmetic
New contributor
user328302 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Thanks for pointing that you. You're probably right. I've updated the question.
– user328302
yesterday
1
What are your constraints? Shell builtins only, or external programs likebcorawk?
– Mark Plotnick
yesterday
Related: unix.stackexchange.com/q/24626/315749
– fra-san
yesterday
@fra-san, the dates are static, in variables, so it's kinda confusing to usedateto solve this problem. @MarkPlotnick, no constraints, which ever method requires the least code. I'm ready to accept your Answer
– user328302
yesterday
add a comment |
Is it possible to use bash to subtract variables containing 24-hour time?
#!/bin/bash
var1="23:30" # 11:30pm
var2="20:00" # 08:00pm
echo "$(expr $var1 - $var2)"
Running it produces the following error.
./test
expr: non-integer argument
I need the output to appear in decimal form, for example:
./test
3.5
bash date variable arithmetic
New contributor
user328302 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Is it possible to use bash to subtract variables containing 24-hour time?
#!/bin/bash
var1="23:30" # 11:30pm
var2="20:00" # 08:00pm
echo "$(expr $var1 - $var2)"
Running it produces the following error.
./test
expr: non-integer argument
I need the output to appear in decimal form, for example:
./test
3.5
bash date variable arithmetic
bash date variable arithmetic
New contributor
user328302 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
user328302 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
edited yesterday
Jeff Schaller
38.5k1053125
38.5k1053125
New contributor
user328302 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
asked yesterday
user328302
262
262
New contributor
user328302 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
user328302 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
user328302 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Thanks for pointing that you. You're probably right. I've updated the question.
– user328302
yesterday
1
What are your constraints? Shell builtins only, or external programs likebcorawk?
– Mark Plotnick
yesterday
Related: unix.stackexchange.com/q/24626/315749
– fra-san
yesterday
@fra-san, the dates are static, in variables, so it's kinda confusing to usedateto solve this problem. @MarkPlotnick, no constraints, which ever method requires the least code. I'm ready to accept your Answer
– user328302
yesterday
add a comment |
Thanks for pointing that you. You're probably right. I've updated the question.
– user328302
yesterday
1
What are your constraints? Shell builtins only, or external programs likebcorawk?
– Mark Plotnick
yesterday
Related: unix.stackexchange.com/q/24626/315749
– fra-san
yesterday
@fra-san, the dates are static, in variables, so it's kinda confusing to usedateto solve this problem. @MarkPlotnick, no constraints, which ever method requires the least code. I'm ready to accept your Answer
– user328302
yesterday
Thanks for pointing that you. You're probably right. I've updated the question.
– user328302
yesterday
Thanks for pointing that you. You're probably right. I've updated the question.
– user328302
yesterday
1
1
What are your constraints? Shell builtins only, or external programs like
bc or awk ?– Mark Plotnick
yesterday
What are your constraints? Shell builtins only, or external programs like
bc or awk ?– Mark Plotnick
yesterday
Related: unix.stackexchange.com/q/24626/315749
– fra-san
yesterday
Related: unix.stackexchange.com/q/24626/315749
– fra-san
yesterday
@fra-san, the dates are static, in variables, so it's kinda confusing to use
date to solve this problem. @MarkPlotnick, no constraints, which ever method requires the least code. I'm ready to accept your Answer– user328302
yesterday
@fra-san, the dates are static, in variables, so it's kinda confusing to use
date to solve this problem. @MarkPlotnick, no constraints, which ever method requires the least code. I'm ready to accept your Answer– user328302
yesterday
add a comment |
2 Answers
2
active
oldest
votes
The date command is pretty flexible about its input. You can use that to your advantage:
#!/bin/bash
var1="23:30"
var2="20:00"
# Convert to epoch time and calculate difference.
difference=$(( $(date -d "$var1" "+%s") - $(date -d "$var2" "+%s") ))
# Divide the difference by 3600 to calculate hours.
echo "scale=2 ; $difference/3600" | bc
Output:
$ ./test.bash
3.50
add a comment |
Using only bash, with no external programs, you could do so something like this:
#!/bin/bash
# first time is the first argument, or 23:30
var1=${1:-23:30}
# second time is the second argument, or 20:00
var2=${2:-20:00}
# Split variables on `:` and insert pieces into arrays
IFS=':' read -r -a t1 <<< "$var1"
IFS=':' read -r -a t2 <<< "$var2"
# strip leading zeros (so it's not interpreted as octal
t1=("${t1[@]##0}")
t2=("${t2[@]##0}")
# check if the first time is before the second one
if (( t1[0] > t2[0] || ( t1[0] == t2[0] && t1[1] > t2[1]) ))
then
# if the minutes on the first time are less than the ones on the second time
if (( t1[1] < t2[1] ))
then
# add 60 minutes to time 1
(( t1[1] += 60 ))
# and subtract an hour
(( t1[0] -- ))
fi
# now subtract the hours and the minutes
echo $((t1[0] -t2[0] )):$((t1[1] - t2[1]))
# to get a decimal result, multiply the minutes by 100 and divide by 60
echo $((t1[0] -t2[0] )).$(((t1[1] - t2[1])*100/60))
else
echo "Time 1 should be after time 2" 2>&1
fi
Test:
$ ./script.sh
3:30
3.50
$ ./script.sh 12:10 11:30
0:40
0.66
$ ./script.sh 12:00 11:30
0:30
0.50
If you want more complex time differences, that could span different days etc, then it's probably best to use GNU date.
Wow, thanks. Would you be willing to add a few quick comments above some of the lines of code that explain what's happening?
– user328302
yesterday
@user328302: I added some comments, let me know if anything is still unclear. I also fixed a bug that wouldn't allow times like09:08(it was treated as octal)
– user000001
yesterday
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
user328302 is a new contributor. Be nice, and check out our Code of Conduct.
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f490764%2fsubtract-time-using-bash%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The date command is pretty flexible about its input. You can use that to your advantage:
#!/bin/bash
var1="23:30"
var2="20:00"
# Convert to epoch time and calculate difference.
difference=$(( $(date -d "$var1" "+%s") - $(date -d "$var2" "+%s") ))
# Divide the difference by 3600 to calculate hours.
echo "scale=2 ; $difference/3600" | bc
Output:
$ ./test.bash
3.50
add a comment |
The date command is pretty flexible about its input. You can use that to your advantage:
#!/bin/bash
var1="23:30"
var2="20:00"
# Convert to epoch time and calculate difference.
difference=$(( $(date -d "$var1" "+%s") - $(date -d "$var2" "+%s") ))
# Divide the difference by 3600 to calculate hours.
echo "scale=2 ; $difference/3600" | bc
Output:
$ ./test.bash
3.50
add a comment |
The date command is pretty flexible about its input. You can use that to your advantage:
#!/bin/bash
var1="23:30"
var2="20:00"
# Convert to epoch time and calculate difference.
difference=$(( $(date -d "$var1" "+%s") - $(date -d "$var2" "+%s") ))
# Divide the difference by 3600 to calculate hours.
echo "scale=2 ; $difference/3600" | bc
Output:
$ ./test.bash
3.50
The date command is pretty flexible about its input. You can use that to your advantage:
#!/bin/bash
var1="23:30"
var2="20:00"
# Convert to epoch time and calculate difference.
difference=$(( $(date -d "$var1" "+%s") - $(date -d "$var2" "+%s") ))
# Divide the difference by 3600 to calculate hours.
echo "scale=2 ; $difference/3600" | bc
Output:
$ ./test.bash
3.50
answered yesterday
Haxiel
1,079310
1,079310
add a comment |
add a comment |
Using only bash, with no external programs, you could do so something like this:
#!/bin/bash
# first time is the first argument, or 23:30
var1=${1:-23:30}
# second time is the second argument, or 20:00
var2=${2:-20:00}
# Split variables on `:` and insert pieces into arrays
IFS=':' read -r -a t1 <<< "$var1"
IFS=':' read -r -a t2 <<< "$var2"
# strip leading zeros (so it's not interpreted as octal
t1=("${t1[@]##0}")
t2=("${t2[@]##0}")
# check if the first time is before the second one
if (( t1[0] > t2[0] || ( t1[0] == t2[0] && t1[1] > t2[1]) ))
then
# if the minutes on the first time are less than the ones on the second time
if (( t1[1] < t2[1] ))
then
# add 60 minutes to time 1
(( t1[1] += 60 ))
# and subtract an hour
(( t1[0] -- ))
fi
# now subtract the hours and the minutes
echo $((t1[0] -t2[0] )):$((t1[1] - t2[1]))
# to get a decimal result, multiply the minutes by 100 and divide by 60
echo $((t1[0] -t2[0] )).$(((t1[1] - t2[1])*100/60))
else
echo "Time 1 should be after time 2" 2>&1
fi
Test:
$ ./script.sh
3:30
3.50
$ ./script.sh 12:10 11:30
0:40
0.66
$ ./script.sh 12:00 11:30
0:30
0.50
If you want more complex time differences, that could span different days etc, then it's probably best to use GNU date.
Wow, thanks. Would you be willing to add a few quick comments above some of the lines of code that explain what's happening?
– user328302
yesterday
@user328302: I added some comments, let me know if anything is still unclear. I also fixed a bug that wouldn't allow times like09:08(it was treated as octal)
– user000001
yesterday
add a comment |
Using only bash, with no external programs, you could do so something like this:
#!/bin/bash
# first time is the first argument, or 23:30
var1=${1:-23:30}
# second time is the second argument, or 20:00
var2=${2:-20:00}
# Split variables on `:` and insert pieces into arrays
IFS=':' read -r -a t1 <<< "$var1"
IFS=':' read -r -a t2 <<< "$var2"
# strip leading zeros (so it's not interpreted as octal
t1=("${t1[@]##0}")
t2=("${t2[@]##0}")
# check if the first time is before the second one
if (( t1[0] > t2[0] || ( t1[0] == t2[0] && t1[1] > t2[1]) ))
then
# if the minutes on the first time are less than the ones on the second time
if (( t1[1] < t2[1] ))
then
# add 60 minutes to time 1
(( t1[1] += 60 ))
# and subtract an hour
(( t1[0] -- ))
fi
# now subtract the hours and the minutes
echo $((t1[0] -t2[0] )):$((t1[1] - t2[1]))
# to get a decimal result, multiply the minutes by 100 and divide by 60
echo $((t1[0] -t2[0] )).$(((t1[1] - t2[1])*100/60))
else
echo "Time 1 should be after time 2" 2>&1
fi
Test:
$ ./script.sh
3:30
3.50
$ ./script.sh 12:10 11:30
0:40
0.66
$ ./script.sh 12:00 11:30
0:30
0.50
If you want more complex time differences, that could span different days etc, then it's probably best to use GNU date.
Wow, thanks. Would you be willing to add a few quick comments above some of the lines of code that explain what's happening?
– user328302
yesterday
@user328302: I added some comments, let me know if anything is still unclear. I also fixed a bug that wouldn't allow times like09:08(it was treated as octal)
– user000001
yesterday
add a comment |
Using only bash, with no external programs, you could do so something like this:
#!/bin/bash
# first time is the first argument, or 23:30
var1=${1:-23:30}
# second time is the second argument, or 20:00
var2=${2:-20:00}
# Split variables on `:` and insert pieces into arrays
IFS=':' read -r -a t1 <<< "$var1"
IFS=':' read -r -a t2 <<< "$var2"
# strip leading zeros (so it's not interpreted as octal
t1=("${t1[@]##0}")
t2=("${t2[@]##0}")
# check if the first time is before the second one
if (( t1[0] > t2[0] || ( t1[0] == t2[0] && t1[1] > t2[1]) ))
then
# if the minutes on the first time are less than the ones on the second time
if (( t1[1] < t2[1] ))
then
# add 60 minutes to time 1
(( t1[1] += 60 ))
# and subtract an hour
(( t1[0] -- ))
fi
# now subtract the hours and the minutes
echo $((t1[0] -t2[0] )):$((t1[1] - t2[1]))
# to get a decimal result, multiply the minutes by 100 and divide by 60
echo $((t1[0] -t2[0] )).$(((t1[1] - t2[1])*100/60))
else
echo "Time 1 should be after time 2" 2>&1
fi
Test:
$ ./script.sh
3:30
3.50
$ ./script.sh 12:10 11:30
0:40
0.66
$ ./script.sh 12:00 11:30
0:30
0.50
If you want more complex time differences, that could span different days etc, then it's probably best to use GNU date.
Using only bash, with no external programs, you could do so something like this:
#!/bin/bash
# first time is the first argument, or 23:30
var1=${1:-23:30}
# second time is the second argument, or 20:00
var2=${2:-20:00}
# Split variables on `:` and insert pieces into arrays
IFS=':' read -r -a t1 <<< "$var1"
IFS=':' read -r -a t2 <<< "$var2"
# strip leading zeros (so it's not interpreted as octal
t1=("${t1[@]##0}")
t2=("${t2[@]##0}")
# check if the first time is before the second one
if (( t1[0] > t2[0] || ( t1[0] == t2[0] && t1[1] > t2[1]) ))
then
# if the minutes on the first time are less than the ones on the second time
if (( t1[1] < t2[1] ))
then
# add 60 minutes to time 1
(( t1[1] += 60 ))
# and subtract an hour
(( t1[0] -- ))
fi
# now subtract the hours and the minutes
echo $((t1[0] -t2[0] )):$((t1[1] - t2[1]))
# to get a decimal result, multiply the minutes by 100 and divide by 60
echo $((t1[0] -t2[0] )).$(((t1[1] - t2[1])*100/60))
else
echo "Time 1 should be after time 2" 2>&1
fi
Test:
$ ./script.sh
3:30
3.50
$ ./script.sh 12:10 11:30
0:40
0.66
$ ./script.sh 12:00 11:30
0:30
0.50
If you want more complex time differences, that could span different days etc, then it's probably best to use GNU date.
edited yesterday
answered yesterday
user000001
892713
892713
Wow, thanks. Would you be willing to add a few quick comments above some of the lines of code that explain what's happening?
– user328302
yesterday
@user328302: I added some comments, let me know if anything is still unclear. I also fixed a bug that wouldn't allow times like09:08(it was treated as octal)
– user000001
yesterday
add a comment |
Wow, thanks. Would you be willing to add a few quick comments above some of the lines of code that explain what's happening?
– user328302
yesterday
@user328302: I added some comments, let me know if anything is still unclear. I also fixed a bug that wouldn't allow times like09:08(it was treated as octal)
– user000001
yesterday
Wow, thanks. Would you be willing to add a few quick comments above some of the lines of code that explain what's happening?
– user328302
yesterday
Wow, thanks. Would you be willing to add a few quick comments above some of the lines of code that explain what's happening?
– user328302
yesterday
@user328302: I added some comments, let me know if anything is still unclear. I also fixed a bug that wouldn't allow times like
09:08 (it was treated as octal)– user000001
yesterday
@user328302: I added some comments, let me know if anything is still unclear. I also fixed a bug that wouldn't allow times like
09:08 (it was treated as octal)– user000001
yesterday
add a comment |
user328302 is a new contributor. Be nice, and check out our Code of Conduct.
user328302 is a new contributor. Be nice, and check out our Code of Conduct.
user328302 is a new contributor. Be nice, and check out our Code of Conduct.
user328302 is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f490764%2fsubtract-time-using-bash%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Thanks for pointing that you. You're probably right. I've updated the question.
– user328302
yesterday
1
What are your constraints? Shell builtins only, or external programs like
bcorawk?– Mark Plotnick
yesterday
Related: unix.stackexchange.com/q/24626/315749
– fra-san
yesterday
@fra-san, the dates are static, in variables, so it's kinda confusing to use
dateto solve this problem. @MarkPlotnick, no constraints, which ever method requires the least code. I'm ready to accept your Answer– user328302
yesterday