命令以毫秒为单位获取时间

Posted

技术标签:

【中文标题】命令以毫秒为单位获取时间【英文标题】:Command to get time in milliseconds 【发布时间】:2013-05-09 01:11:41 【问题描述】:

Linux 中是否有 shell 命令可以获取以毫秒为单位的时间?

【问题讨论】:

date +%s.%N 会给你纳秒,你能用它吗? @Wrikken 这不是很便携。 date +"%Y%m%d.%H%M%S%3N" - 通常我使用这个命令来获取完整日期和唯一时间直到毫秒来创建临时文件名Unix bash 脚本。如果您的系统无法处理毫秒,您可以分别使用 3 到 6 和 9 达到微秒或纳秒。 试试date -Ins 【参考方案1】:

date +"%T.%N" 返回当前时间,单位为纳秒。

06:46:41.431857000

date +"%T.%6N" 返回当前时间,以纳秒四舍五入到前 6 位,即微秒。

06:47:07.183172

date +"%T.%3N" 返回当前时间,纳秒四舍五入到前 3 位,即毫秒。

06:47:42.773

一般来说,date 命令格式的每个字段都可以指定一个可选的字段宽度。

【讨论】:

%xN: 字段宽度不错! date +"%Y%m%d.%H%M%S%3N" 毫秒。 我想这是一个比标记为正确的答案更好的答案。【参考方案2】:

date +%s%N 返回秒数 + 当前纳秒。

因此,echo $(($(date +%s%N)/1000000)) 是您所需要的。

例子:

$ echo $(($(date +%s%N)/1000000))
1535546718115

date +%s 返回自纪元以来的秒数,如果有用的话。

【讨论】:

不适用于 Mac OS,因为 %N 不受 date 支持 问题是要求 Linux 命令。 @alper 的答案适用于 GNU coreutils 的日期命令。 GNUtize 你的 OSX:Install and Use GNU Command Line Tools on Mac OS X date +%s%3N 更快(基于@michael-defort 的回答) 在 OSX 上,您需要使用 MacPorts 或 Homebrew 安装 GNU 版本的 date 作为 coreutils 的一部分 - 然后使用 gdate 命令。看到这个问题:***.com/questions/9804966/… 虽然 date +%s%3N 看起来更简单或者更好,但是在其他一些偏移量计算中使用它会导致时间戳减少 1 毫秒!但是这个解决方案非常适合偏移计算【参考方案3】:

纳米是 10-9 和毫 10-3。因此,我们可以使用纳秒的前三个字符来获取毫秒:

date +%s%3N

来自man date

%N 纳秒 (000000000..999999999)

%s 秒自 1970-01-01 00:00:00 UTC

来源:Server Fault的How do I get the current Unix time in milliseconds in Bash?

【讨论】:

我为@Peter Mortensen 在我的一篇帖子中做了他出色的积极阅读之一感到非常自豪:) 谢谢!!【参考方案4】:

在 OS X 上,date 不支持%N 标志,我建议使用Homebrew 安装coreutils。这将使您能够访问名为 gdate 的命令,该命令的行为与 Linux 系统上的 date 一样。

brew install coreutils

要获得更“原生”的体验,您可以随时将其添加到您的.bash_aliases

alias date='gdate'

然后执行

$ date +%s%N

【讨论】:

【参考方案5】:

这是一个以毫秒为单位获取时间的 Linux 便携式 hack:

#!/bin/sh
read up rest </proc/uptime; t1="$up%.*$up#*."
sleep 3    # your command
read up rest </proc/uptime; t2="$up%.*$up#*."

millisec=$(( 10*(t2-t1) ))
echo $millisec

输出是:

3010

这是一个非常便宜的操作,它适用于 shell 内部和 procfs。

【讨论】:

目前只有一个在 Xeon Phi BusyBox v1.27.0 (2017-09-27 13:20:28 EDT) MicroOS 上运行 - 很乐意投三票! 我正在使用 BusyBox 1.27.1。也是唯一可行的解​​决方案。【参考方案6】:

date 命令在 OS X 上没有提供毫秒,所以使用了 python 的别名

millis()  python -c "import time; print(int(time.time()*1000))"; 

alias millis='python -c "import time; print(int(time.time()*1000))"'

