试图创建一个获取小时数(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
答案 0 :(得分:2)
通过使用由Time()
和((
分隔的shell算术表达式,可以大大简化))
函数。这里的独立算术表达式仅对Bash shell有效,而对未定义的posix shell无效。
(( hr1 += min1 / 60, min1 %= 60 ))
分成两个用逗号,
隔开的表达式:
hr1 += min1 / 60
⇔hr1 = hr1 + min1 / 60
min1 / 60
的优先级高于加法。
Shell算术仅是整数
min1 %= 60
⇔min1 = 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