这是我想如何使用它的一个示例,尽管它不能按原样工作:
todate=2013-07-18
cond=2013-07-15
if [ $todate -ge $cond ];
then
break
fi
我怎样才能达到预期的效果?
#1 楼
正确的答案仍然缺失:todate=$(date -d 2013-07-18 +%s)
cond=$(date -d 2014-08-19 +%s)
if [ $todate -ge $cond ];
then
break
fi
请注意,这需要GNU日期。 BSD
date
的等效date
语法(如默认情况下在OSX中找到的)为date -j -f "%F" 2014-08-19 +"%s"
评论
Donno为什么有人不赞成这一点,它非常准确,并且不涉及串联丑陋的字符串。将您的日期转换为Unix时间戳(以秒为单位),比较Unix时间戳。
– Nicholi
2015年5月2日23:16
我认为,此解决方案的主要优点是,您可以轻松进行加法或减法。例如,我想有一个x秒的超时时间,但是我的第一个想法(超时= $(`日期+%Y%m%d%H%M%S` + 500))显然是错误的。
– iGEL
18年7月20日在9:59
您可以在日期-d 2013-07-18中加上毫微秒的精度+%s%N
–本征场
19年5月31日在9:43
#2 楼
可以使用标准的字符串比较来比较[以年,月,日格式的字符串的时间顺序]。date_a=2013-07-18
date_b=2013-07-15
if [[ "$date_a" > "$date_b" ]] ;
then
echo "break"
fi
,当[使用YYYY的字符串时-MM-DD格式]按字母顺序排序*,也按时间顺序排序*。
(*-排序或比较)
案件。耶!
评论
这里的else分支在哪里?
–弗拉基米尔·德斯波托维奇(Vladimir Despotovic)
16 Dec 15'在14:12
这是在Sierra MacOS上对我有用的唯一解决方案
–弗拉基米尔·德斯波托维奇(Vladimir Despotovic)
16 Dec 15'在14:22
这比我对if [$(sed -e s /-// g <<< $ todate)-ge $(sed -e s /-/// g <<< $ cond)]的解决方案更简单; …此日期格式旨在使用标准字母数字排序进行排序,或者用于-剥离和数字排序。
–ctrl-alt-delor
17年4月8日在17:59
这是这里最明智的答案
– Ed Randall
19年2月23日在11:34
使用此答案,由于它不依赖外部命令,因此它更加健壮。
–BitByteDog
20年6月13日在22:20
#3 楼
您缺少用于比较的日期格式:#!/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
您也缺少循环结构,您打算如何获得更多日期?
评论
这不适用于macOS附带的日期。
– Flimm
16 Dec 8'在9:49
date -d是非标准的,不适用于典型的UNIX。在BSD上,它甚至尝试设置龙骨值DST。
–schily
18/12/7在10:13
如果您在macOS上使用gdate,则上述方法有效,它可以在brew中使用。
–slm♦
20-2-11在7:37
#4 楼
这不是循环结构的问题,而是数据类型的问题。那些日期(
todate
和cond
)是字符串,而不是数字,因此不能使用test
的“ -ge”运算符。 (请记住,方括号表示法等效于命令test
。)您可以为日期使用不同的表示法,以便它们是整数。例如:
date +%Y%m%d
将在2013年7月15日产生一个像20130715的整数。然后,您可以将日期与“ -ge”和等效运算符进行比较。
更新:如果给出了日期(例如,您正在从2013-07-13格式的文件中读取日期),则可以使用tr轻松对其进行预处理。
$ echo "2013-07-15" | tr -d "-"
20130715
#5 楼
运算符-ge
仅适用于整数,您的日期不是。如果脚本是bash或ksh或zsh脚本,则可以使用
<
运算符。在破折号或其他不超过POSIX标准的shell中,此运算符不可用。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
进行比较。评论
这个bash中的else分支在哪里?
–弗拉基米尔·德斯波托维奇(Vladimir Despotovic)
16 Dec 15'在14:12
这似乎是最正确的答案。很有帮助!
– Mojtaba Rezaeian
18-10-21在0:50
#6 楼
我将字符串转换为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
评论
这不适用于macOS随附的日期。
– Flimm
16 Dec 8'在9:50
似乎与unix.stackexchange.com/a/170982/100397相同,该信息在您发布之前发布了一段时间
–roaima
17年4月8日在16:02
#7 楼
标题为文章的文章中也提供了这种方法:unix.com中BASH中的简单日期和时间计算。这些功能摘自该线程中的脚本!
date2stamp () {
date --utc --date "" +%s
}
dateDiff (){
case in
-s) sec=1; shift;;
-m) sec=60; shift;;
-h) sec=3600; shift;;
-d) sec=86400; shift;;
*) sec=86400;;
esac
dte1=$(date2stamp )
dte2=$(date2stamp )
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"
评论
这不适用于macOS随附的日期。
– Flimm
16 Dec 8'在9:51
如果您通过brew在MacOS上安装gdate,则可以通过将date更改为gdate来轻松地修改其工作方式。
–slm♦
18-10-8在20:40
这个答案对我的案子很有帮助。它应该评分!
– Mojtaba Rezaeian
18-10-21在0:40
#8 楼
bash的具体答案
由于我喜欢减少叉子,bash确实允许很多技巧,所以我的目的是:
todate=2013-07-18
cond=2013-07-15
那么,现在:
{ read todate; read cond ;} < <(date -f - +%s <<<"$todate"$'\n'"$cond")
这将仅使用一个fork重新填充两个变量
$todate
和$cond
,其中date -f -
的输出将以stdio读取一个日期最后,您可以使用
((todate>=cond))&&break
或作为函数:
myfunc() {
local todate cond
{ read todate
read cond
} < <(
date -f - +%s <<<""$'\n'""
)
((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
}
Nota为了防止像
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
如果在循环之外。
或使用shell-connector bash函数:
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
}
评论
分析bash很好地演示了如何使用date -f-可以减少资源需求。
– F. Hauri
17年2月13日在0:02
#9 楼
日期是字符串,不是整数;您不能将它们与标准算术运算符进行比较。如果保证分隔符为
-
,则可以使用一种方法:IFS=-
read -ra todate <<<"$todate"
read -ra cond <<<"$cond"
for ((idx=0;idx<=numfields;idx++)); do
(( todate[idx] > cond[idx] )) && break
done
unset IFS
此功能可以追溯到
bash 2.05b.0(1)-release
。#10 楼
您还可以使用mysql的内置函数比较日期。结果以天为单位。from_date="2015-01-02"
date_today="2015-03-10"
diff=$(mysql -u${DBUSER} -p${DBPASSWORD} -N -e"SELECT DATEDIFF('${date_today}','${from_date}');")
只需根据您的变量插入
$DBUSER
和$DBPASSWORD
的值。#11 楼
FWIW:在Mac上,似乎只将“ 2017-05-05”之类的日期输入到日期中,会将当前时间附加到该日期上,并且每次将其转换为纪元时间时,都会得到不同的值。为了获得固定日期的更一致的纪元时间,包括小时,分钟和秒的虚拟值:date -j -f "%Y-%m-%d %H:%M:%S" "2017-05-05 00:00:00" +"%s"
这可能是奇怪的,仅限于日期版本已随macOS一起提供。...已在macOS 10.12.6上进行了测试。
#12 楼
回显@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
#13 楼
该比较不适用于带连字符的日期字符串的原因是shell假定前导0的数字是八进制,在这种情况下为月份“ 07”。已经提出了各种解决方案,但是最快和最简单的方法是删除连字符。 Bash具有字符串替换功能,可以快速简便地进行比较,然后可以将其作为算术表达式执行:todate=2013-07-18
cond=2013-07-15
if (( ${todate//-/} > ${cond//-/} ));
then
echo larger
fi
#14 楼
到目前为止,似乎所有或大多数答案都假设您可以指定日期格式(该问题未明确指定一种或另一种方式),或者假定您具有日期命令等功能丰富的版本。 br />有时候,您无法控制日期的格式(例如SSL证书的失效日期,其中日期以月份名称缩写表示),并且您无权访问更高级的date命令。因此,尽管此解决方案并不完全通用,但它确实可以在Linux,Solaris和FreeBSD上的香草bash外壳上运行,并且可以处理月份名称(从https://stackoverflow.com/questions/15252383/ Unix将月份名称转换为数字):#!/usr/bin/bash
function monthnumber {
month=$(echo ${1:0:3} | tr '[a-z]' '[A-Z]')
MONTHS="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"
tmp=${MONTHS%%$month*}
month=${#tmp}
monthnumber=$((month/3+1))
printf "%02d\n" $monthnumber
}
# Or at the expense of some flexibility and brevity, you get more readability:
function monthnumber2 {
case $(echo ${1:0:3} | tr '[a-z]' '[A-Z]') in
JAN) monthnumber="01" ;;
FEB) monthnumber="02" ;;
MAR) monthnumber="03" ;;
APR) monthnumber="04" ;;
MAY) monthnumber="05" ;;
JUN) monthnumber="06" ;;
JUL) monthnumber="07" ;;
AUG) monthnumber="08" ;;
SEP) monthnumber="09" ;;
OCT) monthnumber="10" ;;
NOV) monthnumber="11" ;;
DEC) monthnumber="12" ;;
esac
printf "%02d\n" $monthnumber
}
TODAY=$( date "+%Y%m%d" )
echo "GET /" | openssl s_client -connect github.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > tmp.pem
cert_expiry_date=$(openssl x509 -in tmp.pem -noout -enddate | cut -d'=' -f2)
month_name=$(echo $cert_expiry_date | cut -d' ' -f1)
month_number=$( monthnumber $month_name )
cert_expiration_datestamp=$( echo $cert_expiry_date | awk "{printf \"%d%02d%02d\",$4,\"${month_number}\",$2}" )
echo "compare: [ $cert_expiration_datestamp -gt $TODAY ]"
if [ $cert_expiration_datestamp -gt $TODAY ] ; then
echo "all ok, the cert expiration date is in the future."
else
echo "WARNING: cert expiration date is in the past."
fi
评论
您想循环播放什么?您是说条件式而不是循环式吗?为什么标记文件?这些日期实际上是文件时间吗?
在stackoverflow上查看此内容:stackoverflow.com/questions/8116503/…