Bagaimana cara mendapatkan waktu Unix saat ini dalam milidetik dalam bash?

232

Bagaimana saya mendapatkan waktu Unix saat ini dalam milidetik (yaitu jumlah milidetik sejak Unix, 1 Januari 1970)?

Richard
sumber

Jawaban:

265

Ini:

date +%s 

akan mengembalikan jumlah detik sejak zaman.

Ini:

date +%s%N

mengembalikan detik dan nanodetik saat ini.

Begitu:

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

akan memberi Anda jumlah milidetik sejak zaman - detik saat ini ditambah tiga nanodetik.


dan dari MikeyB - echo $(($(date +%s%N)/1000000))(membaginya dengan 1000 hanya membawa ke microseconds)

warren
sumber
39
Saya bertanya-tanya berapa banyak MS cut menambahkan :-)
Kyle Brandt
13
Atau jika Anda ingin melakukan semuanya dalam shell, menghindari overhead mahal dari proses tambahan (sebenarnya, kami menghindari masalah ketika jumlah digit dalam% + s + N berubah):echo $(($(date +%s%N)/1000))
MikeyB
5
Ini prinsip dari masalah ini ... hindari angka ajaib dan kode apa yang sebenarnya Anda maksud .
MikeyB
25
Saya pikir perlu dicatat bahwa orang itu meminta Unix, bukan Linux, dan jawaban teratas saat ini (tanggal +% s% N) tidak berfungsi pada sistem AIX saya.
Pete
12
@Pete +1 Sama untuk OS X, dan FreeBSD
ocodo
100

Anda cukup menggunakan %3Nuntuk memotong nanodetik ke 3 digit paling signifikan (yang kemudian menjadi milidetik):

$ date +%s%3N
1397392146866

Ini berfungsi misalnya pada kubuntu saya 12,04.

Namun ketahuilah, itu %Nmungkin tidak diterapkan tergantung pada sistem target Anda. Misalnya diuji pada sistem tertanam (rootro buildroot, dikompilasi menggunakan toolchain lintas lengan non-HF) tidak ada %N:

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

(Dan juga tablet Android saya (yang tidak di-rooting) tidak memiliki %N).

Joe
sumber
1
@warren: Saya melihat bahwa Anda mengedit dan mengubah 1397392146%3Nuntuk 1397392146%N, tetapi output 1397392146%3Nadalah bahwa apa yang saya benar-benar akan terlihat pada konsol busybox tablet android saya. Bisakah Anda menjelaskan hasil edit Anda?
Joe
komentar warren dari sejarah "diubah dari 3 menjadi 6, karena 3 hanya akan membawa Anda ke mikrodetik". Hasil editnya tampaknya sepenuhnya palsu; Anda harus mengembalikannya.
bukzor
1
Ini adalah fitur GNU coreutils secara khusus. Pada akhirnya, ini diterapkan di gnulib di sini: github.com/gagern/gnulib/blob/… .
telotortium
mungkin titik di sana masuk akal. date +%s.%3Ncetakan 1510718281.134.
darksky
Ini harus menjadi jawaban yang diterima.
Noah Sussman
61

date +%N tidak berfungsi pada OS X, tetapi Anda dapat menggunakannya

  • rubi: ruby -e 'puts Time.now.to_f'
  • python: python -c 'import time; print time.time()'
  • node.js: node -e 'console.log(Date.now())'
  • PHP: php -r 'echo microtime(TRUE);'
  • Eliksir: DateTime.utc_now() |> DateTime.to_unix(:millisecond)
  • internet: wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
  • atau selama milidetik dibulatkan ke detik terdekat date +%s000
Lri
sumber
1
untuk kelengkapan ...node -e 'console.log(Date.now())'
slf
1
Menggunakan PHP:php -r 'echo microtime(TRUE);'
TachyonVortex
8
Tentu, Anda hanya harus menunggu agar penerjemah itu tidak hangat. Ini juga berfungsi:wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
Camilo Martin
8
Atau, jika Anda tidak benar-benar membutuhkan milidetik tetapi hanya format yang benar:date +%s000
Lenar Hoyt
1
apple.stackexchange.com/questions/135742/… memiliki instruksi untuk melakukan ini di OSX via Brew'scoreutils
sameers
10

Hanya melempar ini ke luar, tapi saya pikir formula yang tepat dengan divisi adalah:

echo $(($(date +%s%N)/1000000))
percikan
sumber
10

Solusi saya bukan yang terbaik tetapi bekerja untuk saya.

date +%s000

Saya hanya perlu mengonversi tanggal seperti 2012-05-05 ke milidetik.

Pablo
sumber
1
Hack luar biasa, lol :)
k06a
7
Anda harus menjadi seseorang di antara rekan kerja saya.
Nakilon
7

