什么时间日期值始终大于任何时间日期?

什么时间日期值始终大于任何时间日期?

什么时间日期值始终大于任何时间日期?

在脚本中,我想为变量提供一个参数duration,以便循环将永远运行,直到我终止进程:

# `duration` has a value in seconds
end=$(($(date +%s) + duration))  

while true; do
    # ...
    [ $(date +%s) -ge $end ] && break
    # ...
done

答案1

我会把它改成:

SECONDS=0

while true; do
    # ...
    [ "$duration" = forever ] || [ "$SECONDS" -lt "$duration" ] || break
    # ...
done

并且duration=forever无需担心[系统支持的最大数量是多少。

$SECONDS每秒自动递增。该功能来自 ksh,并且在zsh和中也可用bash。但请注意,每次挂钟时间的完整秒数发生变化时,$SECONDSin都会递增,因此,例如,如果在 12:00:00.999 运行,则它将在 12:00:01.000 时递增到 1,因此仅在一毫秒后。bashSECONDS=0

如果可以选择切换到zsh(不再有该错误),您可以将其更改为:

typeset -F SECONDS=0
while true; do
    # ...
    (( SECONDS < duration )) || break
    # ...
done

并使用duration=inffor 循环永远运行。这也允许分数持续时间。

答案2

斯蒂芬的方法更好,但如果你真的想与一些不可能达到的数字进行比较,你可以指定Bash 的最大值在比较中;在当前的 Linux 系统(32 位和 64 位)上,即:

end=9223372036854775807

当前版本的 GNU 甚至无法达到该值date,因为它们将年份限制为 1900 + (2 31 - 1),因此 的最大结果date +%s是 67768036191719999 (2147485547 年 12 月 31 日 23:59:59,UTC- 12)。

答案3

找到日期有效的最大值并不困难。无论如何,它只有 64 位可供测试。

#!/bin/bash

start=${1:-50}
maxint=$(( (1<<63)-1 ))
usedate="date"

for ((n=start;n>=0;n--)); do
    limit=$((1<<n))
    if [[ $limit -lt 0 ]] || [[ $limit -gt $maxint ]] ; then limit=$maxint; fi

    if [[ $usedate == "date" ]]; then
    if endtime=$(date -d @"$((end | limit))" +'<<%s>>'); then
        enderror=""
    else
        enderror="error reported"
    fi
    else
    enderror=$( printf -v endtime '%(%s)T' "$((end | limit))" >/dev/null);
    fi
    
    if [ -z "$enderror" ]; then 
    end=$((end | limit))
    fi
    printf "end=%d %x\n" "$end" "$end"

done

该限制在第 54 位之前看起来都很好,其结果是:

$ ./script 54
end=36028797018963967 7fffffffffffff

但一旦你尝试 55,结果就会变得需要更长的时间来解释(可能是一年的日期限制)。

$ ./script 55
end=67768036191691199 f0c2ab7c54e1bf

测试 printf (已经在脚本中定义,change usedate)没有给出最多 63 位的限制(end=9223372036854775807 7ffffffffffffff)。

您可以测试您的日期以找出系统上的确切限制。

答案4

有趣的是,在我的系统上,日期可以追溯到 20 亿年前! :-)

为了找到有效范围,我编写了这个小脚本:

#!/bin/bash
printdate () { TZ=UTC0 date -d@$1 ;}
limits () { # GOOD BAD
  local good=$1 bad=$2 mid
  while (( ( good > bad ? good - bad : bad - good ) >1 )) ;do
    (( mid = (good - bad) / 2  + bad )) # "(good+bad)/2" could overflow 
    printdate $mid >/dev/null 2>&1 && good=$mid || bad=$mid
  done
echo $good
printdate $good
}

((MAX=(1<<63)-1))
limits 0 $MAX
limits 0 -$MAX
Results:

# limits 0 $MAX
67768036191676799
Wed Dec 31 23:59:59 UTC 2147485547

# limits 0 -$MAX
-67768040609740800
Thu Jan  1 00:00:00 UTC -2147481748

相关内容