如何以bash为单位获取当前Unix时间(以毫秒为单位)?


232

如何获得以毫秒为单位的当前Unix时间(即自1970年1月1日Unix时代以来的毫秒数)?

Answers:


264

这个:

date +%s 

将返回自纪元以来的秒数

这个:

date +%s%N

返回秒和当前的纳秒。

所以:

date +%s%N | cut -b1-13

将为您提供自纪元以来的毫秒数-当前秒数加上左三分之一的纳秒。


和从MikeyB - echo $(($(date +%s%N)/1000000))(除以1000只带来微秒)


39
我不知道削减会增加多少毫秒:-)
凯尔·布​​兰特

13
或者,如果您想在shell中完成所有操作,则避免了额外过程的昂贵开销(实际上,当%+ s + N中的位数发生变化时,我们避免了该问题):echo $(($(date +%s%N)/1000))
MikeyB 2010年

5
这就是问题所在的原理……避免使用幻数并编写您的实际含义
MikeyB 2010年

25
我认为值得注意的是,该人要求使用Unix,而不是Linux,并且当前的最高答案(日期+%s%N)在我的AIX系统上不起作用。
皮特

12
@Pete +1同为OS X和FreeBSD
ocodo

99

您可以简单地%3N将ns截断为3个最高有效数字(然后是毫秒):

$ date +%s%3N
1397392146866

这适用于例如我的kubuntu 12.04。

但是请注意,%N根据目标系统的不同,可能无法实现。例如,在嵌入式系统(buildroot rootfs,使用非HF臂交叉工具链编译)上进行的测试没有%N

$ date +%s%3N
1397392146%3N

(而且我的(非扎根)Android平板电脑也没有%N)。


1
@warren:我看到您编辑了并将其更改1397392146%3N1397392146%N,但输出的1397392146%3N是我在android平板电脑的busybox控制台上真正看到的内容。您能解释一下您的编辑吗?
2015年

沃伦在历史上的评论是“从3更改为6,因为3仅会使您达到微秒”。他的编辑似乎完全是虚假的。你应该回滚。
bukzor 2015年

1
这是GNU coreutils特别的功能。最终,这是在gnulib中实现的:github.com/gagern/gnulib/blob/…
telotortium

可能那里的一个点很有意义。date +%s.%3N版画1510718281.134
darksky '17

这应该是公认的答案。
诺亚·萨斯曼

61

date +%N 在OS X上不起作用,但是您可以使用以下一种

  • 红宝石: ruby -e 'puts Time.now.to_f'
  • 蟒蛇: python -c 'import time; print time.time()'
  • node.js: node -e 'console.log(Date.now())'
  • PHP: php -r 'echo microtime(TRUE);'
  • 长生不老药: DateTime.utc_now() |> DateTime.to_unix(:millisecond)
  • 互联网: wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
  • 或毫秒舍入到最接近的秒数 date +%s000

1
为了完整性...node -e 'console.log(Date.now())'
slf

1
使用PHP:php -r 'echo microtime(TRUE);'
TachyonVortex

8
当然,您只需要等待这些口译员热身即可。这也有效:wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
Camilo Martin

8
或者,如果您实际上不需要毫秒,而只需正确的格式:date +%s000
Lenar Hoyt 2015年

1
apple.stackexchange.com/questions/135742/…具有在OSX中通过Brew进行此操作的说明coreutils
相同

9

只是把它扔在那里,但我认为除法的正确公式是:

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

9

我的解决方案不是最好的,但对我有用。

date +%s000

我只需要将2012-05-05之类的日期转换为毫秒。


1
骇客

7
您一定是我同事中的一员。
纳基隆

7

对于建议运行外部程序以毫秒为单位的人员……您最好这样做:

wget -qO- http://www.timeapi.org/utc/now?\\s.\\N

要点是:从这里选择任何答案之前,请记住,并非所有程序都会在一秒钟内运行。测量!


您不需要询问本地系统的时间。我想这暗示了这个问题。您还依赖于网络连接。
orkoden

