Subtract time using bash?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












5














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









share|improve this question























  • Thanks for pointing that you. You're probably right. I've updated the question.
    – user328302
    Dec 24 '18 at 12:37






  • 1




    What are your constraints? Shell builtins only, or external programs like bc or awk ?
    – Mark Plotnick
    Dec 24 '18 at 12:39










  • Related: unix.stackexchange.com/q/24626/315749
    – fra-san
    Dec 24 '18 at 12:41










  • @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
    Dec 24 '18 at 12:47















5














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









share|improve this question























  • Thanks for pointing that you. You're probably right. I've updated the question.
    – user328302
    Dec 24 '18 at 12:37






  • 1




    What are your constraints? Shell builtins only, or external programs like bc or awk ?
    – Mark Plotnick
    Dec 24 '18 at 12:39










  • Related: unix.stackexchange.com/q/24626/315749
    – fra-san
    Dec 24 '18 at 12:41










  • @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
    Dec 24 '18 at 12:47













5












5








5


1





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









share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 24 '18 at 12:57









Jeff Schaller

39k1053125




39k1053125










asked Dec 24 '18 at 12:25









user328302

262




262











  • Thanks for pointing that you. You're probably right. I've updated the question.
    – user328302
    Dec 24 '18 at 12:37






  • 1




    What are your constraints? Shell builtins only, or external programs like bc or awk ?
    – Mark Plotnick
    Dec 24 '18 at 12:39










  • Related: unix.stackexchange.com/q/24626/315749
    – fra-san
    Dec 24 '18 at 12:41










  • @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
    Dec 24 '18 at 12:47
















  • Thanks for pointing that you. You're probably right. I've updated the question.
    – user328302
    Dec 24 '18 at 12:37






  • 1




    What are your constraints? Shell builtins only, or external programs like bc or awk ?
    – Mark Plotnick
    Dec 24 '18 at 12:39










  • Related: unix.stackexchange.com/q/24626/315749
    – fra-san
    Dec 24 '18 at 12:41










  • @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
    Dec 24 '18 at 12:47















Thanks for pointing that you. You're probably right. I've updated the question.
– user328302
Dec 24 '18 at 12:37




Thanks for pointing that you. You're probably right. I've updated the question.
– user328302
Dec 24 '18 at 12:37




1




1




What are your constraints? Shell builtins only, or external programs like bc or awk ?
– Mark Plotnick
Dec 24 '18 at 12:39




What are your constraints? Shell builtins only, or external programs like bc or awk ?
– Mark Plotnick
Dec 24 '18 at 12:39












Related: unix.stackexchange.com/q/24626/315749
– fra-san
Dec 24 '18 at 12:41




Related: unix.stackexchange.com/q/24626/315749
– fra-san
Dec 24 '18 at 12:41












@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
Dec 24 '18 at 12:47




@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
Dec 24 '18 at 12:47










2 Answers
2






active

oldest

votes


















7














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





share|improve this answer




























    5














    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.






    share|improve this answer






















    • 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
      Dec 24 '18 at 12:55










    • @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
      Dec 24 '18 at 13:17










    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
    );



    );













    draft saved

    draft discarded


















    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









    7














    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





    share|improve this answer

























      7














      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





      share|improve this answer























        7












        7








        7






        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





        share|improve this answer












        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






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Dec 24 '18 at 12:59









        Haxiel

        1,337310




        1,337310























            5














            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.






            share|improve this answer






















            • 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
              Dec 24 '18 at 12:55










            • @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
              Dec 24 '18 at 13:17















            5














            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.






            share|improve this answer






















            • 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
              Dec 24 '18 at 12:55










            • @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
              Dec 24 '18 at 13:17













            5












            5








            5






            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.






            share|improve this answer














            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.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 24 '18 at 14:33

























            answered Dec 24 '18 at 12:50









            user000001

            902713




            902713











            • 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
              Dec 24 '18 at 12:55










            • @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
              Dec 24 '18 at 13:17
















            • 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
              Dec 24 '18 at 12:55










            • @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
              Dec 24 '18 at 13:17















            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
            Dec 24 '18 at 12:55




            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
            Dec 24 '18 at 12:55












            @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
            Dec 24 '18 at 13:17




            @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
            Dec 24 '18 at 13:17

















            draft saved

            draft discarded
















































            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.




            draft saved


            draft discarded














            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





















































            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






            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Displaying single band from multi-band raster using QGIS

            How many registers does an x86_64 CPU actually have?