cod*_*ter 7 linux bash printf datetime
我们可以使用内置printf函数打印当前时间,而无需调用date像这样的外部命令,如下所示:
printf '%(%Y-%m-%d:%H:%M:%S)T %s\n' -1
# sample output: 2019-03-30:17:39:36,846
Run Code Online (Sandbox Code Playgroud)
我们如何让 printf 也打印毫秒或纳秒?在格式字符串中使用%3N或%N不起作用:
printf '%(%Y-%m-%d:%H:%M:%S,%3N)T %s\n' -1 # outputs 2019-03-30:17:38:16,%3N
printf '%(%Y-%m-%d:%H:%M:%S,%N)T %s\n' -1 # outputs 2019-03-30:17:38:16,%N
Run Code Online (Sandbox Code Playgroud)
但是, date 命令工作正常:
date +%Y-%m-%d:%H:%M:%S,%3N # gives 2019-03-30:17:39:36,846
date +%Y-%m-%d:%H:%M:%S,%N # gives 2019-03-30:17:39:36,160643077
Run Code Online (Sandbox Code Playgroud)
这是在 Red Hat Linux 7.3 版上。
$EPOCHREALTIMEEPOCHREALTIME 具有微秒级粒度的浮点值EPOCHSECONDS 自 Unix Epoch 以来的秒数简单地:
IFS=. read ESEC NSEC <<<$EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
Run Code Online (Sandbox Code Playgroud)
$EPOCHREALTIME请注意:
Run Code Online (Sandbox Code Playgroud)EPOCHREALTIME Each time this parameter is referenced, it expands to the number of seconds since the Unix Epoch (see time(3)) as a floating point value with micro-second granularity.
因此,如果我在同一行中两次要求相同的变量:
echo $EPOCHREALTIME... $EPOCHREALTIME
1572000683.886830... 1572000683.886840
Run Code Online (Sandbox Code Playgroud)
或更明确地说:
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
761893
761925
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
37
Run Code Online (Sandbox Code Playgroud)
在我的树莓派上也一样:
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
801459
801694
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
246
Run Code Online (Sandbox Code Playgroud)
因此,查询这两次构建整数部分和小数部分的分离过程可能会导致问题:(在同一行上首先访问$ EPOCHREALTIME可能给出:NNN1.999995,然后下一个:NNN2.000002。比结果将变为:NNN1.000002具有1000000微秒错误)
$EPOCHSECONDS和$EPOCHREALTIME两者一起使用不仅会导致首先提到的错误!
$EPOCHSECONDS使用time()不经常更新的$EPOCHREALTIMEcall to ,而使用 call to gettimeofday()! 所以结果可能会有很大不同:
我发现This answer to time() 和 gettimeofday() 返回不同的秒数,并有很好的解释。
如果我尝试我的主机:
epochVariableDiff () {
local errcnt=0 lasterrcnt v1 v2 v3 us vals line
while ((errcnt==0)) || ((errcnt>lasterrcnt)); do
lasterrcnt=$errcnt
printf -v vals '%(%s)T %s %s' -1 $EPOCHSECONDS $EPOCHREALTIME
IFS=$' .' read v1 v2 v3 us <<<"$vals"
[ "$v1" = "$v2" ] && [ "$v2" = "$v3" ] || ((errcnt++))
[ $errcnt -eq 1 ] && echo "$line"
printf -v line '%3d %s - %s - %s . %s' $errcnt $v1 $v2 $v3 $us
printf "%s\r" "$line"
((errcnt)) && echo "$line"
read -t ${1:-.0002}
done
}
Run Code Online (Sandbox Code Playgroud)
(
注意:我使用read -t代替sleep,因为sleep不是内置的
Nota2:您可以使用函数的参数来更改读取超时(睡眠)的值
)
这可能会导致一些愚蠢的事情:
$ epochVariableDiff .0002
0 1586851573 - 1586851573 - 1586851573 . 999894
1 1586851573 - 1586851573 - 1586851574 . 000277
2 1586851573 - 1586851573 - 1586851574 . 000686
3 1586851573 - 1586851573 - 1586851574 . 001087
4 1586851573 - 1586851573 - 1586851574 . 001502
5 1586851573 - 1586851573 - 1586851574 . 001910
6 1586851573 - 1586851573 - 1586851574 . 002309
7 1586851573 - 1586851573 - 1586851574 . 002701
8 1586851573 - 1586851573 - 1586851574 . 003108
9 1586851573 - 1586851573 - 1586851574 . 003495
10 1586851573 - 1586851573 - 1586851574 . 003899
11 1586851573 - 1586851573 - 1586851574 . 004400
12 1586851573 - 1586851573 - 1586851574 . 004898
13 1586851573 - 1586851573 - 1586851574 . 005324
14 1586851573 - 1586851573 - 1586851574 . 005720
15 1586851573 - 1586851573 - 1586851574 . 006113
16 1586851573 - 1586851573 - 1586851574 . 006526
17 1586851573 - 1586851573 - 1586851574 . 006932
18 1586851573 - 1586851573 - 1586851574 . 007324
19 1586851573 - 1586851573 - 1586851574 . 007733
19 1586851574 - 1586851574 - 1586851574 . 008144
Run Code Online (Sandbox Code Playgroud)
之前(在我的主机上)的整数部分$EPOCHREALTIME可能增加超过8000微秒$EPOCHSECONDS。
注意: 这似乎与某些错误有关,重新启动后,不同主机之间或同一主机上的结果可能会有很大差异,还有其他事情......奇怪的是,我可以在许多不同的主机(英特尔酷睿、英特尔至强、 Amd64 ..)但不是在树莓派上!?(相同的 Debian bash v5.0.3(1)-release),不同的内核版本。
正确:这不是错误!混合time()和gettimeofday()是一个错误!
所以避免同时使用两者!!!
printf "..%06.0f"注意:我使用%06.0f而不是%d确保$NSEC被解释为十进制(浮点数),(如果变量以 开头,则防止八进制解释0)。
相比:
printf "nn.%06.0f\n" 012345
nn.012345
printf "nn.%06.0f\n" 098765
nn.098765
Run Code Online (Sandbox Code Playgroud)
和
printf "nn.%d\n" 012345
nn.5349
printf "nn.%d\n" 098765
-bash: printf: 098765: invalid octal number
nn.0
Run Code Online (Sandbox Code Playgroud)
小测试:
等到下一秒,然后用微秒打印当前时间
while ! read -t .$((1000000-10#${EPOCHREALTIME#*.})) foo; do
IFS=. read ESEC NSEC <<< $EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
done
Run Code Online (Sandbox Code Playgroud)
您可以通过按结束此测试 Return
2019-10-25:13:16:46.000444
2019-10-25:13:16:47.000489
2019-10-25:13:16:48.000399
2019-10-25:13:16:49.000383
2019-10-25:13:16:50.000508
Run Code Online (Sandbox Code Playgroud)
在bash5中,您可以从 获得微秒精度EPOCHREALTIME。但是,printf它本身无法直接访问它,因此您需要自己提取微秒。
$ echo $EPOCHREALTIME; printf '%(%F:%T)T.%d\n' "$EPOCHSECONDS" "${EPOCHREALTIME#*.}"; echo $EPOCHREALTIME
1554006709.936990
2019-03-31:00:31:49.937048
1554006709.937083
Run Code Online (Sandbox Code Playgroud)
这需要一点时间,但结果似乎精确到大约 0.05 毫秒。