Come ottenere il tempo Unix corrente in millisecondi in bash?


232

Come posso ottenere l'attuale tempo di Unix in millisecondi (ovvero il numero di millisecondi dall'epoca di Unix dal 1 ° gennaio 1970)?

Risposte:


265

Questo:

date +%s 

restituirà il numero di secondi dall'epoca.

Questo:

date +%s%N

restituisce i secondi e i nanosecondi correnti.

Così:

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

ti darà il numero di millisecondi dall'epoca - secondi attuali più i tre a sinistra dei nanosecondi.


e da MikeyB - echo $(($(date +%s%N)/1000000))(la divisione per 1000 porta solo ai microsecondi)


39
Mi chiedo quanti ms aggiunge il taglio :-)
Kyle Brandt,

13
O se vuoi fare tutto nella shell, evitando il costoso sovraccarico di un processo aggiuntivo (in realtà, stiamo evitando il problema quando cambia il numero di cifre in% + s + N):echo $(($(date +%s%N)/1000))
MikeyB

5
È il principio della questione ... evita i numeri magici e codifica ciò che realmente intendi .
MikeyB,

25
Penso che valga la pena notare che l'uomo ha chiesto Unix, non Linux, e l'attuale risposta in alto (data +% s% N) non funziona sul mio sistema AIX.
Pete,

12
@Pete +1 Lo stesso per OS X e FreeBSD
ocodo

100

Puoi semplicemente usare %3Nper troncare i nanosecondi alle 3 cifre più significative (che quindi sono i millisecondi):

$ date +%s%3N
1397392146866

Funziona ad esempio sul mio Kubuntu 12.04.

Ma attenzione, %Npotrebbe non essere implementato a seconda del sistema di destinazione. Ad esempio testato su un sistema incorporato (buildroot rootfs, compilato usando una toolchain cross non-HF) non c'era %N:

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

(E anche il mio tablet Android (non rootato) non ha %N).


1
@warren: ho visto che hai modificato e modificato 1397392146%3Nin 1397392146%N, ma l'output di 1397392146%3Nè quello che avevo davvero visto sulla console busybox del mio tablet Android. Potresti spiegare la tua modifica?
Joe,

Il commento di Warren dalla cronologia è "cambiato da 3 a 6, poiché 3 ti porta solo in microsecondi". La sua modifica sembra del tutto falsa; dovresti farlo tornare indietro.
Bukzor,

1
Questa è una caratteristica dei coreutils GNU in particolare. Alla fine, questo è implementato in gnulib qui: github.com/gagern/gnulib/blob/… .
Telotortium,

probabilmente un punto lì dentro ha senso. date +%s.%3Nstampe 1510718281.134.
darksky,

Questa dovrebbe essere la risposta accettata.
Noah Sussman,

61

date +%N non funziona su OS X, ma è possibile utilizzarne uno

  • rubino: ruby -e 'puts Time.now.to_f'
  • pitone: python -c 'import time; print time.time()'
  • node.js: node -e 'console.log(Date.now())'
  • PHP: php -r 'echo microtime(TRUE);'
  • Elisir: DateTime.utc_now() |> DateTime.to_unix(:millisecond)
  • le internet: wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
  • o per millisecondi arrotondato al secondo più vicino date +%s000

1
per completezza ...node -e 'console.log(Date.now())'
slf

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

8
Certo, devi solo aspettare che quegli interpreti si riscaldino. Anche questo funziona:wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
Camilo Martin il

8
Oppure, se in realtà non hai bisogno dei millisecondi ma solo del formato corretto:date +%s000
Lenar Hoyt

1
apple.stackexchange.com/questions/135742/… ha le istruzioni per farlo in OSX tramite Brew'scoreutils
sameers,

10

Basta lanciarlo là fuori, ma penso che la formula corretta con la divisione sarebbe:

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

10

La mia soluzione non è la migliore ma ha funzionato per me.

date +%s000

