Як знайти різницю між двома часовими позначками до мілісекунд?


10

Я новачок в сценарії оболонок. Основою мого сценарію є пошук різниці між двома часовими позначками до мілісекунд. У мене є файл із вмістом часових міток лише як

2012-09-13 15:00:29,290 2012-09-13 15:00:29,297
2012-09-13 15:00:29,428 2012-09-13 15:00:29,447

У такий спосіб у мене є близько 30 тис. Записів, де я не повинен стикатися з будь-якими проблемами продуктивності при виконанні сценарію. Багато факторів, таких як високосний рік, місяці з 31 днем ​​і т.д.

Хтось може мені допомогти з цього приводу?


1
Чи входить DST на малюнок? Стрибки секунди? Які правила DST? Чи змінилися вони з часом у вашій країні? Чи маєте ви мати справу з датами до 1970 року або перед переходом на григоріанський календар?
Стефан Шазелас

Відповіді:


13

Не потрібно робити складний синтаксичний аналіз, зробить для вас все чари за допомогою свого друга, :

#!/bin/bash
while read d1_1 d1_2 d2_1 d2_2; do
  secdiff=$((
    $(date -d "$d2_1 $d2_2" +%s) - $(date -d "$d1_1 $d1_2" +%s)
  ))
  nanosecdiff=$((
    $(date -d "$d2_1 $d2_2" +%N) - $(date -d "$d1_1 $d1_2" +%N)
  ))
  printf "%s %s - %s %s = %d milliseconds\n" $d2_1 $d2_2 $d1_1 $d1_2 $((
    (secdiff * 1000) + (nanosecdiff / 1000000)
  ))
done < YOUR_FILE.txt

ВИХІД

2012-09-13 15:00:29,297 - 2012-09-13 15:00:29,290 = 7 milliseconds
2012-09-13 15:00:29,447 - 2012-09-13 15:00:29,428 = 19 milliseconds

Подивитися man date

ПРИМІТКА

  • date -d дуже корисно, воно конвертує часові позначки
  • %s- час епохи (секунди з 01.01-1970)
  • %Nє наносекундами
  • $(( ))а (( ))для bashарифметики див. http://mywiki.wooledge.org/ArithmeticExpression
  • $( ) виступає за command substitution

Чи відповідає це вашим потребам?


1
Виправлена арифметична помилка (об'єднання секунд і наносекунд). Тепер я спочатку обчислюю секунди (ОП не просив цього, але для повноти та надійності при повторному використанні)
Жилль Квінот

0

Мова сценаріїв, таких як Perl, Python або Ruby, буде швидкою і вимагає невеликих зусиль. Наприклад, за допомогою Perl та Date :: Parse :

perl -MDate::Parse -l -ne 's/,/./g; split; print str2time("$_[2] $_[3]") - str2time("$_[0] $_[1]")'

(Для кожного рядка замініть ,на ., розділіть рядок на слова $_[0]наскрізь $_[3], проаналізуйте дати, утворені першими двома та наступними двома словами, та надрукуйте різницю.)


"Маленькі зусилля" досить відносні. Звичайно, якщо ви програміст X і знаєте про бібліотеку Y, це синч. Ось як завжди. Власне, я здивований, що програміст Python ще не ввійшов сюди. Я вважаю, що це лише питання часу ...: - \
Майк S

Ось чому люди дають тут повне рішення. Таким чином, вам не потрібно бути програмістом X або знати про бібліотеку Y. І ви все ще отримаєте користь від «малих зусиль» того, що у вашому сценарії є один рядок, а не 10.
CherryDT

0

Я щойно натрапив на цю посаду, є, принаймні сьогодні, більш просте dateрішення. Використовуючи рамки у відповіді @Gilles Quenot (написав би коментар своєму прихильнику, але недостатньо репутації):

while read d1_1 d1_2 d2_1 d2_2
do
    date -d "$d2_1 $d2_2 $(date -d "$d1_1 $d1_2" +%s.%N) seconds ago" +%s.%N
done << END
2012-09-13 15:00:29,290 2012-09-13 15:00:29,297
END

Результат:

$ ./time_elapsed.sh 
0.007000000

Використання %3Nзамість %Nурізає вихід до мілісекунд.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.