Làm thế nào để có được thời gian Unix hiện tại tính bằng mili giây trong bash?


232

Làm cách nào để tôi có được thời gian Unix hiện tại tính bằng mili giây (tức là số mili giây kể từ Unix epoch ngày 1 tháng 1 năm 1970)?

Câu trả lời:


265

Điều này:

date +%s 

sẽ trả về số giây kể từ kỷ nguyên.

Điều này:

date +%s%N

trả về giây và nano giây hiện tại.

Vì thế:

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

sẽ cung cấp cho bạn số mili giây kể từ kỷ nguyên - giây hiện tại cộng với ba phần trăm giây còn lại.


và từ MikeyB - echo $(($(date +%s%N)/1000000))(chia cho 1000 chỉ mang đến micro giây)


39
Tôi tự hỏi có bao nhiêu ms cắt giảm thêm :-)
Kyle Brandt

13
Hoặc nếu bạn muốn thực hiện tất cả trong vỏ, tránh chi phí quá cao của một quy trình bổ sung (thực ra, chúng tôi đang tránh vấn đề khi số chữ số trong% + s + N thay đổi):echo $(($(date +%s%N)/1000))
MikeyB

5
Đó là nguyên tắc của vấn đề ... tránh các số ma thuật và mã hóa ý nghĩa thực sự của bạn .
MikeyB

25
Tôi nghĩ rằng đáng chú ý là người đàn ông đã yêu cầu Unix, không phải Linux và câu trả lời hàng đầu hiện tại (ngày +% s% N) không hoạt động trên hệ thống AIX của tôi.
Pete

12
@Pete +1 Tương tự cho OS X và FreeBSD
ocodo

99

Bạn có thể chỉ cần sử dụng %3Nđể cắt các nano giây thành 3 chữ số có ý nghĩa nhất (sau đó là mili giây):

$ date +%s%3N
1397392146866

Điều này hoạt động ví dụ như trên kubfox 12.04 của tôi.

Nhưng hãy lưu ý, điều đó %Ncó thể không được thực hiện tùy thuộc vào hệ thống mục tiêu của bạn. Ví dụ, đã thử nghiệm trên một hệ thống nhúng (rootro buildroot, được biên dịch bằng cách sử dụng chuỗi công cụ chéo không phải HF), không có %N:

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

(Và cả máy tính bảng Android (không root) của tôi không có %N).


1
@warren: Tôi thấy rằng bạn đã chỉnh sửa và thay đổi 1397392146%3Nthành 1397392146%N, nhưng kết quả đầu ra 1397392146%3Nlà những gì tôi thực sự thấy trên bảng điều khiển busybox của máy tính bảng Android của tôi. Bạn có thể giải thích chỉnh sửa của bạn?
Joe

Nhận xét của warren từ lịch sử là "thay đổi từ 3 thành 6, vì 3 chỉ đưa bạn đến micro giây". Chỉnh sửa của anh ấy có vẻ hoàn toàn giả mạo; bạn nên cuộn nó lại
bukzor

1
Đây là một tính năng của GNU coreutils. Cuối cùng, điều này được thực hiện trong gnulib tại đây: github.com/gagern/gnulib/blob/ mẹo .
telotortium

có lẽ một dấu chấm trong đó có ý nghĩa. date +%s.%3Nin 1510718281.134.
darksky

Đây phải là câu trả lời được chấp nhận.

61

date +%N không hoạt động trên OS X, nhưng bạn có thể sử dụng một trong

  • hồng ngọc: ruby -e 'puts Time.now.to_f'
  • trăn: python -c 'import time; print time.time()'
  • node.js: node -e 'console.log(Date.now())'
  • PHP: php -r 'echo microtime(TRUE);'
  • Thuốc tiên: DateTime.utc_now() |> DateTime.to_unix(:millisecond)
  • các mạng nội bộ: wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
  • hoặc trong một phần nghìn giây được làm tròn đến giây gần nhất date +%s000

1
cho đầy đủ ...node -e 'console.log(Date.now())'
slf

1
Sử dụng PHP:php -r 'echo microtime(TRUE);'
TachyonVortex

8
Chắc chắn, bạn chỉ cần chờ những thông dịch viên khởi động. Điều này cũng hoạt động:wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
Camilo Martin

8
Hoặc, nếu bạn không thực sự cần một phần nghìn giây mà chỉ cần định dạng đúng:date +%s000
Lenar Hoyt

1
apple.stackexchange.com/questions/135742/ từ có hướng dẫn thực hiện việc này trong OSX thông qua Brew'scoreutils
cùng

10

Chỉ cần ném nó ra khỏi đó, nhưng tôi nghĩ rằng công thức chính xác với phép chia sẽ là:

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

10

Giải pháp của tôi không phải là tốt nhất nhưng làm việc cho tôi.

date +%s000

Tôi chỉ cần chuyển đổi một ngày như 2012-05-05 sang mili giây.


