fin*_*oot 20 shell-script date posix timestamps time
我刚刚注意到,POSIXdate似乎没有%s或%N格式项。所以我不能使用那些。在我的 shell 脚本中获取纪元时间戳的替代方法是什么?
Sté*_*las 31
对于整数秒的纪元时间,则为:
\nawk \'BEGIN{srand(); print srand()}\'\nRun Code Online (Sandbox Code Playgroud)\n或者:
\nawk \'BEGIN{print srand(srand())}\'\nRun Code Online (Sandbox Code Playgroud)\n与POSIXawk一样,srand()不带参数使用当前时间作为伪随机生成器的种子。它还返回前一个种子,因此srand()上面的第二个返回用于前一个\xc2\xb9 的纪元时间。
您可以通过以下方式获得小数部分:
\necho|LC_ALL=C TZ=UTC0 diff -u /dev/null - |sed -n \'2s/.*\\(\\.[0-9]*\\).*/\\1/p\'\nRun Code Online (Sandbox Code Playgroud)\nPOSIX 确实指定了 的输出格式diff -u,并且当文件为-.
但是,自从您在获得输出之前调用以来,可能已经过去了数千甚至数百万纳秒awk,甚至可能不是同一秒。<epochtime> % 60不过,如果您愿意,可以通过与标头中 (UTC) 时间戳的第二部分进行比较来检查情况diff是否如此。
\xc2\xb9 关于该awk解决方案,请注意 POSIX 过去并没有用那么多话来表达它。不久前我确实对 POSIX 的措辞不明确提出了反对,并指出在当今时代强制实现使用这种可怜的熵源是不合理的。相反,决议明确要求srand()使用纪元时间。
ilk*_*chu 13
编写一个 C 程序来调用time()并打印结果。借用函数规范中的time()示例程序,我们将其称为例如seconds.c:
#include <stdio.h>
#include <stdint.h>
#include <time.h>
int main(void)
{
time_t t = time(NULL);
printf("%ju\n", (uintmax_t) t);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并用 进行编译c99 -o seconds seconds.c。(如果我正确地阅读了规范,那应该是编译它的标准方法。)
或者,您可以获取分解的日期并计算秒数。这相对容易,因为每一天的长度都是 86400 秒。我们确实需要去掉某些值的前导零,这样 shell 算术就不会将它们视为八进制:
作为外壳函数:
epochtime() {
eval "$(date -u +'y=%Y j=%j h=%H m=%M s=%S')"
s=${s#0}
m=${m#0}
h=${h#0}
j=${j#0}
j=${j#0}
t=$(( ((y-1970)*365 + (y-1969)/4 + j - 1)*86400 + h*3600 + m*60 + s))
echo "$t"
}
Run Code Online (Sandbox Code Playgroud)
闰年计算注意事项:纪元后的第一个闰年是 1972 年, (1972-1969)/4 = 3/4 = 0 ,而 (1973-1969)/4 = 4/4 = 1 (依赖于整数截断)。因此 (year-1969)/4 给出了当前年份之前的闰年数。今年可能的闰日包含在%j值“一年中的某一天”中。该数字从 1 开始计数,但我们想要的是经过的完整天数,因此表达式中需要负一。
您可以使用自定义格式字符串来完成此操作date,该字符串为自纪元以来的秒数内的 POSIX 公式生成 shell 算术表达式:
secs=$((`TZ=GMT0 date \
+"((%Y-1600)*365+(%Y-1600)/4-(%Y-1600)/100+(%Y-1600)/400+1%j-1000-135140)\
*86400+(1%H-100)*3600+(1%M-100)*60+(1%S-100)"`))
Run Code Online (Sandbox Code Playgroud)
这种方法取自https://www.etalabs.net/sh_tricks.html