Как получить текущее время Unix в миллисекундах в Bash?


232

Как узнать текущее время Unix в миллисекундах (т. Е. Количество миллисекунд с начала Unix 1 января 1970 года)?

Ответы:


265

Этот:

date +%s 

вернет количество секунд с начала эпохи.

Этот:

date +%s%N

возвращает секунды и текущие наносекунды.

Так:

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

даст вам количество миллисекунд с начала эпохи - текущие секунды плюс три оставшиеся наносекунды.


и от MikeyB - echo $(($(date +%s%N)/1000000))(деление на 1000 приносит только микросекунды)


39
Интересно, сколько мс добавляет сокращение :-)
Кайл Брандт

13
Или, если вы хотите сделать все это в оболочке, избегая дорогостоящих накладных расходов на дополнительный процесс (на самом деле, мы избегаем проблемы при изменении числа цифр в% + s + N):echo $(($(date +%s%N)/1000))
MikeyB

5
Это принцип дела ... избегайте магических чисел и кодируйте то, что вы на самом деле имеете в виду .
MikeyB

25
Я думаю, что стоит отметить, что этот человек попросил Unix, а не Linux, и текущий топовый ответ (дата +% s% N) не работает в моей системе AIX.
Пит

12
@ Пит +1 То же самое для OS X и FreeBSD
ocodo

100

Вы можете просто использовать, %3Nчтобы урезать наносекунды до 3 самых значащих цифр (которые тогда являются миллисекундами):

$ date +%s%3N
1397392146866

Это работает, например, на моем Kubuntu 12.04.

Но имейте в виду, что %Nэто не может быть реализовано в зависимости от вашей целевой системы. Например, тестирование во встроенной системе (buildroot rootfs, скомпилированный с использованием не-HF-кросс-цепочки инструментов) не было %N:

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

(А также у моего (не рутированного) планшета Android нет %N).


1
@warren: Я видел , что вы редактировали и изменил 1397392146%3Nк 1397392146%N, но вывод в 1397392146%3Nтом , что то , что я действительно видел на BusyBox консоли моего андроид планшета. Не могли бы вы объяснить ваши изменения?
Джо

Комментарий Уоррена из истории «изменен с 3 на 6, так как 3 переводит вас в микросекунды». Его редактирование кажется совершенно ложным; ты должен откатиться назад.
Букзор

1
Это особенность GNU coreutils специально. В конечном счете, это реализовано в gnulib здесь: github.com/gagern/gnulib/blob/… .
телоториум

вероятно, точка там имеет смысл. date +%s.%3Nпечать 1510718281.134.
Даркский

Это должен быть принятый ответ.
Ноа Суссман

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
Камило Мартин

8
Или, если вам на самом деле не нужны миллисекунды, а только правильный формат:date +%s000
Ленар Хойт

1
В apple.stackexchange.com/questions/135742/… есть инструкции по выполнению этого в OSX с помощью Brew'scoreutils
sameers

10

Просто добавлю это, но я думаю, что правильная формула с делением была бы:

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

10

Мое решение не лучшее, но сработало для меня.

date +%s000

Мне просто нужно было преобразовать дату, например 2012-05-05, в миллисекунды.


1
Удивительный хак, лол :)
k06a

7
Вы, должно быть, кто-то из моих коллег.
Накилон

7

Для людей, которые предлагают запускать внешние программы, чтобы получить миллисекунды ... с такой скоростью, вы могли бы также сделать это:

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

Суть в том, что перед тем, как выбрать любой ответ отсюда, имейте в виду, что не все программы будут работать менее одной секунды. Мера!


Вы не спрашиваете местную систему о времени. Что, я думаю, подразумевается в вопросе. Вы также зависите от сетевого подключения.
orkoden

2
@orkoden Вопрос явно задает «количество миллисекунд с начала Unix 1 января 1970 года». Кроме того, я больше указываю на то, что вам никогда не следует запускать весь Ruby или Python (или wget) просто для того, чтобы получить время - либо это делается по быстрому каналу, либо миллисекунды не имеют значения.
Камило Мартин

2
Да, я понял, что вы предлагаете худшее решение, чтобы подчеркнуть недостатки плохих решений. Я попробовал несколько решений и измерил время. lpaste.net/119499 Результаты довольно интересные. Даже на очень быстрой машине i7 dateдля запуска требуется 3 мс.
orkoden

@orkoden Хорошее тестирование! Какая ОС? Это может быть связано с порождением процесса.
Камило Мартин

1
@Nakilon, и именно поэтому не стоит полагаться на такие удобные удобства, как при производстве чего-либо.
Камило Мартин

5

это решение работает на macOS.

если вы планируете использовать bash-скрипт и имеете Python, вы можете использовать этот код:

#!/bin/bash

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

почему голосование против?
Фрэнк Тониг

Не кажется особенно оправданным. Подсказка на стрелке вниз говорит: «Этот ответ бесполезен», но 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>
Уоррен

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кажется более надежным вариантом.
Акостадинов

2

Наиболее точная временная метка, которую мы можем получить (по крайней мере, для Mac OS X), вероятно, такова:

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

1490665305.021699

Но мы должны помнить, что для запуска требуется около 30 миллисекунд. Мы можем сократить его до шкалы из двухзначной дроби и в самом начале вычислить средние накладные расходы на считывание времени, а затем убрать его из измерения. Вот пример:

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

Простейшим способом было бы сделать небольшой исполняемый файл (из Cf.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"})'

ОП специально попросил способы сделать это с помощью bash. Как этот bash, сохранить как метод для запуска чего-то еще?
MadHatter

Я использую это в моих скриптах оболочки bash ... под OSX. Таким образом, dateне может быть использовано, и нет команд только для bash, которые отвечают потребности.
TVNshack

Справедливо. Если бы вы разъяснили, почему OSX dateнельзя использовать как часть вашего ответа , я бы убрал свое отрицательное мнение.
MadHatter

Это было объяснено несколькими ответами выше. Я не мог добавить в качестве комментария ту команду, которая отсутствовала в предложенном списке. Так что я добавил это здесь.
TVNshack

Честно говоря, я принимаю это полезное дополнение к канону. +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

Для Alpine Linux (много образов Docker) и, возможно, других минимальных сред Linux, вы можете злоупотреблять adjtimex:

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

adjtimexиспользуется для чтения (и установки) переменных времени ядра. С помощью awkвы можете получить микросекунды, с помощью headвы можете использовать только первые 3 цифры.

Я понятия не имею, насколько надежна эта команда.

Примечание: бесстыдно украден из этого ответа

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.