1
Hack tuyệt vời, lol :)
k06a

7
Bạn phải là một trong số các đồng nghiệp của tôi.
Nakilon

7

Đối với những người đề xuất chạy các chương trình bên ngoài để có được milli giây ... với tốc độ đó, bạn cũng có thể làm điều này:

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

Quan điểm: trước khi chọn bất kỳ câu trả lời nào từ đây, xin lưu ý rằng không phải tất cả các chương trình sẽ chạy dưới một giây. Đo lường!


Bạn không hỏi hệ thống địa phương cho thời gian. Mà tôi đoán là ngụ ý trong câu hỏi. Bạn cũng phụ thuộc vào kết nối mạng.
orkoden

2
@orkoden Câu hỏi yêu cầu rõ ràng về "số mili giây kể từ thời kỳ Unix 1 tháng 1 năm 1970". Ngoài ra, tôi còn chỉ ra cách bạn không nên kích hoạt toàn bộ Ruby hoặc Python (hoặc wget) chỉ để có thời gian - điều này được thực hiện thông qua một kênh nhanh hoặc một phần nghìn giây không thành vấn đề.
Camilo Martin

2
Vâng, tôi hiểu rằng bạn đang đưa ra một giải pháp tồi tệ hơn để làm nổi bật những sai sót của các giải pháp xấu. Tôi đã thử một vài giải pháp và đo thời gian. lpaste.net/119499 Kết quả thật thú vị. Ngay cả trên một máy i7 rất nhanh cũng datemất 3 ms để chạy.
orkoden

@orkoden Thử nghiệm đẹp! HĐH gì? Điều này có thể phải làm với quá trình sinh sản trên cao.
Camilo Martin

1
@Nakilon và đây là lý do tại sao người ta không nên dựa vào các tiện ích có khả năng uốn cong như những tiện ích cho sản xuất bất cứ thứ gì.
Camilo Martin

4

giải pháp này hoạt động trên macOS.

nếu bạn cân nhắc sử dụng tập lệnh bash và có sẵn python, bạn có thể sử dụng mã này:

#!/bin/bash

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

Tại sao bỏ phiếu xuống?
Frank Thonig

Không có vẻ đặc biệt hợp lý. Gợi ý về mũi tên xuống cho biết "Câu trả lời này không hữu ích", nhưng IMO nó hữu ích. Có lẽ họ muốn bạn biến nó thành một kịch bản Python thay thế. Điều đó sẽ đơn giản hơn và cũng hoạt động tốt như một lệnh bash.
Andrew Schulman

Đừng lo lắng quá nhiều về downvote (nó không phải của tôi) ... đặc biệt nếu chúng ẩn danh (từ đó người ta không thể học được những gì có vẻ là sai, phải không?). Chỉ cần hlep bạn xử lý nó ... ở đây đi +1 khác ... đoán xem: BẠN cũng được phép "bỏ phiếu" ngay bây giờ, phải không?
Pierre.Vriens

Downvote dường như đã được gây ra bởi một vấn đề với hệ thống. Nó đã được gỡ bỏ, một lần nữa bởi hệ thống.
Michael Hampton

2

Nếu bạn đang tìm cách hiển thị thời lượng tập lệnh của bạn chạy, phần sau đây sẽ cung cấp kết quả (không hoàn toàn chính xác):

Càng gần đầu tập lệnh của bạn càng tốt, hãy nhập vào phần sau

basetime=$(date +%s%N)

Điều này sẽ cung cấp cho bạn một giá trị bắt đầu của một cái gì đó như 1361802943996000000

Vào cuối tập lệnh của bạn, sử dụng như sau

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

Nó sẽ hiển thị một cái gì đó như

runtime: 12.383 seconds

Ghi chú:

(1 * 10 ^ 09) có thể được thay thế bằng 1000000000 nếu bạn muốn

"scale=3"là một thiết lập khá hiếm hoi buộc bcphải làm những gì bạn muốn. Còn nhiều nữa!

Tôi chỉ thử nghiệm điều này trên Win7 / MinGW ... Tôi không có hộp * nix thích hợp trong tay.


3
hoặc bạn chỉ có thể sử dụngtime <script>
warren

2

Đây là cách lấy thời gian tính bằng mili giây mà không cần thực hiện phép chia. Có lẽ nó nhanh hơn ...

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

Cập nhật: Một cách khác trong bash thuần chỉ hoạt động với bash 4.2+giống như trên nhưng sử dụng printfđể lấy ngày. Nó chắc chắn sẽ nhanh hơn vì không có quá trình nào được tách ra khỏi quy trình chính.

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

Một lưu ý khác ở đây là việc strftimetriển khai của bạn phải hỗ trợ %s%Nđó không phải là trường hợp trên máy thử nghiệm của tôi. Xem man strftimecho các tùy chọn được hỗ trợ. Cũng xem man bashđể xem printfcú pháp. -1-2là những giá trị đặc biệt cho thời gian.