Avevo solo bisogno di convertire una data come il 05-05-2012 in millisecondi.


1
Incredibile hack, lol :)
k06a

7
Devi essere qualcuno tra i miei colleghi.
Nakilon,

7

Per le persone che suggeriscono di eseguire programmi esterni per ottenere i milli secondi ... a quel ritmo, potresti anche fare questo:

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

Il punto è: prima di scegliere una risposta da qui, tieni presente che non tutti i programmi verranno eseguiti per un intero secondo. Misurare!


Per il momento non stai chiedendo al sistema locale. Il che immagino sia implicito nella domanda. Dipendi anche da una connessione di rete.
orkoden,

2
@orkoden La domanda chiede esplicitamente "numero di millisecondi dall'epoca di Unix dal 1 ° gennaio 1970". Inoltre, sto più sottolineando come non dovresti mai accendere l'intero Ruby o Python (o wget) solo per ottenere il tempo - o questo viene fatto attraverso un canale veloce o i millisecondi non contano.
Camilo Martin,

2
Sì, ho capito che stavi dando una soluzione peggiore per evidenziare i difetti delle soluzioni sbagliate. Ho provato diverse soluzioni e misurato il tempo. lpaste.net/119499 I risultati sono piuttosto interessanti. Anche su una macchina i7 molto veloce dateimpiega 3 ms per funzionare.
orkoden,

@orkoden Bel test! Quale sistema operativo? Ciò potrebbe avere a che fare con l'overhead di generazione dei processi.
Camilo Martin,

1
@Nakilon e questo è il motivo per cui non si dovrebbe fare affidamento su comodità arricciabili come quelle per qualsiasi produzione.
Camilo Martin,

4

questa soluzione funziona su macOS.

se consideri l'utilizzo di uno script bash e disponi di python disponibile, puoi usare questo codice:

#!/bin/bash

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

perché il voto negativo?
Frank Thonig,

Non sembra particolarmente giustificato. Il suggerimento sulla freccia giù dice "Questa risposta non è utile", ma IMO è utile. Forse volevano che tu lo trasformassi in uno script Python. Sarebbe più semplice e funzionerebbe bene anche come comando bash.
Andrew Schulman,

Non preoccuparti troppo dei downvotes (non era mio) ... specialmente se sono anonimi (da cui non si può imparare cosa sembra essere sbagliato, giusto?). Solo per aiutarlo a elaborarlo ... ecco un altro +1 ... indovina un po ': puoi anche "votare" ora, giusto?
Pierre.Vriens,

Il downvote sembra essere stato causato da un problema con il sistema. Da allora è stato rimosso, di nuovo dal sistema.
Michael Hampton

2

Se stai cercando un modo per visualizzare il tempo di esecuzione dello script, ciò che segue fornirà un risultato (non completamente accurato):

Il più vicino possibile all'inizio dello script, inserisci quanto segue

basetime=$(date +%s%N)

Questo ti darà un valore iniziale di qualcosa come 1361802943996000000

Alla fine dello script, utilizzare quanto segue

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

che mostrerà qualcosa di simile

runtime: 12.383 seconds

Appunti:

(1 * 10 ^ 09) può essere sostituito con 1000000000 se lo si desidera

"scale=3"è un'ambientazione piuttosto rara che ti costringe bca fare quello che vuoi. Ce ne sono molti di più!

L'ho testato solo su Win7 / MinGW ... Non ho una scatola * nix a portata di mano.


3
o potresti semplicemente usaretime <script>
warren il

2

Ecco come ottenere il tempo in millisecondi senza eseguire la divisione. Forse è più veloce ...

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

Aggiornamento: Un'altra alternativa in puro bash che funziona solo con bash 4.2+è la stessa di cui sopra, ma usa printfper ottenere la data. Sarà sicuramente più veloce perché nessun processo viene biforcuto rispetto a quello principale.

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

