Как рассчитать разницу во времени в сценарии bash?

Я печатаю время начала и окончания с использованием date +"%T" , что приводит к чему-то вроде:

 10:33:56 10:36:10 

Как я мог рассчитать и распечатать разницу между этими двумя?

Я хотел бы получить что-то вроде:

 2m 14s 

У Bash есть удобная встроенная переменная SECONDS которая отслеживает количество секунд, прошедших с момента запуска оболочки. Эта переменная сохраняет свои свойства при назначении, а значение, возвращаемое после присвоения, – это количество секунд с момента назначения плюс присвоенное значение.

Таким образом, вы можете просто установить SECONDS в 0 перед запуском события времени, просто прочитайте SECONDS после события и выполните арифметику времени перед отображением.

 SECONDS=0 # do some work duration=$SECONDS echo "$(($duration / 60)) minutes and $(($duration % 60)) seconds elapsed." 

Поскольку это решение не зависит от date +%s (которое является расширением GNU), оно переносимо для всех систем, поддерживаемых Bash.

секунд

Чтобы измерить прошедшее время (в секундах), нам необходимо:

  • целое число, которое представляет количество прошедших секунд и
  • способ преобразования такого целого в полезный формат.

Целое число прошедших секунд:

  • Существует два внутренних пути bash для нахождения целочисленного значения для количества прошедших секунд:

    1. Bash variable SECONDS (если SECONDS не установлен, он теряет свое специальное свойство).

      • Установка значения SECONDS в 0:

         SECONDS=0 sleep 1 # Process to execute elapsedseconds=$SECONDS 
      • Хранение значения переменной SECONDS в начале:

         a=$SECONDS sleep 1 # Process to execute elapsedseconds=$(( SECONDS - a )) 
    2. Bash printf option %(datefmt)T :

       a="$(TZ=UTC0 printf '%(%s)T\n' '-1')" ### `-1` is the current time sleep 1 ### Process to execute elapsedseconds=$(( $(TZ=UTC0 printf '%(%s)T\n' '-1') - a )) 

Преобразование такого целого в удобный формат

Внутренний printf bash может сделать это напрямую:

 $ TZ=UTC0 printf '%(%H:%M:%S)T\n' 12345 03:25:45 

по аналогии

 $ elapsedseconds=$((12*60+34)) $ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds" 00:12:34 

но это не будет длиться более 24 часов, так как мы на самом деле печатаем время на стене, а не продолжительность:

 $ hours=30;mins=12;secs=24 $ elapsedseconds=$(( ((($hours*60)+$mins)*60)+$secs )) $ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds" 06:12:24 

Для любителей мелочей, от bash-hackers.org :

%(FORMAT)T выводит строку даты-времени, полученную в результате использования FORMAT в качестве строки форматирования для strftime(3) . Связанным аргументом является количество секунд с момента Epoch или -1 (текущее время) или -2 (время запуска оболочки). Если соответствующий аргумент не указан, текущее время используется по умолчанию.

Таким образом, вы можете просто вызвать textifyDuration $elpasedseconds где textifyDuration – еще одна реализация длительности печати:

 textifyDuration() { local duration=$1 local shiff=$duration local secs=$((shiff % 60)); shiff=$((shiff / 60)); local mins=$((shiff % 60)); shiff=$((shiff / 60)); local hours=$shiff local splur; if [ $secs -eq 1 ]; then splur=''; else splur='s'; fi local mplur; if [ $mins -eq 1 ]; then mplur=''; else mplur='s'; fi local hplur; if [ $hours -eq 1 ]; then hplur=''; else hplur='s'; fi if [[ $hours -gt 0 ]]; then txt="$hours hour$hplur, $mins minute$mplur, $secs second$splur" elif [[ $mins -gt 0 ]]; then txt="$mins minute$mplur, $secs second$splur" else txt="$secs second$splur" fi echo "$txt (from $duration seconds)" } 

Дата GNU.

Чтобы получить форматированное время, мы должны использовать внешний инструмент (дату GNU) несколькими способами, чтобы получить почти дольше года и в том числе наносекунды.