2
@orkoden该问题明确询问“自1970年1月Unix时代以来的毫秒数”。另外,我更要指出的是,您不应该仅仅为了获得时间而启动整个Ruby或Python(或wget)-是通过快速通道完成还是以毫秒为单位。
卡米洛·马丁

2
是的,我知道您提供的解决方案更糟,以突出不良解决方案的缺陷。我尝试了几种解决方案并测量了时间。lpaste.net/119499结果有点有趣。即使在速度非常快的i7机器上,也date需要3毫秒才能运行。
orkoden

@orkoden不错的测试!什么操作系统?这可能与进程产生的开销有关。
卡米洛·马丁

1
@Nakilon,这就是为什么不应该像任何东西那样依赖可卷曲的便利。
卡米洛·马丁

4

此解决方案可在macOS上使用。

如果您考虑使用bash脚本并提供python,则可以使用以下代码:

#!/bin/bash

python -c 'from time import time; print int(round(time() * 1000))'

为什么要投下反对票?
Frank Thonig '18

似乎没有什么特别的道理。向下箭头上的提示显示“此答案没有用”,但是IMO很有用。也许他们希望您改为使用Python脚本。那会更简单,并且也可以作为bash命令正常工作。
安德鲁·舒尔曼

不要过分担心投票(不是我的)……尤其是在匿名的情况下(从那里人们无法了解什么是错的,对吗?)。只是希望您能处理它...这里还有+1 ...猜猜是什么:现在还可以“投票”,对吗?
Pierre.Vriens,

降低票数似乎是由系统问题引起的。此后,系统再次将其删除。
迈克尔·汉普顿

2

如果您正在寻找一种显示脚本运行时间的方法,则以下内容将提供(并非完全准确)的结果:

尽可能在脚本开头附近输入以下内容

basetime=$(date +%s%N)

这将为您提供类似于1361802943996000000的起始值

在脚本末尾,使用以下命令

echo "runtime: $(echo "scale=3;($(date +%s%N) - ${basetime})/(1*10^09)" | bc) seconds"

这将显示类似

runtime: 12.383 seconds

笔记:

(1 * 10 ^ 09)可以替换为1000000000

"scale=3"是一种非常罕见的设置,可以强制bc执行您想要的操作。还有更多!

我仅在Win7 / MinGW上进行了测试...我没有合适的* nix盒。


3
或者您也可以使用time <script>
沃伦(Warren)2014年

2

这是在不执行除法的情况下以毫秒为单位获取时间的方法。也许更快...

# test=`date +%s%N`
# testnum=${#test}
# echo ${test:0:$testnum-6}
1297327781715

更新:纯bash的另一种替代方法仅与bash 4.2+上面相同,但用于printf获取日期。肯定会更快,因为没有任何过程可以脱离主要过程。

