Como obter o tempo atual do Unix em milissegundos no bash?


232

Como obtenho o tempo atual do Unix em milissegundos (ou seja, número de milissegundos desde a época do Unix, em 1º de janeiro de 1970)?

Respostas:


265

Este:

date +%s 

retornará o número de segundos desde a época.

Este:

date +%s%N

retorna os segundos e os nanossegundos atuais.

Assim:

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

fornecerá o número de milissegundos desde a época - segundos atuais mais os três à esquerda dos nanossegundos.


e do MikeyB - echo $(($(date +%s%N)/1000000))(dividir por 1000 gera apenas em microssegundos)


39
Pergunto-me quantos ms o corte acrescenta :-)
Kyle Brandt

13
Ou se você quiser fazer tudo isso no shell, evitando a sobrecarga cara de um processo adicional (na verdade, estamos evitando o problema quando o número de dígitos em% + s + N for alterado):echo $(($(date +%s%N)/1000))
MikeyB

5
É o princípio da questão ... evite números mágicos e codifique o que você realmente quer dizer .
MikeyB

25
Acho que vale a pena notar que o homem pediu o Unix, não o Linux, e a principal resposta atual (data +% s% N) não funciona no meu sistema AIX.
Pete

12
@Pete +1 O mesmo para OS X e FreeBSD
out

100

Você pode simplesmente usar %3Npara truncar os nanossegundos para os três dígitos mais significativos (que são, em seguida, milissegundos):

$ date +%s%3N
1397392146866

Isso funciona, por exemplo, no meu kubuntu 12.04.

Mas esteja ciente de que isso %Npode não ser implementado dependendo do seu sistema de destino. Por exemplo, testado em um sistema incorporado (rootfs do buildroot, compilado usando uma cadeia de ferramentas cruzada de braço não HF), não havia %N:

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

(E também o meu tablet Android (não enraizado) não tem %N).


1
@warren: Vi que você editou e alterou o arquivo 1397392146%3Npara 1397392146%N, mas a saída 1397392146%3Né o que eu realmente tinha visto no console do busybox do meu tablet Android. Você poderia explicar sua edição?
Joe

O comentário de warren do histórico é "alterado de 3 para 6, pois 3 leva apenas para microssegundos". Sua edição parece totalmente espúria; você deve reverter.
bukzor

1
Este é um recurso do coreUtil GNU especificamente. Por fim, isso é implementado no gnulib aqui: github.com/gagern/gnulib/blob/… .
telotortium

provavelmente um ponto lá faz sentido. date +%s.%3Nimpressões 1510718281.134.
darksky

Essa deve ser a resposta aceita.
Noah Sussman

61

date +%N não funciona no OS X, mas você pode usar um dos

  • rubi: ruby -e 'puts Time.now.to_f'
  • Pitão: python -c 'import time; print time.time()'
  • node.js: node -e 'console.log(Date.now())'
  • PHP: php -r 'echo microtime(TRUE);'
  • Elixir: DateTime.utc_now() |> DateTime.to_unix(:millisecond)
  • as internets: wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
  • ou por milissegundos arredondados para o segundo mais próximo date +%s000

1
para completar ...node -e 'console.log(Date.now())'
slf 10/10

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

8
Claro, você só precisa aguardar o aquecimento dos intérpretes. Isso também funciona:wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
Camilo Martin

8
Ou, se você realmente não precisa os milissegundos , mas apenas o formato correto:date +%s000
Lenar Hoyt

1
apple.stackexchange.com/questions/135742/… tem instruções para fazer isso no OSX via Brew'scoreutils
sameers

10

Apenas jogando isso lá fora, mas acho que a fórmula correta com a divisão seria:

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

10

Minha solução não é a melhor, mas funcionou para mim.

date +%s000

Eu só precisava converter uma data como 05/05/2012 para milissegundos.


1
O que você
quer tocar hoje?

7
Você deve ser alguém entre meus colegas de trabalho.
Nakilon

7

Para as pessoas que sugerem executar programas externos para obter os mili segundos ... nesse ritmo, você também pode fazer o seguinte:

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

A questão é: antes de escolher qualquer resposta a partir daqui, lembre-se de que nem todos os programas serão executados em menos de um segundo. A medida!


Você não está perguntando ao sistema local sobre o tempo. O que eu acho que está implícito na pergunta. Você também depende de uma conexão de rede.
precisa saber é

2
@orkoden A pergunta pede explicitamente "número de milissegundos desde a época do Unix, em 1º de janeiro de 1970". Além disso, estou mais apontando como você nunca deve acionar Ruby ou Python (ou wget) apenas para ter tempo - isso é feito através de um canal rápido ou milissegundos não importam.
Camilo Martin

2
Sim, entendi que você estava dando uma solução pior para destacar as falhas das más soluções. Tentei várias soluções e medi o tempo. lpaste.net/119499 Os resultados são interessantes. Mesmo em uma máquina i7 muito rápida, são datenecessários 3 ms para funcionar.
precisa saber é o seguinte

@orkoden Bom teste! Qual SO? Isso pode ter a ver com a sobrecarga do processo.
Camilo Martin

1
@ Nakilon, e é por isso que não se deve confiar em conveniências flexíveis como aquelas para qualquer produção.
Camilo Martin

4

Esta solução funciona no macOS.

se você considerar usar um script bash e tiver python disponível, poderá usar este código:

#!/bin/bash

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

por que o voto negativo?
22818 Frank Thonig

