创建函数以执行显示时间算术

时间:2019-07-02 21:19:59

标签: bash time

试图创建一个获取小时数(0-24)和分钟数(0-60)的函数,并将其加15分钟。问题是,当我尝试输入45以上的数字时,我得到的数字超过60。

创建了if语句来接受我的输入,并且如果分钟数超过60,它将从minutes变量中减去60,并将1添加到hour变量中。

预期结果是,它将超过60分钟的时间转换为1小时,其余时间转换为分钟。实际结果是,有时if then语句不能正确运行,并且if AND then语句同时执行这两种操作,或者有时我得到负数。

#!/bin/bash

read -p "Hours: " hr1
read -p "Minutes: " min1
min1=$((min1+15))

Time() {
    echo $min1
    if $min1 > 60
    then
        min1=$((min1-60))
        if $min1 < 0
            then $((min1*-1))
        fi
        hr1=$((hr1+1))
    else
        $min1 + 15
    fi
}

Time

echo $min1
echo $hr1

3 个答案:

答案 0 :(得分:2)

通过使用由Time()((分隔的shell算术表达式,可以大大简化))函数。这里的独立算术表达式仅对Bash shell有效,而对未定义的posix shell无效。

(( hr1 += min1 / 60, min1 %= 60 ))

分成两个用逗号,隔开的表达式:

hr1 += min1 / 60hr1 = hr1 + min1 / 60 min1 / 60的优先级高于加法。 Shell算术仅是整数

min1 %= 60min1 = min1 % 60 min1 / 60

的模数提醒
#!/usr/bin/env bash

read -r -p 'Hours: ' hr1
read -r -p 'Minutes: ' min1

# Bash stand-alone arithmetic expression add 15 to min1
(( min1+=15 )) 

Time() {
    echo "${min1}"
    # Two Bash stand-alone arithmetic expressions separated by ,
    # Add integer division of min1 by 60 to hr1
    # Truncate min1 to the integer division reminder of itself by 60
    (( hr1 += min1 / 60, min1 %= 60 ))
}

Time

echo "${min1}"
echo "${hr1}"

答案 1 :(得分:2)

有许多种方法可以将分钟数添加到给定的时间,然后获得所得到的小时数和分钟数。如Oliver Gaida所示,一种系统的方式是使用date函数。出于学习目的,手动转换是很好的方法,但是您将要确保自己处理增加的时间,导致时间累累到第二天。

为了处理转换的所有方面,将总时间转换为 seconds 很有用。届时,您可以执行所有必要的测试,以确定总时间是否已将小时数累积到第二天,等等。

由于您似乎只想捕获结果时间的小时和分钟,而与天数无关,因此您可以相对于每天的秒数,并且如果秒数超出了每天 seconds ,只需将模数秒数减少每天 seconds

用于更新getHM()Time()中的值的简短函数hr1(您的min1函数)可能类似于以下内容:

## function converting number of seconds to hours, minutes (discarding days)
getHM() {
    test -z "$1" && {   ## validate input given
        printf "error: insufficient arguments getHM()\n" >&2
        return 1
    }
    local secs="$1"                     ## local variables seconds
    local secsperday=$((3600 * 24))     ## seconds-per-day
    local days=$((secs / secsperday))   ## days
    (( days > 0 )) && {     ## seconds exceed seconds-per-day
        printf "error: time exceeds 24 hours, days discarded.\n" >&2
        secs=$((secs % secsperday))     ## reduce secs modulo by secsperday
    }
    hr1=$((secs / 3600))                ## update hr1 & min1 values
    min1=$(((secs - hr1 * 3600) / 60))
}

如函数中所述,它只是舍弃了任何其他天数,以返回结果的小时数(0-23)和分钟数(0-59)。

将其添加到简短示例中,您可以这样做:

#!/bin/bash

declare -i hr1=-1 min1=-1 addminutes=15     ## initialize variables

## function converting number of seconds to hours, minutes (discarding days)
getHM() {
    test -z "$1" && {   ## validate input given
        printf "error: insufficient arguments getHM()\n" >&2
        return 1
    }
    local secs="$1"                     ## local variables seconds
    local secsperday=$((3600 * 24))     ## seconds-per-day
    local days=$((secs / secsperday))   ## days
    (( days > 0 )) && {     ## seconds exceed seconds-per-day
        printf "error: time exceeds 24 hours, days discarded.\n" >&2
        secs=$((secs % secsperday))     ## reduce secs modulo by secsperday
    }
    hr1=$((secs / 3600))                ## update hr1 & min1 values
    min1=$(((secs - hr1 * 3600) / 60))
}

## loop until valid input received
while ((hr1 < 0)) || ((hr1 > 23)) || ((min1 < 0)) || ((min1 > 59)); do
    read -p "Hours: " hr1
    read -p "Minutes: " min1
done

## convert all to seconds adding desired 15 minutes
secs=$((hr1 * 3600 + (min1 + addminutes) * 60))

getHM "$secs"   ## call function to update hr1 & min1

printf "\nHours   : %d\nMinutes : %d\n" "$hr1" "$min1"

注意:,当使用算术运算符进行比较时,例如((...)),任何非整数值都将被评估为0,因此如果要验证使用仅提供 integer 输入,您需要在while完成后在read循环中执行此操作-如果不是,则将其中一个变量重置为-1检测到整数值)

使用/输出示例

无需小时调整:

$ bash gethm.sh
Hours: 23
Minutes: 44

Hours   : 23
Minutes : 59

加法导致总时间恰好在一天的开始降落:

$ bash gethm.sh
Hours: 23
Minutes: 45
error: time exceeds 24 hours, days discarded.

Hours   : 0
Minutes : 0

注意:,如果总时间导致小时数累积到第二天,则会显示错误消息。仅供参考,您可以根据需要将其删除)

示例显示滚动到新的一天后1分钟:

$ bash gethm.sh
Hours: 23
Minutes: 46
error: time exceeds 24 hours, days discarded.

Hours   : 0
Minutes : 1

仔细检查,如果您还有其他问题,请告诉我

答案 2 :(得分:1)

有了日期,这很容易。将日期转换为epoche-seconds,再加上900秒,然后转换回去。

<input name="inputName" onchange="script here"/>

23:08