日期:获取当前 15 分钟间隔

日期:获取当前 15 分钟间隔

有什么方法可以使用 date 命令或类似命令获取当前 15 分钟间隔吗?

例如,像 date 这样的东西%Y.%m.%d %H:%M 会给我,我需要在从到 的时间范围内2011.02.22 10:19产生的东西。2011.02.22 10:1510:1510:29

答案1

您可以使用 获取当前的 unix 时间戳date "+%s",通过一些简单的数学计算找到当前刻钟(我的示例在 中bash),然后使用更好的格式将其打印回来date

curdate=`date "+%s"`
curquarter=$(($curdate - ($curdate % (15 * 60))))
date -d"@$curquarter"

从时间戳设置当前日期和时间的语法@是 GNU 扩展至日期,如果它不适用于您的操作系统,您可以像这样执行相同的操作(不要忘记指定 UTC,否则,它不会工作):

date -d"1970-01-01 $curquarter seconds UTC"

答案2

以下方法使得无需调用date两次。
系统调用的开销可能会使“简单”命令比 bash 在其自己的本地环境中执行相同操作慢 100 倍。

更新简单提一下我上面的评论:“慢 100 倍”。现在可以读取“500慢了很多倍”...我最近陷入了(不,是盲目地)这个问题。这是链接:构建测试文件的快速方法

eval $(date +Y=%Y\;m=%m\;d=%d\;H=%H\;M=%M)
[[ "$M" < "15" ]] && M=00 # cater for octal clash
M=$(((M/15)*15))
((M==0)) && M=00 # the math returns 0, so make it 00  
echo $Y.$m.$d $H:$M  

或者

eval $(date +Y=%Y\;m=%m\;d=%d\;H=%H\;M=%M)
if   [[ "$M" < "15" ]] ; then M=00
elif [[ "$M" < "30" ]] ; then M=15
elif [[ "$M" < "45" ]] ; then M=30
else M=45
fi
echo $Y.$m.$d $H:$M

两个版本都只会返回

2011.02.23 01:00
2011.02.23 01:15
2011.02.23 01:30
2011.02.23 01:45   

这是第一个对所有 60 个值进行 TEST 循环的循环 {00..59}

for X in {00..59} ;                         ###### TEST
do                                          ###### TEST 
  eval $(date +Y=%Y\;m=%m\;d=%d\;H=%H\;M=%M)
  M=$X                                      ###### TEST 
  [[ "$M" < "15" ]] && M=00 # cater for octal clash
  M=$(((M/15)*15))
  ((M==0)) && M=00 # the math returns 0, so make it 00  
  echo $Y.$m.$d $H:$M 
done                                        ###### TEST 

答案3

这是在 shell 中处理日期的方法。首先调用date以获取组件,并用组件填充位置参数($1$2等)(请注意,这是您确实希望$(…)在双引号之外使用以将字符串分解为单词的罕见情况之一)。然后对组件执行算术、测试或任何您需要执行的操作。最后组装组件。

算术部分可能有点棘手,因为 shell 将其0视为八进制前缀;例如,这里$(($5/15))会在整点 8 或 9 分钟时失败。由于最多有一个前导0,${5#0}对于算术来说是安全的。添加 100 然后去掉 是1在输出中获得固定位数的一种方法。

set $(date "+%Y %m %d %H %M")
m=$((100+15*(${5#0}/15)))
last_quarter_hour="$1.$2.$3 $4:${m#1}"

答案4

有些 shell 无需调用外部命令即可完成该工作date

a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "#$((a-a%(15*60)))"
a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "$((a-a%(15*60)))"
zmodload zsh/datetime; a=$EPOCHSECONDS; strftime '%Y-%m-%d %H:%M' $((a-a%(15*60)))

以上三个提供本地(非 UTC)时间。如果需要,请使用前导 TZ=UTC0。

ksh 和 bash 语法几乎相同(#ksh 中所需的除外)。 zsh 需要加载一个模块(包含在 zsh 发行版中)。

也可以使用 (GNU) awk 来完成此操作:

awk 'BEGIN{t=systime();print strftime("%Y.%m.%d %H:%M",t-t%(15*60),1)}'

如果需要本地,这将提供 UTC 结果(将最后一个更改1为)。0但是加载外部 awk 或外部 zsh 模块可能与调用 date 本身一样慢:

a=$(date +%s); date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'

一个小的可执行文件busybox可以提供类似的结果:

a=$(busybox date +%s);busybox date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'

请注意,如果 busybox 链接到 PATH 目录中的那些名称,则可以省略前导 busybox 单词。

date以上两者都busybox date将打印 UTC 时间。删除-u当地时间选项。


如果您的操作系统有更有限的日期版本(这是您必须使用的),请尝试:

a=$(date +%s); a=$(( a-a%(15*60) ))
date -d"1970-01-01 $a seconds UTC" +'%Y.%m.%d %H:%M'

或者,如果在 FreeBSD 中,请尝试:

a=$(date +%s); a=$(( a-a%(15*60) ))
date -r "$a" +'%Y.%m.%d %H:%M'

相关内容