编辑:遵循@CharlesDuffy 的评论。 分叉任何子进程都需要额外的时间。

$ time date +%s%N
1597103627N
date +%s%N  0.00s user 0.00s system 63% cpu 0.006 total

Python is still improving it's VM start time,它的速度不如提前编译的代码(如date)。

在我的机器上,大约需要 30 毫秒 - 60 毫秒(即 date 所用 6 毫秒的 5x-10 倍)

$ time python -c "import time; print(int(time.time()*1000))"
1597103899460
python -c "import time; print(int(time.time()*1000))"  0.03s user 0.01s system 83% cpu 0.053 total

我认为awkpython 轻量级,所以awk 的时间范围为 6 毫秒到 12 毫秒(即日期的 1 倍到 2 倍):

$ time awk '@load "time"; BEGINprint int(1000 * gettimeofday())'
1597103729525
awk '@load "time"; BEGINprint int(1000 * gettimeofday())'  0.00s user 0.00s system 74% cpu 0.010 total

【讨论】:

...然而,一旦你 fork()ed 关闭了一个单独的进程,execed 你的 Python 解释器,让它加载它的库/否则初始化,写它的结果,然后退出,该结果将不再准确。【参考方案7】:

在大多数情况下,其他答案可能就足够了,但当我在 BusyBox 系统上遇到问题时,我想我会加两分钱。

有问题的系统不支持%N 格式选项,并且没有 Python 或 Perl 解释器。

经过多次挠头,我们(感谢戴夫!)想出了这个:

adjtimex | awk '/(time.tv_sec|time.tv_usec):/  printf("%06d", $2) '

它从adjtimex 的输出中提取秒和微秒(通常用于设置系统时钟的选项)并在没有新行的情况下打印它们(因此它们粘在一起)。请注意,微秒字段必须预先填充零,但这不会影响超过六位数的秒字段。由此,将微秒转换为毫秒应该是微不足道的。

如果你需要一个尾随的新行(也许是因为它看起来更好)然后尝试

adjtimex | awk '/(time.tv_sec|time.tv_usec):/  printf("%06d", $2) ' && printf "\n"

另请注意,这需要adjtimexawk 可用。如果没有,那么使用 BusyBox,您可以使用以下命令在本地指向它们:

ln -s /bin/busybox ./adjtimex
ln -s /bin/busybox ./awk

然后调用上面的为

./adjtimex | ./awk '/(time.tv_sec|time.tv_usec):/  printf("%06d", $2) '

当然你也可以把它们放在你的PATH

编辑:

以上内容适用于我的 BusyBox 设备。在 Ubuntu 上我尝试了同样的事情并意识到 adjtimex 有不同的版本。在 Ubuntu 上,这可以输出以秒为单位的时间,小数点为微秒(包括尾随的新行)

sudo apt-get install adjtimex
adjtimex -p | awk '/raw time:/  print $6 '

不过,我不会在 Ubuntu 上这样做。我会使用date +%s%N

【讨论】:

哇,不错的选择!确实你的命令有效,但我不知道为什么。我在哪里可以找到 awk 命令的文档?!你到底是怎么知道如何构建字符串以从 adjtimex 输出中提取所需信息的? 很棒的busybox解决方案 如果有可能自己编译 Busybox,启用“CONFIG_FEATURE_DATE_NANO”将是另一种方法。【参考方案8】:

用时间和时区显示日期

日期 +"%d-%m-%Y %T.%N %Z"

输出:22-04-2020 18:01:35.970289239 IST

【讨论】:

【参考方案9】:

纯 bash 解决方案

bash 5.0 (released on 7 Jan 2019) 开始,您可以使用内置变量EPOCHREALTIME,其中包含自纪元以来的秒数,包括精确到微秒 (μs) 的小数位(echo $EPOCHREALTIME 打印一些东西比如1547624774.371215)。通过删除. 和最后三个位置我们得到毫秒:

任意使用

(( t = $EPOCHREALTIME/./ / 1000 ))

或类似的东西

t=$EPOCHREALTIME/./
t=$t%???

无论哪种方式,t 都会类似于 1547624774371

【讨论】:

【参考方案10】:

我只是想在Alper's answer 中添加我必须做些什么才能让这些东西正常工作:

在 Mac 上,您需要 brew install coreutils,因此我们可以使用 gdate。否则在 Linux 上,它只是 date。此功能将帮助您对命令进行计时,而无需创建临时文件或任何东西:

function timeit() 
    start=`gdate +%s%N`
    bash -c $1
    end=`gdate +%s%N`
    runtime=$(((end-start)/1000000000.0))
    echo " seconds"

您可以将它与字符串一起使用:

timeit 'tsc --noEmit'

【讨论】:

我喜欢这个解决方案,但我对millis 更感兴趣。我将此功能移植到我在 ubuntu 中的 .bashrc:function timeit () start=$(date +%s%N); $*; end=$(date +%s%N); runtime=$(((end-start)/1000000)); echo "$runtime ms" 【参考方案11】:

Perl 可用于此目的,即使在 AIX 等特殊平台上也是如此。示例:

#!/usr/bin/perl -w

use strict;
use Time::HiRes qw(gettimeofday);

my ($t_sec, $usec) = gettimeofday ();
my $msec= int ($usec/1000);

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
    localtime ($t_sec);

printf "%04d-%02d-%02d %02d:%02d:%02d %03d\n",
    1900+$year, 1+$mon, $mday, $hour, $min, $sec, $msec;

【讨论】:

【参考方案12】:

这样的 Python 脚本:

import time
cur_time = int(time.time()*1000)

【讨论】:

这不会返回毫秒数,这将返回以毫秒表示的秒数。一切都将是 $SECONDS000 @kilianc maoyang的Python代码提供毫秒。 @jlliagre:但实际时间分辨率是否优于 16-17 毫秒(1/60 秒)? 是的,Python 的 time.time() 至少在 macOS 上返回浮点数到小数点后 6 位。【参考方案13】:

当您从 4.1 版开始使用 GNU AWK 时,您可以加载时间库并执行以下操作:

$ awk '@load "time"; BEGINprintf "%.6f", gettimeofday()'

这将以亚秒精度打印自 1970-01-01T00:00:00 以来的当前时间(以秒为单位)。

the_time = gettimeofday() 返回自 1970-01-01 UTC 以来经过的时间(以秒为单位)作为浮点值。如果该平台时间不可用,返回-1并设置ERRNO返回的时间应该是亚秒级的精度,但实际精度可能因平台而异。如果标准 C gettimeofday() 系统调用在这个平台上可用,那么它只返回值。否则,如果在 MS-Windows 上,它会尝试使用 GetSystemTimeAsFileTime()

来源:GNU awk manual

在 Linux 系统上,标准 C 函数 getimeofday() 以微秒精度返回时间。

【讨论】:

特别是 GAWK,对吧?我在常规 AWK 上尝试过,但失败了。【参考方案14】:

我想从 bash 生成值并在 Java 代码中使用该值转换回日期(java.util)。

以下命令适用于我在 bash 文件中生成值:

date +%s000

【讨论】:

很好。不过,我建议我们不要使用java.util.Date。该课程设计不良且早已过时。而是使用来自java.time, the modern Java date and time API 的Instant。那么你只需要 bash 中的 date %+s 和 Java 中的 Instant.ofEpochSecond()【参考方案15】:

打印小数秒:

start=$(($(date +%s%N)/1000000)) \
    && sleep 2 \
    && end=$(($(date +%s%N)/1000000)) \
    && runtime=$((end - start))

divisor=1000 \
    && foo=$(printf "%s.%s" $(( runtime / divisor )) $(( runtime % divisor ))) \
    && printf "runtime %s\n" $foo # in bash integer cannot cast to float

输出:runtime 2.3

【讨论】:

以上是关于命令以毫秒为单位获取时间的主要内容,如果未能解决你的问题,请参考以下文章

如何从日期对象python获取以毫秒(秒后3位小数)为单位的时间值?

如何以毫秒为单位获取当前时间?

如何在 PHP 中以毫秒为单位获取当前时间?

如何像 Java 一样获取自 1970 年以来的当前时间戳(以毫秒为单位)

以毫秒为单位获取时间来分析函数持续时间

如何以毫秒为单位获取firebase服务器的当前时间戳?