Математика внутри даты.

Нет необходимости в внешней арифметике, сделайте все за один шаг в date :

 date -u -d "0 $FinalDate seconds - $StartDate seconds" +"%H:%M:%S" 

Да, в командной строке 0 0. Необходимо.

Предполагается, что вы можете изменить date +"%T" на date +"%s" чтобы значения сохранялись (печатались) в секундах.

Обратите внимание, что команда ограничена:

  • Положительные значения $StartDate и $FinalDate секунд.
  • Значение в $FinalDate больше (позже во времени), чем $StartDate .
  • Разница во времени меньше 24 часов.
  • Вы принимаете формат вывода с часами, секундами и секундами. Очень легко изменить.
  • Допустимо использовать -u UTC раз. Чтобы избежать «DST» и местных поправок времени.

Если вы должны использовать строку 10:33:56 , ну, просто преобразуйте ее в секунды,
Кроме того, слово секунд может быть сокращено в секундах:

 string1="10:33:56" string2="10:36:10" StartDate=$(date -u -d "$string1" +"%s") FinalDate=$(date -u -d "$string2" +"%s") date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S" 

Обратите внимание, что преобразование времени секунд (как представлено выше) относится к началу этого «дня» (сегодня).


Концепция может быть расширена до наносекунд, например:

 string1="10:33:56.5400022" string2="10:36:10.8800056" StartDate=$(date -u -d "$string1" +"%s.%N") FinalDate=$(date -u -d "$string2" +"%s.%N") date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S.%N" 

Если требуется рассчитать более длительные (до 364 дней) разницы во времени, мы должны использовать начало (некоторого) года в качестве эталона и значение формата %j (номер дня в году):

Похожий на:

 string1="+10 days 10:33:56.5400022" string2="+35 days 10:36:10.8800056" StartDate=$(date -u -d "2000/1/1 $string1" +"%s.%N") FinalDate=$(date -u -d "2000/1/1 $string2" +"%s.%N") date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N" Output: 026 days 00:02:14.340003400 