printf -v test '%(%s%N)T' -1
testnum=${#test}
echo ${test:0:$testnum-6}

但是,这里的另一个问题是您的strftime实现应该支持%s%N而在我的测试机上却不是这种情况。请参阅man strftime以获取受支持的选项。另请man bash参见查看printf语法。-1并且-2是时间的特殊值。


似乎我strftime(3)不支持,%N所以没有办法printf打印纳秒。我正在使用Ubuntu 14.04。
haridsv

@haridsv,是的,它不在glibc中。date似乎是更可靠的选择。
akostadinov

2

我们可以获得的最准确的时间戳(至少对于Mac OS X是这样):

python -c 'import datetime; print datetime.datetime.now().strftime("%s.%f")'

1490665305.021699

但是,我们需要记住,运行大约需要30毫秒。我们可以将其削减为2位数的小数位数,并从一开始就计算读取时间的平均开销,然后将其从测量中删除。这是一个例子:

function getTimestamp {
  echo `python -c 'import datetime; print datetime.datetime.now().strftime("%s.%f")' | cut -b1-13` 
}
function getDiff {
  echo "$2-$1-$MeasuringCost" | bc
}
prev_a=`getTimestamp`
acc=0
ITERATIONS=30
for i in `seq 1 $ITERATIONS`;do 
  #echo -n $i 
  a=`getTimestamp`
  #echo -n "   $a"
  b=`echo "$a-$prev_a" | bc`
  prev_a=$a
  #echo "  diff=$b"
  acc=`echo "$acc+$b" | bc`
done
MeasuringCost=`echo "scale=2; $acc/$ITERATIONS" | bc`
echo "average: $MeasuringCost sec"
t1=`getTimestamp`
sleep 2
t2=`getTimestamp`
echo "measured seconds: `getDiff $t1 $t2`"

您可以取消注释echo命令,以更好地了解其工作方式。

此脚本的结果通常是以下3个结果之一:

measured seconds: 1.99
measured seconds: 2.00
measured seconds: 2.01

1

使用date和expr可以达到目标,即

X=$(expr \`date +%H\` \\* 3600 + \`date +%M\` \\* 60 + \`date +%S\`)
echo $X

只是扩展它就可以做你想做的一切

我意识到自纪元以来并没有给出毫秒数,但是对于某些情况它可能仍然是有用的答案,这完全取决于您真正需要什么,如果需要毫秒数,请乘以1000:D

最简单的方法是制作一个小的可执行文件(来自C f.ex.)并使其可用于脚本。


date多次运行存在潜在的问题。在某些情况下,运行命令时,日期或时间可能会在两次运行之间改变。最好只运行date一次并将其解析出来并进行计算。做到这一点的几种方法之一是t=$(date +%H%M%S); (( x = ${t:0:2} * 3600 + ${t:2:2} * 60 + ${t:4:2} )); echo "$x"。由于问题被标记为bash,因此使用Bash语法。正如您所暗示的那样,您的答案(以及我的变化)到目前为止只提供了当天的秒数,而不是自大纪元以来的毫秒数。
丹尼斯·威廉姆森

1

(从上面重复)date +%N在OS X上不起作用,但是您也可以使用:

Perl(需要Time :: Format模块)。也许不是最好的CPAN模块,但可以完成工作。Time :: Format通常可用于发行版。

perl -w -e'use Time::Format; printf STDOUT ("%s.%s\n", time, $time{"mmm"})'

OP特别要求使用bash的方法。除了作为启动其他方法的方法之外,这种bash效果如何?
MadHatter

我在OSX下的bash shell脚本中使用它。因此,date不能使用,并且没有满足要求的仅bash命令。
TVNshack '16

很公平。如果您要弄清为什么date不能将OSX 用作答案的一部分,我将删除我的反对意见。
MadHatter

上面已经解释了一些答案。我无法在建议的列表中添加该命令作为注释。所以我在这里添加了它。
TVNshack '16

公平地说,我接受这是对经典的有益补充。向我+1!
MadHatter

1

在OSX中将所有先前的响应放在一起

ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G31+

你可以喜欢

microtime() {
    python -c 'import time; print time.time()'
}
compute() {
    local START=$(microtime)
    #$1 is command $2 are args
    local END=$(microtime)
    DIFF=$(echo "$END - $START" | bc)
    echo "$1\t$2\t$DIFF"
}

0

如果您希望进行简单的外壳计算,使用上面的答案,这是容易且可移植的:

now() {
    python -c 'import datetime; print datetime.datetime.now().strftime("%s.%f")'
}
seismo:~$ x=`now`
seismo:~$ y=`now`
seismo:~$ echo "$y - $x" | bc
5.212514

0

对于高山linux(许多docker映像)以及可能的其他最小linux环境,您可以滥用adjtimex

adjtimex | awk '/(time.tv_usec):/ { printf("%06d\n", $2) }' | head -c3

adjtimex用于读取(和设置)内核时间变量。有了,awk您可以得到微秒,head只能使用前3位数字。

我不知道这个命令有多可靠。

注意:从此答案中偷偷偷走

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.