Answers:
您可以使用来获取当前的unix时间戳date "+%s"
,通过一些简单的数学运算来找到当前的四分之一小时(我的示例在中bash
),并使用以下更好的格式将其打印回date
:
curdate=`date "+%s"`
curquarter=$(($curdate - ($curdate % (15 * 60))))
date -d"@$curquarter"
@
从时间戳设置当前日期和时间的语法是迄今为止的GNU扩展,如果它在您的OS上不起作用,您可以这样做(不要忘记指定UTC,否则它将不会)工作):
date -d"1970-01-01 $curquarter seconds UTC"
以下方法无需调用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
printf
or sed
以及“不必要的” cat
vs <file确实会在运行时产生巨大差异。循环时,如我的“慢500倍”示例。。所以,date
我的意思是尽可能使用shell并允许诸如批处理之类的程序。Gilles的Left-Pad-0示例,vs printf
这是在Shell中处理日期的一种方法。首先调用date
获取组件,并用组件填充位置参数($1
,$2
等)(请注意,这是在少数情况下您确实希望使用$(…)
双引号将字符串分解为单词的一种情况)。然后对组件执行算术,测试或任何需要执行的操作。最后组装组件。
算术部分可能有点棘手,因为外壳将其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}"
也许不再重要,但是您可以尝试使用我自己的dateutils。四舍五入到分钟是通过dround
和一个负参数完成的:
dround now /-15m
=>
2012-07-11T13:00:00
或遵守您的格式:
dround now /-15m -f '%Y.%m.%d %H:%M'
=>
2012.07.11 13:00
dateutils.dround '2018-11-12 13:55' -15m
产生。2018-11-12T13:15:00
2018-11-12T13:45:00
/-15m
即向下舍入到小时数的15分钟的下一个倍数。此功能的语法更加麻烦,因为它接受的值较少,例如/ -13m不可能是因为13并非60的除数(以小时为单位的分钟数)
某些shell可以在不调用外部date
命令的情况下完成工作:
sh
a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "#$((a-a%(15*60)))"
bash a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "$((a-a%(15*60)))"
zsh 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模块可能与调用日期本身一样慢:
约会 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'
如果您可以使用两次调用日期,则此方法可以在Solaris上的bash中使用:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))"
代言编辑为:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))" | sed 's/:0$/:00/'
不确定您的确切要求。但是,如果您想在15分钟后生成时间,则可以使用date -d '+15 min'
。输出如下所示:
$ date; date -d '+15 min'
Tue Feb 22 18:12:39 IST 2011
Tue Feb 22 18:27:39 IST 2011