К сожалению, в этом случае нам нужно вручную вычесть 1 ONE из числа дней. Команда date отображает первый день года как 1. Не так сложно …

 a=( $(date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N") ) a[0]=$((10#${a[0]}-1)); echo "${a[@]}" 

Использование большого количества секунд действителен и документируется здесь:
https://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html#Examples-of-date


Дата Busybox

Инструмент, используемый в небольших устройствах (очень маленький исполняемый файл для установки): Busybox.

Либо сделайте ссылку на busybox с именем date:

 $ ln -s /bin/busybox date 

Затем используйте эту date (поместите ее в каталог, содержащий PATH).

Или сделайте псевдоним вроде:

 $ alias date='busybox date' 

Дата Busybox имеет приятный вариант: -D для получения формата времени ввода. Это открывает множество форматов, которые будут использоваться как время. Используя опцию -D, мы можем напрямую конвертировать время 10:33:56:

 date -D "%H:%M:%S" -d "10:33:56" +"%Y.%m.%d-%H:%M:%S" 

И как вы можете видеть из вывода команды выше, этот день считается «сегодня». Чтобы получить время, начинающееся с эпохи:

 $ string1="10:33:56" $ date -u -D "%Y.%m.%d-%H:%M:%S" -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S" 1970.01.01-10:33:56 

Дата Busybox может даже получать время (в формате выше) без -D:

 $ date -u -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S" 1970.01.01-10:33:56 

И выходной формат может быть даже секунд с эпохи.

 $ date -u -d "1970.01.01-$string1" +"%s" 52436 

Для обоих времен, и немного bash math (busybox не может выполнить математику, пока):

 string1="10:33:56" string2="10:36:10" t1=$(date -u -d "1970.01.01-$string1" +"%s") t2=$(date -u -d "1970.01.01-$string2" +"%s") echo $(( t2 - t1 )) 

Или отформатирован:

 $ date -u -D "%s" -d "$(( t2 - t1 ))" +"%H:%M:%S" 00:02:14 

Вот как я это сделал:

 START=$(date +%s); sleep 1; # Your stuff END=$(date +%s); echo $((END-START)) | awk '{print int($1/60)":"int($1%60)}' 

На самом деле просто, возьмите количество секунд в начале, затем возьмите количество секунд в конце и распечатайте разницу в минутах: секунды.

Другим вариантом является использование dateutils от dateutils ( http://www.fresse.org/dateutils/#datediff ):

 $ datediff 10:33:56 10:36:10 134s $ datediff 10:33:56 10:36:10 -f%H:%M:%S 0:2:14 $ datediff 10:33:56 10:36:10 -f%0H:%0M:%0S 00:02:14 

Вы также можете использовать gawk . mawk 1.3.4 также имеет strftime и mktime но более старые версии mawk и nawk этого не делают.

 $ TZ=UTC0 awk 'BEGIN{print strftime("%T",mktime("1970 1 1 10 36 10")-mktime("1970 1 1 10 33 56"))}' 00:02:14 

Или вот еще один способ сделать это с GNU date :

 $ date [email protected]$(($(date -ud'1970-01-01 10:36:10' +%s)-$(date -ud'1970-01-01 10:33:56' +%s))) +%T 00:02:14 

Я хотел бы предложить другой способ избежать напоминания о команде date . Это может быть полезно в случае, если вы уже собрали временные метки в формате даты %T :

 ts_get_sec() { read -rhms <<< $(echo $1 | tr ':' ' ' ) echo $(((h*60*60)+(m*60)+s)) } start_ts=10:33:56 stop_ts=10:36:10 START=$(ts_get_sec $start_ts) STOP=$(ts_get_sec $stop_ts) DIFF=$((STOP-START)) echo "$((DIFF/60))m $((DIFF%60))s" 

мы можем обрабатывать миллисекунды одинаково.

 ts_get_msec() { read -rhms ms <<< $(echo $1 | tr '.:' ' ' ) echo $(((h*60*60*1000)+(m*60*1000)+(s*1000)+ms)) } start_ts=10:33:56.104 stop_ts=10:36:10.102 START=$(ts_get_msec $start_ts) STOP=$(ts_get_msec $stop_ts) DIFF=$((STOP-START)) min=$((DIFF/(60*1000))) sec=$(((DIFF%(60*1000))/1000)) ms=$(((DIFF%(60*1000))%1000)) echo "${min}:${sec}.$ms" 

Вот какая-то магия:

 time1=14:30 time2=$( date +%H:%M ) # 16:00 diff=$( echo "$time2 - $time1" | sed 's%:%+(1/60)*%g' | bc -l ) echo $diff hours # outputs 1.5 hours 

sed заменяет : формулой для преобразования в 1/60. Тогда расчет времени, который производится bc

Начиная с даты (GNU coreutils) 7.4 теперь вы можете использовать -d для арифметики:

 $ date -d -30days Sat Jun 28 13:36:35 UTC 2014 $ date -d tomorrow Tue Jul 29 13:40:55 UTC 2014 

Единицами, которые вы можете использовать, являются дни, годы, месяцы, часы, минуты и секунды:

 $ date -d tomorrow+2days-10minutes Thu Jul 31 13:33:02 UTC 2014 

Следуя от ответа Даниэля Камиля Козара, чтобы показать часы / минуты / секунды:

 echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds" 

Таким образом, полный скрипт будет:

 date1=$(date +"%s") date2=$(date +"%s") diff=$(($date2-$date1)) echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds" 

Или немного сверните

 alias timerstart='starttime=$(date +"%s")' alias timerstop='echo seconds=$(($(date +"%s")-$starttime))' 

Тогда это работает.

 timerstart; sleep 2; timerstop seconds=2 
 % start=$(date +%s) % echo "Diff: $(date -d @$(($(date +%s)-$start)) +"%M minutes %S seconds")" Diff: 00 minutes 11 seconds 

С units GNU:

 $ units 2411 units, 71 prefixes, 33 nonlinear units You have: (10hr+36min+10s)-(10hr+33min+56s) You want: s * 134 / 0.0074626866 You have: (10hr+36min+10s)-(10hr+33min+56s) You want: min * 2.2333333 / 0.44776119 

date может дать вам разницу и отформатировать ее для вас (показаны варианты OS X)

 date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) +%T # 00:02:14 date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) \ +'%-Hh %-Mm %-Ss' # 0h 2m 14s 

Некоторая обработка строк может удалить эти пустые значения

 date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) \ +'%-Hh %-Mm %-Ss' | sed "s/[[:<:]]0[hms] *//g" # 2m 14s 

Это не сработает, если вы поместите ранее раннее время. Если вам нужно это обработать, измените $(($(date ...) - $(date ...))) на $(echo $(date ...) - $(date ...) | bc | tr -d -)

Вот решение, использующее только функции команд date , используя «назад», и не используя вторую переменную для сохранения времени окончания:

 #!/bin/bash # save the current time start_time=$( date +%s.%N ) # tested program sleep 1 # the current time after the program has finished # minus the time when we started, in seconds.nanoseconds elapsed_time=$( date +%s.%N --date="$start_time seconds ago" ) echo elapsed_time: $elapsed_time 

это дает:

 $ ./time_elapsed.sh elapsed_time: 1.002257120 

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

 #!/bin/bash dTime="" tmp="" #firstEntry="$(head -n 1 "$LOG" | sed 's/.*] \([0-9: -]\+\).*/\1/')" firstEntry="2013-01-16 01:56:37" #lastEntry="$(tac "$LOG" | head -n 1 | sed 's/.*] \([0-9: -]\+\).*/\1/')" lastEntry="2014-09-17 18:24:02" # I like to make the variables easier to parse firstEntry="${firstEntry//-/ }" lastEntry="${lastEntry//-/ }" firstEntry="${firstEntry//:/ }" lastEntry="${lastEntry//:/ }" # remove the following lines in production echo "$lastEntry" echo "$firstEntry" # compute days in last entry for i in `seq 1 $(echo $lastEntry|awk '{print $2}')`; do { case "$i" in 1|3|5|7|8|10|12 ) dTime=$(($dTime+31)) ;; 4|6|9|11 ) dTime=$(($dTime+30)) ;; 2 ) dTime=$(($dTime+28)) ;; esac } done # do leap year calculations for all years between first and last entry for i in `seq $(echo $firstEntry|awk '{print $1}') $(echo $lastEntry|awk '{print $1}')`; do { if [ $(($i%4)) -eq 0 ] && [ $(($i%100)) -eq 0 ] && [ $(($i%400)) -eq 0 ]; then { if [ "$i" = "$(echo $firstEntry|awk '{print $1}')" ] && [ $(echo $firstEntry|awk '{print $2}') -lt 2 ]; then { dTime=$(($dTime+1)) } elif [ $(echo $firstEntry|awk '{print $2}') -eq 2 ] && [ $(echo $firstEntry|awk '{print $3}') -lt 29 ]; then { dTime=$(($dTime+1)) } fi } elif [ $(($i%4)) -eq 0 ] && [ $(($i%100)) -ne 0 ]; then { if [ "$i" = "$(echo $lastEntry|awk '{print $1}')" ] && [ $(echo $lastEntry|awk '{print $2}') -gt 2 ]; then { dTime=$(($dTime+1)) } elif [ $(echo $lastEntry|awk '{print $2}') -eq 2 ] && [ $(echo $lastEntry|awk '{print $3}') -ne 29 ]; then { dTime=$(($dTime+1)) } fi } fi } done # substract days in first entry for i in `seq 1 $(echo $firstEntry|awk '{print $2}')`; do { case "$i" in 1|3|5|7|8|10|12 ) dTime=$(($dTime-31)) ;; 4|6|9|11 ) dTime=$(($dTime-30)) ;; 2 ) dTime=$(($dTime-28)) ;; esac } done dTime=$(($dTime+$(echo $lastEntry|awk '{print $3}')-$(echo $firstEntry|awk '{print $3}'))) # The above gives number of days for sample. Now we need hours, minutes, and seconds # As a bit of hackery I just put the stuff in the best order for use in a for loop dTime="$(($(echo $lastEntry|awk '{print $6}')-$(echo $firstEntry|awk '{print $6}'))) $(($(echo $lastEntry|awk '{print $5}')-$(echo $firstEntry|awk '{print $5}'))) $(($(echo $lastEntry|awk '{print $4}')-$(echo $firstEntry|awk '{print $4}'))) $dTime" tmp=1 for i in $dTime; do { if [ $i -lt 0 ]; then { case "$tmp" in 1 ) tmp="$(($(echo $dTime|awk '{print $1}')+60)) $(($(echo $dTime|awk '{print $2}')-1))" dTime="$tmp $(echo $dTime|awk '{print $3" "$4}')" tmp=1 ;; 2 ) tmp="$(($(echo $dTime|awk '{print $2}')+60)) $(($(echo $dTime|awk '{print $3}')-1))" dTime="$(echo $dTime|awk '{print $1}') $tmp $(echo $dTime|awk '{print $4}')" tmp=2 ;; 3 ) tmp="$(($(echo $dTime|awk '{print $3}')+24)) $(($(echo $dTime|awk '{print $4}')-1))" dTime="$(echo $dTime|awk '{print $1" "$2}') $tmp" tmp=3 ;; esac } fi tmp=$(($tmp+1)) } done echo "The sample time is $(echo $dTime|awk '{print $4}') days, $(echo $dTime|awk '{print $3}') hours, $(echo $dTime|awk '{print $2}') minutes, and $(echo $dTime|awk '{print $1}') seconds." 

Вы получите результат следующим образом.

 2012 10 16 01 56 37 2014 09 17 18 24 02 The sample time is 700 days, 16 hours, 27 minutes, and 25 seconds. 

Я немного изменил сценарий, чтобы сделать его автономным (т. Е. Просто установить значения переменных), но, возможно, общая идея также встречается. Возможно, вам понадобится дополнительная проверка ошибок для отрицательных значений.

Мне нужен сценарий разницы во времени для использования с mencoder (его --endpos относительный), и мое решение – вызвать скрипт Python:

 $ ./timediff.py 1:10:15 2:12:44 1:02:29 

Также поддерживаются доли секунд:

 $ echo "diff is `./timediff.py 10:51.6 12:44` (in hh:mm:ss format)" diff is 0:01:52.4 (in hh:mm:ss format) 

и он может сказать вам, что разница между 200 и 120 составляет 1h 20m:

 $ ./timediff.py 120:0 200:0 1:20:0 

и может конвертировать любое (возможно, дробное) количество секунд или минут или часов в hh: mm: ss

 $ ./timediff.py 0 3600 1:00:0 $ ./timediff.py 0 3.25:0:0 3:15:0 

timediff.py:

 #!/usr/bin/python import sys def x60(h,m): return 60*float(h)+float(m) def seconds(time): try: h,m,s = time.split(':') return x60(x60(h,m),s) except ValueError: try: m,s = time.split(':') return x60(m,s) except ValueError: return float(time) def difftime(start, end): d = seconds(end) - seconds(start) print '%d:%02d:%s' % (d/3600,d/60%60,('%02f' % (d%60)).rstrip('0').rstrip('.')) if __name__ == "__main__": difftime(sys.argv[1],sys.argv[2]) 

Обобщение решения @ nisetama с использованием даты GNU (надежный Ubuntu 14.04 LTS):

 start=`date` #  stop=`date` duration=`date [email protected]$(($(date -ud"$stop" +%s)-$(date -ud"$start" +%s))) +%T` echo $start echo $stop echo $duration 

получая:

 Wed Feb 7 12:31:16 CST 2018 Wed Feb 7 12:32:25 CST 2018 00:01:09 

Я не могу комментировать ответ mcaleaa, поэтому я размещаю его здесь. Переменная «diff» должна быть на маленьком корпусе. Вот пример.

 [[email protected] ~]# date1=$(date +"%s"); date Wed Feb 21 23:00:20 MYT 2018 [[email protected] ~]# [[email protected] ~]# date2=$(date +"%s"); date Wed Feb 21 23:00:33 MYT 2018 [[email protected] ~]# [[email protected] ~]# diff=$(($date2-$date1)) [[email protected] ~]# 

Предыдущая переменная была объявлена ​​в нижнем регистре. Это то, что произошло, когда используется верхний регистр.

 [[email protected] ~]# echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds" -bash: / 3600 : syntax error: operand expected (error token is "/ 3600 ") [[email protected] ~]# 

Итак, быстрое исправление будет таким:

 [[email protected] ~]# echo "Duration: $(($diff / 3600 )) hours $((($diff % 3600) / 60)) minutes $(($diff % 60)) seconds" Duration: 0 hours 0 minutes 13 seconds [[email protected] ~]# 

Вот моя реализация bash (с битами, взятыми из других SO 😉

 function countTimeDiff() { timeA=$1 # 09:59:35 timeB=$2 # 17:32:55 # feeding variables by using read and splitting with IFS IFS=: read ah am as <<< "$timeA" IFS=: read bh bm bs <<< "$timeB" # Convert hours to minutes. # The 10# is there to avoid errors with leading zeros # by telling bash that we use base 10 secondsA=$((10#$ah*60*60 + 10#$am*60 + 10#$as)) secondsB=$((10#$bh*60*60 + 10#$bm*60 + 10#$bs)) DIFF_SEC=$((secondsB - secondsA)) echo "The difference is $DIFF_SEC seconds."; SEC=$(($DIFF_SEC%60)) MIN=$((($DIFF_SEC-$SEC)%3600/60)) HRS=$((($DIFF_SEC-$MIN*60)/3600)) TIME_DIFF="$HRS:$MIN:$SEC"; echo $TIME_DIFF; } $ countTimeDiff 2:15:55 2:55:16 The difference is 2361 seconds. 0:39:21 , function countTimeDiff() { timeA=$1 # 09:59:35 timeB=$2 # 17:32:55 # feeding variables by using read and splitting with IFS IFS=: read ah am as <<< "$timeA" IFS=: read bh bm bs <<< "$timeB" # Convert hours to minutes. # The 10# is there to avoid errors with leading zeros # by telling bash that we use base 10 secondsA=$((10#$ah*60*60 + 10#$am*60 + 10#$as)) secondsB=$((10#$bh*60*60 + 10#$bm*60 + 10#$bs)) DIFF_SEC=$((secondsB - secondsA)) echo "The difference is $DIFF_SEC seconds."; SEC=$(($DIFF_SEC%60)) MIN=$((($DIFF_SEC-$SEC)%3600/60)) HRS=$((($DIFF_SEC-$MIN*60)/3600)) TIME_DIFF="$HRS:$MIN:$SEC"; echo $TIME_DIFF; } $ countTimeDiff 2:15:55 2:55:16 The difference is 2361 seconds. 0:39:21 

Не проверено, может быть глючит.

  • «Непревзойденная дата: 1302828677828», пытающаяся десериализовать с помощью Gson дату в миллисекундах, полученную с сервера
  • Java getHours (), getMinutes () и getSeconds ()
  • Преобразование даты в MySQL из поля строки
  • Как рассчитать «время назад» в Java?
  • В Ruby on Rails, какая разница между DateTime, Timestamp, Time и Date?
  • Преобразование строки Java в дату
  • Java: почему устаревший конструктор даты не используется, и что я использую вместо этого?
  • Выделите даты в определенном диапазоне с помощью датпикера jQuery
  • Как выбрать только дату из поля datetime в MySQL
  • Разница между двумя датами в Python
  • Случайная дата в C #
  • Давайте будем гением компьютера.