Bagi orang yang menyarankan menjalankan program eksternal untuk mendapatkan mili detik ... pada tingkat itu, Anda sebaiknya melakukan ini:

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

Poinnya adalah: sebelum memilih jawaban apa pun dari sini, harap diingat bahwa tidak semua program akan berjalan dalam satu detik penuh. Mengukur!

Camilo Martin
sumber
Anda tidak menanyakan waktu ke sistem lokal. Yang saya duga tersirat dalam pertanyaan. Anda juga bergantung pada koneksi jaringan.
orkoden
2
@orkoden Pertanyaan secara eksplisit menanyakan "jumlah milidetik sejak Unix 1 Januari 1970". Juga, saya lebih menunjukkan bagaimana Anda seharusnya tidak menjalankan seluruh Ruby atau Python (atau wget) hanya untuk mendapatkan waktu - baik ini dilakukan melalui saluran cepat atau milidetik tidak masalah.
Camilo Martin
2
Ya, saya mengerti bahwa Anda memberikan solusi yang lebih buruk untuk menyoroti kekurangan solusi yang buruk. Saya mencoba beberapa solusi dan mengukur waktu. lpaste.net/119499 Hasilnya agak menarik. Bahkan pada mesin i7 yang sangat cepat datemembutuhkan 3 ms untuk dijalankan.
orkoden
@orkoden Pengujian bagus! OS apa? Ini mungkin ada hubungannya dengan proses pemijahan overhead.
Camilo Martin
1
@Nakilon dan inilah mengapa orang tidak harus bergantung pada kenyamanan yang dapat dikeriting seperti yang untuk produksi apa pun.
Camilo Martin
4

solusi ini berfungsi pada macOS.

jika Anda mempertimbangkan untuk menggunakan skrip bash dan memiliki python tersedia, Anda bisa menggunakan kode ini:

#!/bin/bash

python -c 'from time import time; print int(round(time() * 1000))'
Frank Thonig
sumber
mengapa memilih bawah?
Frank Thonig
Tampaknya tidak dibenarkan. Petunjuk pada panah bawah mengatakan "Jawaban ini tidak berguna", tetapi IMO itu berguna. Mungkin mereka ingin Anda menjadikannya skrip Python. Itu akan lebih sederhana dan juga berfungsi dengan baik sebagai perintah bash.
Andrew Schulman
Jangan terlalu khawatir tentang downvotes (itu bukan milikku) ... terutama jika mereka anonim (dari mana orang tidak dapat belajar apa yang tampaknya salah, kan?). Hanya untuk membantu Anda memprosesnya ... inilah +1 lainnya ... coba tebak: ANDA juga diizinkan untuk "memberikan suara" sekarang, bukan?
Pierre.Vriens
Downvote tampaknya disebabkan oleh masalah dengan sistem. Sejak itu telah dihapus, lagi oleh sistem.
Michael Hampton
2

Jika Anda mencari cara untuk menampilkan berapa lama skrip Anda berjalan, yang berikut ini akan memberikan hasil (tidak sepenuhnya akurat):

Sedekat awal skrip Anda, masukkan yang berikut ini

basetime=$(date +%s%N)

Ini akan memberi Anda nilai awal dari sesuatu seperti 1361802943996000000

Di akhir skrip Anda, gunakan yang berikut ini

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

yang akan menampilkan sesuatu seperti

runtime: 12.383 seconds

Catatan:

(1 * 10 ^ 09) dapat diganti dengan 1000000000 jika diinginkan

"scale=3"adalah pengaturan yang agak jarang yang memaksa bcuntuk melakukan apa yang Anda inginkan. Masih banyak lagi!

Saya hanya menguji ini pada Win7 / MinGW ... Saya tidak memiliki kotak * nix yang tepat.

pengguna161733
sumber
3
atau Anda bisa menggunakantime <script>
warren
2

Inilah cara mendapatkan waktu dalam milidetik tanpa melakukan pembagian. Mungkin lebih cepat ...

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

Pembaruan: Alternatif lain dalam bash murni yang hanya berfungsi bash 4.2+sama dengan di atas tetapi digunakan printfuntuk mendapatkan tanggal. Ini pasti akan lebih cepat karena tidak ada proses yang dihapus dari yang utama.

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

Tangkapan lain di sini adalah bahwa strftimeimplementasi Anda harus mendukung %sdan %Nyang BUKAN terjadi pada mesin uji saya. Lihat man strftimeopsi yang didukung. Lihat juga man bashuntuk melihat printfsintaks. -1dan -2merupakan nilai khusus untuk waktu.

