Answers:
正确的答案仍然缺失:
todate=$(date -d 2013-07-18 +%s)
cond=$(date -d 2014-08-19 +%s)
if [ $todate -ge $cond ];
then
break
fi
请注意,这需要GNU日期。date
BSD 的等效语法date
(如默认情况下在OSX中找到的)是date -j -f "%F" 2014-08-19 +"%s"
timeout=$(`date +%Y%m%d%H%M%S` + 500)
)显然是错误的。
date -d 2013-07-18 +%s%N
您缺少比较的日期格式:
#!/bin/bash
todate=$(date -d 2013-07-18 +"%Y%m%d") # = 20130718
cond=$(date -d 2013-07-15 +"%Y%m%d") # = 20130715
if [ $todate -ge $cond ]; #put the loop where you need it
then
echo 'yes';
fi
您也缺少循环结构,如何计划获得更多日期?
date
用于macOS随附的产品。
date -d
是非标准的,在典型的UNIX上不起作用。在BSD上,它甚至尝试设置kenel值DST
。
可以使用标准字符串比较来比较[年,月,日格式的字符串的时间顺序]。
date_a=2013-07-18
date_b=2013-07-15
if [[ "$date_a" > "$date_b" ]] ;
then
echo "break"
fi
值得庆幸的是,当[使用YYYY-MM-DD格式的字符串]按字母顺序排序*时,它们也按时间顺序排序*。
(*-排序或比较)
在这种情况下,不需要花哨的东西。好极了!
if [ $(sed -e s/-//g <<< $todate) -ge $(sed -e s/-//g <<< $cond) ];
...的解决方案更简单。此日期格式设计为使用标准的字母数字排序进行排序,或者用于-
剥离和数字排序。
这不是循环结构的问题,而是数据类型的问题。
这些日期(todate
和cond
)是字符串,而不是数字,因此您不能使用的“ -ge”运算符test
。(请记住,方括号符号等效于命令test
。)
您可以做的是为日期使用不同的符号,以便它们是整数。例如:
date +%Y%m%d
会在2013年7月15日产生一个类似20130715的整数。然后,您可以将日期与“ -ge”和等效运算符进行比较。
更新:如果给出了日期(例如,您正在从2013-07-13格式的文件中读取日期),则可以使用tr轻松对其进行预处理。
$ echo "2013-07-15" | tr -d "-"
20130715
运算符-ge
仅适用于整数,而日期则无效。
如果您的脚本是bash或ksh或zsh脚本,则可以改用<
运算符。在破折号或其他不超过POSIX标准的外壳程序中,此运算符不可用。
if [[ $cond < $todate ]]; then break; fi
在任何shell中,都可以通过删除破折号将字符串转换为数字,同时遵守日期顺序。
if [ "$(echo "$todate" | tr -d -)" -ge "$(echo "$cond" | tr -d -)" ]; then break; fi
另外,您也可以使用传统的expr
实用程序。
if expr "$todate" ">=" "$cond" > /dev/null; then break; fi
由于在循环中调用子流程可能很慢,因此您可能更喜欢使用shell字符串处理构造进行转换。
todate_num=${todate%%-*}${todate#*-}; todate_num=${todate_num%%-*}${todate_num#*-}
cond_num=${cond%%-*}${cond#*-}; cond_num=${cond_num%%-*}${cond_num#*-}
if [ "$todate_num" -ge "$cond_num" ]; then break; fi
当然,如果您可以首先检索不带连字符的日期,则可以将其与进行比较-ge
。
我将字符串转换为unix时间戳(自1.1.1970 0:0:0以来的秒数)。这些可以轻松比较
unix_todate=$(date -d "${todate}" "+%s")
unix_cond=$(date -d "${cond}" "+%s")
if [ ${unix_todate} -ge ${unix_cond} ]; then
echo "over condition"
fi
date
用于macOS随附的。
标题为文章的文章中也提供了这种方法:unix.com的BASH中的简单日期和时间计算。
date2stamp () {
date --utc --date "$1" +%s
}
dateDiff (){
case $1 in
-s) sec=1; shift;;
-m) sec=60; shift;;
-h) sec=3600; shift;;
-d) sec=86400; shift;;
*) sec=86400;;
esac
dte1=$(date2stamp $1)
dte2=$(date2stamp $2)
diffSec=$((dte2-dte1))
if ((diffSec < 0)); then abs=-1; else abs=1; fi
echo $((diffSec/sec*abs))
}
# calculate the number of days between 2 dates
# -s in sec. | -m in min. | -h in hours | -d in days (default)
dateDiff -s "2006-10-01" "2006-10-31"
dateDiff -m "2006-10-01" "2006-10-31"
dateDiff -h "2006-10-01" "2006-10-31"
dateDiff -d "2006-10-01" "2006-10-31"
dateDiff "2006-10-01" "2006-10-31"
date
用于macOS随附的。
date
为来轻松进行修改以使其工作gdate
。
由于我喜欢减少叉子和bash确实有很多技巧,所以我的目的是:
todate=2013-07-18
cond=2013-07-15
现在好了:
{ read todate; read cond ;} < <(date -f - +%s <<<"$todate"$'\n'"$cond")
这将重新填充两个变量$todate
和$cond
,只用一把叉子,用ouptut date -f -
至极取标准输入输出读取一行一个日期。
最后,您可以打破循环
((todate>=cond))&&break
或作为功能:
myfunc() {
local todate cond
{ read todate
read cond
} < <(
date -f - +%s <<<"$1"$'\n'"$2"
)
((todate>=cond))&&return
printf "%(%a %d %b %Y)T older than %(%a %d %b %Y)T...\n" $todate $cond
}
使用bash的内置printf
wich可以将日期时间渲染为距纪元秒(请参见man bash
;-)
此脚本仅使用一个fork。
这将创建一个专用的子进程(仅一个分支):
mkfifo /tmp/fifo
exec 99> >(exec stdbuf -i 0 -o 0 date -f - +%s >/tmp/fifo 2>&1)
exec 98</tmp/fifo
rm /tmp/fifo
输入和输出打开时,可以删除fifo条目。
功能:
myDate() {
local var="${@:$#}"
shift
echo >&99 "${@:1:$#-1}"
read -t .01 -u 98 $var
}
注意为了防止类似的无用派生todate=$(myDate 2013-07-18)
,变量应由函数自己设置。为了允许自由语法(日期字符串带或不带引号),变量名称必须是最后一个参数。
然后进行日期比较:
myDate 2013-07-18 todate
myDate Mon Jul 15 2013 cond
(( todate >= cond )) && {
printf "To: %(%c)T > Cond: %(%c)T\n" $todate $cond
break
}
可能会呈现:
To: Thu Jul 18 00:00:00 2013 > Cond: Mon Jul 15 00:00:00 2013
bash: break: only meaningful in a `for', `while', or `until' loop
如果在循环之外。
wget https://github.com/F-Hauri/Connector-bash/raw/master/shell_connector.bash
要么
wget https://f-hauri.ch/vrac/shell_connector.sh
(两者并不完全相同:.sh
如果没有来源,则包含完整的测试脚本)
source shell_connector.sh
newConnector /bin/date '-f - +%s' @0 0
myDate 2013-07-18 todate
myDate "Mon Jul 15 2013" cond
(( todate >= cond )) && {
printf "To: %(%c)T > Cond: %(%c)T\n" $todate $cond
break
}
回显@Gilles答案(“ -ge运算符仅适用于整数”),这是一个示例。
curr_date=$(date +'%Y-%m-%d')
echo "$curr_date"
2019-06-20
old_date="2019-06-19"
echo "$old_date"
2019-06-19
datetime
epoch
@ mike-q在https://stackoverflow.com/questions/10990949/convert-date-time-string-to-epoch-in-bash中的答案,将整数转换为:
curr_date_int=$(date -d "${curr_date}" +"%s")
echo "$curr_date_int"
1561014000
old_date_int=$(date -d "${old_date}" +"%s")
echo "$old_date_int"
1560927600
"$curr_date"
大于(大于)"$old_date"
,但是此表达式错误地计算为False
:
if [[ "$curr_date" -ge "$old_date" ]]; then echo 'foo'; fi
...在此处明确显示:
if [[ "$curr_date" -ge "$old_date" ]]; then echo 'foo'; else echo 'bar'; fi
bar
整数比较:
if [[ "$curr_date_int" -ge "$old_date_int" ]]; then echo 'foo'; fi
foo
if [[ "$curr_date_int" -gt "$old_date_int" ]]; then echo 'foo'; fi
foo
if [[ "$curr_date_int" -lt "$old_date_int" ]]; then echo 'foo'; fi
if [[ "$curr_date_int" -lt "$old_date_int" ]]; then echo 'foo'; else echo 'bar'; fi
bar