Có vẻ như tôi strftime(3)không hỗ trợ %Nnên không có cách nào printfđể in nano giây. Tôi đang sử dụng Ubuntu 14.04.
haridsv

@haridsv, vâng, nó không ở glibc. datecó vẻ như là lựa chọn đáng tin cậy hơn
akostadinov

2

Dấu thời gian chính xác nhất mà chúng ta có thể nhận được (ít nhất là đối với Mac OS X) có lẽ là đây:

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

1490665305.021699

Nhưng chúng ta cần lưu ý rằng phải mất khoảng 30 mili giây để chạy. Chúng ta có thể cắt nó theo tỷ lệ 2 chữ số, và ngay từ đầu, tính toán chi phí trung bình của thời gian đọc, và sau đó loại bỏ nó khỏi phép đo. Đây là một ví dụ:

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

Bạn có thể bỏ ghi chú các lệnh echo để thấy rõ hơn cách thức hoạt động của nó.

Kết quả cho kịch bản này thường là một trong 3 kết quả sau:

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

1

Sử dụng ngày và expr có thể giúp bạn có nghĩa là

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

Chỉ cần mở rộng trên đó để làm bất cứ điều gì bạn muốn

Tôi nhận ra rằng điều này không mang lại mili giây kể từ epoch, nhưng nó vẫn có thể hữu ích như một câu trả lời cho một số trường hợp, tất cả phụ thuộc vào những gì bạn cần nó thực sự, nhân với 1000 nếu bạn cần số mili giây: D

Cách đơn giản nhất là tạo một tệp thực thi nhỏ (từ C f.ex.) và làm cho nó có sẵn cho tập lệnh.


Có một vấn đề tiềm năng chạy datenhiều lần. Trong một số trường hợp, ngày hoặc giờ có thể thay đổi giữa các lần chạy khi lệnh của bạn được viết. Tốt hơn là chạy datemột lần và phân tích các phần ra và thực hiện tính toán của bạn. Một trong nhiều cách để làm điều đó sẽ là t=$(date +%H%M%S); (( x = ${t:0:2} * 3600 + ${t:2:2} * 60 + ${t:4:2} )); echo "$x". Điều này sử dụng cú pháp Bash vì câu hỏi được gắn thẻ bash . Như bạn đã nói, câu trả lời của bạn (và biến thể của tôi) chỉ đưa ra vài giây cho ngày hiện tại cho đến nay và không kể từ Kỷ nguyên và không tính bằng mili.
Dennis Williamson

1

(lặp lại từ trên) date +%Nkhông hoạt động trên OS X, nhưng bạn cũng có thể sử dụng:

Perl (yêu cầu mô-đun Time :: Format). Có lẽ không phải là mô-đun CPAN tốt nhất để sử dụng nhưng hoàn thành công việc. Time :: Format thường được cung cấp với các bản phân phối.

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

OP đặc biệt yêu cầu các cách để làm điều đó bằng cách sử dụng bash. Làm thế nào là bash này, lưu như một phương pháp để khởi chạy một cái gì đó khác?
MadHatter

Tôi sử dụng điều này trong các tập lệnh bash shell của mình ... trong OSX. Vì vậy, datekhông thể được sử dụng và không có lệnh bash nào chỉ đáp ứng nhu cầu.
TVNshack 15/03/2016

Đủ công bằng. Nếu bạn muốn làm rõ lý do tại sao OSX datekhông thể được sử dụng như một phần câu trả lời của bạn , tôi sẽ xóa phần dưới của tôi.
MadHatter

Điều này đã được giải thích một vài câu trả lời ở trên. Tôi không thể thêm vào như nhận xét rằng lệnh bị thiếu với danh sách đề xuất. Vì vậy, tôi đã thêm nó ở đây.
TVNshack

Đủ công bằng, tôi chấp nhận đây là một bổ sung hữu ích cho canon. +1 từ tôi!
MadHatter

1

Đặt tất cả các phản hồi trước đó lại với nhau, khi ở OSX

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

bạn có thể làm như

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

Nếu bạn muốn một vỏ tính toán đơn giản trôi qua, đây là cách dễ dàng và dễ mang theo, sử dụng câu trả lời ở trên:

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

Đối với linux alpine (nhiều hình ảnh docker) và có thể các môi trường linux tối thiểu khác mà bạn có thể lạm dụng adjtimex:

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

adjtimexđược sử dụng để đọc (và thiết lập) các biến thời gian của hạt nhân. Với awkbạn có thể nhận được micro giây, với headbạn chỉ có thể sử dụng 3 chữ số đầu tiên.

Tôi không biết lệnh này đáng tin cậy như thế nào.

Lưu ý: Bị đánh cắp một cách đáng xấu hổ từ câu trả lời này

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.