akostadinov
sumber
Sepertinya saya strftime(3)tidak mendukung %Njadi tidak ada cara untuk printfmencetak nanodetik. Saya menggunakan Ubuntu 14.04.
haridsv
@ haridsv, ya, itu tidak di glibc. datesepertinya pilihan yang lebih bisa diandalkan.
akostadinov
2

Stempel waktu paling akurat yang bisa kita dapatkan (setidaknya untuk Mac OS X) mungkin ini:

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

1490665305.021699

Tetapi kita harus ingat bahwa dibutuhkan sekitar 30 milidetik untuk berjalan. Kita dapat memotongnya menjadi skala fraksi 2 digit, dan pada mulanya menghitung rata - rata overhead membaca waktu, dan kemudian menghapusnya dari pengukuran. Berikut ini sebuah contoh:

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

Anda dapat menghapus komentar perintah gema untuk melihat lebih baik cara kerjanya.

Hasil untuk skrip ini biasanya adalah salah satu dari 3 hasil ini:

measured seconds: 1.99
measured seconds: 2.00
measured seconds: 2.01
ishahak
sumber
1

Menggunakan tanggal dan expr dapat membawa Anda ke sana yaitu

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

Perluas untuk melakukan apa pun yang Anda inginkan

Saya menyadari ini tidak memberikan milidetik sejak zaman, tetapi mungkin masih berguna sebagai jawaban untuk beberapa kasus, itu semua tergantung pada apa yang Anda butuhkan, kalikan dengan 1000 jika Anda memerlukan nomor milidetik: D

Cara paling sederhana adalah dengan membuat executable kecil (dari C f.ex.) dan membuatnya tersedia untuk skrip.

Johan Andersson
sumber
Ada masalah potensial yang terjadi datebeberapa kali. Dalam beberapa kasus, tanggal atau waktu dapat berubah antar berjalan saat perintah Anda ditulis. Lebih baik dijalankan datesekali dan parsing bagian-bagian keluar dan lakukan perhitungan Anda. Salah satu dari beberapa cara untuk melakukannya adalah t=$(date +%H%M%S); (( x = ${t:0:2} * 3600 + ${t:2:2} * 60 + ${t:4:2} )); echo "$x". Ini menggunakan sintaks Bash karena pertanyaannya ditandai bash . Seperti yang Anda singgung, jawaban Anda (dan variasi saya) hanya memberikan detik untuk hari ini sejauh ini dan bukan sejak Zaman dan bukan dalam milis.
Dennis Williamson
1

(ulangi dari atas) date +%Ntidak berfungsi pada OS X, tetapi Anda juga dapat menggunakan:

Perl (membutuhkan modul Time :: Format). Mungkin bukan modul CPAN terbaik untuk digunakan tetapi menyelesaikan pekerjaan. Waktu :: Format umumnya tersedia dengan distribusi.

perl -w -e'use Time::Format; printf STDOUT ("%s.%s\n", time, $time{"mmm"})'
TVNshack
sumber
OP secara khusus meminta cara untuk melakukannya menggunakan bash. Bagaimana bash ini, simpan sebagai metode untuk meluncurkan sesuatu yang lain?
MadHatter
Saya menggunakan ini di skrip bash shell saya ... di bawah OSX. Jadi, datetidak dapat digunakan dan tidak ada perintah bash-only yang menjawab kebutuhan.
TVNshack
Cukup adil. Jika Anda ingin menjelaskan mengapa OSX datetidak dapat digunakan sebagai bagian dari jawaban Anda , saya akan menghapus downvote saya.
MadHatter
Ini dijelaskan beberapa jawaban di atas. Saya tidak dapat menambahkan sebagai komentar bahwa perintah yang hilang dengan daftar yang diusulkan. Jadi saya sudah menambahkannya di sini.
TVNshack
Cukup adil, saya menerima ini adalah tambahan yang berguna untuk kanon. +1 dari saya!
MadHatter
1

Menyatukan semua respons sebelumnya, saat berada di OSX

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

Anda bisa suka

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"
}
loretoparisi
sumber
0

Jika Anda menginginkan perhitungan shell yang sederhana, ini mudah dan portabel, menggunakan jawaban di atas:

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
Bill Cheswick
sumber
0

Untuk alpine linux (banyak gambar buruh pelabuhan) dan mungkin lingkungan linux minimal lainnya, Anda dapat menyalahgunakan adjtimex:

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

adjtimexdigunakan untuk membaca (dan mengatur) variabel waktu kernel. Dengan awkAnda bisa mendapatkan mikrodetik, dengan headAnda dapat menggunakan 3 digit pertama saja.

Saya tidak tahu seberapa andal perintah ini.

Catatan: Tanpa malu-malu dicuri dari jawaban ini

Qw3ry
sumber