Un altro problema è che l' strftimeimplementazione dovrebbe supportare %se %Nche NON è il caso sulla mia macchina di prova. Vedi man strftimeper le opzioni supportate. Vedi anche man bashper vedere la printfsintassi. -1e -2sono valori speciali per il tempo.


Sembra che il mio strftime(3)non supporti %Nquindi nessun modo per printfstampare nanosecondi. Sto usando Ubuntu 14.04.
Haridsv,

@haridsv, sì, non è in glibc. datesembra l'opzione più affidabile.
Akostadinov

2

Il timestamp più preciso che possiamo ottenere (almeno per Mac OS X) è probabilmente questo:

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

1490665305.021699

Ma dobbiamo tenere a mente che ci vogliono circa 30 millisecondi per funzionare. Possiamo tagliarlo alla scala di 2 cifre e all'inizio calcolare il sovraccarico medio della lettura del tempo, quindi rimuoverlo dalla misurazione. Ecco un esempio:

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

Puoi decommentare i comandi echo per vedere meglio come funziona.

I risultati per questo script sono in genere uno di questi 3 risultati:

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

1

L'uso di date ed expr può farti arrivare ad es

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

Espandilo per fare quello che vuoi

Mi rendo conto che questo non dà millisecondi dall'epoca, ma potrebbe ancora essere utile come risposta per alcuni dei casi, tutto dipende da cosa ne hai davvero bisogno, moltiplicalo per 1000 se hai bisogno di un numero di millisecondi: D

Il modo più semplice sarebbe quello di rendere un piccolo eseguibile (da C f.ex.) e renderlo disponibile allo script.


C'è un potenziale problema in esecuzione datepiù volte. In alcuni casi, la data o l'ora possono cambiare tra le esecuzioni man mano che il comando viene scritto. È meglio eseguire dateuna volta e analizzare le parti ed eseguire il calcolo. Uno dei diversi modi per farlo sarebbe t=$(date +%H%M%S); (( x = ${t:0:2} * 3600 + ${t:2:2} * 60 + ${t:4:2} )); echo "$x". Questo utilizza la sintassi di Bash poiché la domanda è taggata bash . Come alludi, la tua risposta (e la mia variazione) fornisce solo secondi per il giorno corrente finora e non dall'epoca e non in millis.
Dennis Williamson,

1

(ripeti dall'alto) date +%Nnon funziona su OS X, ma puoi usare anche:

Perl (richiede il modulo Time :: Format). Forse non è il miglior modulo CPAN da usare ma fa il lavoro. Time :: Format è generalmente reso disponibile con le distribuzioni.

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

L'OP ha specificamente chiesto modi per farlo usando bash. In che modo questo bash, salva come metodo per lanciare qualcos'altro?
MadHatter

Lo uso nei miei script shell bash ... sotto OSX. Quindi, datenon può essere usato e non ci sono comandi solo bash che rispondono alla necessità.
TVNshack,

Giusto. Se dovessi chiarire perché OSX datenon può essere utilizzato come parte della tua risposta , rimuoverei il mio voto negativo.
MadHatter

Questo è stato spiegato alcune risposte sopra. Non ho potuto aggiungere come commento quel comando che mancava alla lista proposta. Quindi l'ho aggiunto qui.
TVNshack

Abbastanza giusto, accetto che questa sia un'utile aggiunta al canone. +1 da me!
MadHatter

1

Mettendo insieme tutte le risposte precedenti, quando in OSX

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

puoi fare come

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 vuoi un semplice calcolo di shell trascorso, questo è facile e portatile, usando la risposta sopra:

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

Per alpine linux (molte immagini docker) e possibilmente altri ambienti Linux minimi puoi abusare di adjtimex:

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

adjtimexè usato per leggere (e impostare) variabili temporali del kernel. Con awkte puoi ottenere i microsecondi, con headte puoi usare solo le prime 3 cifre.

Non ho idea di quanto sia affidabile questo comando.

Nota: spudoratamente rubato da questa risposta

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.