Não parece particularmente justificado. A dica na seta para baixo diz "Esta resposta não é útil", mas o IMO é útil. Talvez eles quisessem que você o transformasse em um script Python. Isso seria mais simples e também funcionaria bem como um comando bash.
Andrew Schulman

Não se preocupe muito com votos negativos (não era meu) ... especialmente se eles são anônimos (dos quais não se pode aprender o que parece estar errado, certo?). Só para ajudá-lo a processá-lo ... aqui vai outro +1 ... adivinhe: você também tem permissão para "votar" agora, certo?
Pierre.Vriens

O voto negativo parece ter sido causado por um problema no sistema. Desde então, foi removido, novamente pelo sistema.
Michael Hampton

2

Se você estiver procurando uma maneira de exibir o período de execução do script, o seguinte fornecerá um resultado (não totalmente preciso):

O mais próximo possível do script, digite o seguinte

basetime=$(date +%s%N)

Isso fornecerá um valor inicial de algo como 1361802943996000000

No final do seu script, use o seguinte

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

que exibirá algo como

runtime: 12.383 seconds

Notas:

(1 * 10 ^ 09) pode ser substituído por 1000000000 se você desejar

"scale=3"é uma configuração bastante rara que obriga bca fazer o que você deseja. Há muito mais!

Eu só testei isso no Win7 / MinGW ... Não tenho uma caixa * nix adequada à mão.


3
ou você pode simplesmente usartime <script>
Warren

2

Aqui está como obter tempo em milissegundos sem executar a divisão. Talvez seja mais rápido ...

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

Atualização: Outra alternativa no bash puro que funciona apenas com o bash 4.2+mesmo é acima, mas use printfpara obter a data. Definitivamente, será mais rápido porque nenhum processo é extraído do principal.

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

Outro problema aqui é que sua strftimeimplementação deve suportar %se %NNÃO é o caso na minha máquina de teste. Veja man strftimepara opções suportadas. Veja também man bashpara ver a printfsintaxe. -1e -2são valores especiais para o tempo.


Parece que o meu strftime(3)não suporta, %Nentão não há como printfimprimir nanossegundos. Estou usando o Ubuntu 14.04.
precisa saber é

@haridsv, sim, não está na glibc. dateparece ser a opção mais confiável.
akostadinov

2

O carimbo de data e hora mais preciso que podemos obter (pelo menos para o Mac OS X) é provavelmente o seguinte:

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

1490665305.021699

Mas precisamos ter em mente que leva cerca de 30 milissegundos para ser executado. Podemos reduzi-lo na escala da fração de 2 dígitos e, no início, calcular a sobrecarga média da leitura do tempo e removê-lo da medição. Aqui está um exemplo:

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`"

Você pode descomentar os comandos de eco para ver melhor como ele funciona.

Os resultados para este script são geralmente um destes 3 resultados:

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

1

Usar date e expr pode levá-lo até lá, ie

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

Basta expandi-lo para fazer o que quiser

Sei que isso não dá milissegundos desde a época, mas ainda pode ser útil como resposta para alguns casos, tudo depende do que você realmente precisa, multiplique por 1000 se precisar de um número de milissegundos: D

A maneira mais simples seria tornar um pequeno executável (de C f.ex.) e disponibilizá-lo para o script.


Há um problema em potencial executando datevárias vezes. Em alguns casos, a data ou hora pode mudar entre as execuções à medida que seu comando é gravado. É melhor executar dateuma vez, analisar as peças e fazer seu cálculo. Uma das várias maneiras de fazer isso seria t=$(date +%H%M%S); (( x = ${t:0:2} * 3600 + ${t:2:2} * 60 + ${t:4:2} )); echo "$x". Isso usa a sintaxe do Bash, pois a pergunta é marcada como bash . Como você alude, sua resposta (e minha variação) dá apenas segundos para o dia atual até agora e não desde a época nem em milis.
Dennis Williamson

1

(repetir de cima) date +%Nnão funciona no OS X, mas você também pode usar:

Perl (requer o módulo Time :: Format). Talvez não seja o melhor módulo de CPAN a ser usado, mas faz o trabalho. Time :: Format geralmente é disponibilizado com distribuições.

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

O OP pediu especificamente maneiras de fazer isso usando o bash. Como é essa festança, salve como um método para iniciar outra coisa?
21916 MadHatter

Eu uso isso nos meus scripts shell bash ... no OSX. Portanto, datenão pode ser usado e não há comandos somente do bash que atendam à necessidade.
TVNshack 15/03

Justo. Se você esclarecer por que o OSX datenão pode ser usado como parte de sua resposta , eu removo meu voto negativo.
21916 MadHatter

Isso foi explicado algumas respostas acima. Não pude adicionar como comentário o comando que faltava na lista proposta. Então eu adicionei aqui.
TVNshack 15/03

Justo, aceito que essa seja uma adição útil ao cânon. +1 de mim!
21416 MadHatter

1

Reunindo todas as respostas anteriores, quando estiver no OSX

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

você pode fazer como

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

Se você deseja um cálculo simples de shell, isso é fácil e portátil, usando a resposta acima:

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

Para linux alpino (muitas imagens do docker) e possivelmente outros ambientes linux mínimos, você pode abusar adjtimex:

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

adjtimexé usado para ler (e definir) variáveis ​​de tempo do kernel. Com awkvocê pode obter os microssegundos, headvocê pode usar apenas os 3 primeiros dígitos.

Não tenho ideia de quão confiável é esse comando.

Nota: Roubado descaradamente desta resposta

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.