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

26 Charlie [2012-08-30 17:49:00]

Как я могу конвертировать секунды в часы, минуты и секунды?

show_time() {
  ?????
}

show_time 36 # 00:00:36
show_time 1036 # 00:17:26
show_time 91925 # 25:32:05

bash


13 ответов


27 Решение choroba [2012-08-30 17:59:00]

Я сам использую следующую функцию:

function show_time () {
    num=$1
    min=0
    hour=0
    day=0
    if((num>59));then
        ((sec=num%60))
        ((num=num/60))
        if((num>59));then
            ((min=num%60))
            ((num=num/60))
            if((num>23));then
                ((hour=num%24))
                ((day=num/24))
            else
                ((hour=num))
            fi
        else
            ((min=num))
        fi
    else
        ((sec=num))
    fi
    echo "$day"d "$hour"h "$min"m "$sec"s
}

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


70 perreal [2012-08-30 17:58:00]

#!/bin/sh

convertsecs() {
 ((h=${1}/3600))
 ((m=(${1}%3600)/60))
 ((s=${1}%60))
 printf "%02d:%02d:%02d\n" $h $m $s
}
TIME1="36"
TIME2="1036"
TIME3="91925"

echo $(convertsecs $TIME1)
echo $(convertsecs $TIME2)
echo $(convertsecs $TIME3)

Для секунд float:

convertsecs() {
 h=$(bc <<< "${1}/3600")
 m=$(bc <<< "(${1}%3600)/60")
 s=$(bc <<< "${1}%60")
 printf "%02d:%02d:%05.2f\n" $h $m $s
}

36 BashDevel [2015-02-11 12:59:00]

Самый простой способ, которым я знаю:

secs=100000
printf '%dh:%dm:%ds\n' $(($secs/3600)) $(($secs%3600/60)) $(($secs%60))

Примечание. Если вы хотите дней, просто добавьте другой блок и разделите его на 86400.


35 ACyclic [2015-03-26 04:55:00]

Дата использования, конвертированная в UTC:

$ date -d@36 -u +%H:%M:%S
00:00:36
$ date -d@1036 -u +%H:%M:%S
00:17:16
$ date -d@12345 -u +%H:%M:%S
03:25:45

Ограничение состоит в том, что часы будут зацикливаться на 23, но это не имеет значения для большинства случаев использования, когда вы хотите использовать одну строку.

В macOS запустите brew install coreutils и замените date на gdate


17 qubodup [2016-09-12 17:24:00]

Простой однострочный

$ secs=236521
$ printf '%dh:%dm:%ds\n' $(($secs/3600)) $(($secs%3600/60)) $(($secs%60))
65h:42m:1s

С ведущими нулями

$ secs=236521
$ printf '%02dh:%02dm:%02ds\n' $(($secs/3600)) $(($secs%3600/60)) $(($secs%60))
65h:42m:01s

С днями

$ secs=236521
$ printf '%dd:%dh:%dm:%ds\n' $(($secs/86400)) $(($secs%86400/3600)) $(($secs%3600/60)) \
  $(($secs%60))
2d:17h:42m:1s

С наносекундами

$ secs=21218.6474912
$ printf '%02dh:%02dm:%02fs\n' $(echo -e "$secs/3600\n$secs%3600/60\n$secs%60"| bc | xargs echo)
05h:53m:38.647491s

На основании qaru.site/questions/208925/... но редактирование отклонено.


9 eMPee584 [2015-08-23 11:31:00]

Для нас ленивые люди: готовые script доступны https://github.com/k0smik0/FaCRI/blob/master/fbcmd/bin/displaytime:

#!/bin/bash

function displaytime {
  local T=$1
  local D=$((T/60/60/24))
  local H=$((T/60/60%24))
  local M=$((T/60%60))
  local S=$((T%60))
  [[ $D > 0 ]] && printf '%d days ' $D
  [[ $H > 0 ]] && printf '%d hours ' $H
  [[ $M > 0 ]] && printf '%d minutes ' $M
  [[ $D > 0 || $H > 0 || $M > 0 ]] && printf 'and '
  printf '%d seconds\n' $S
}

displaytime $1

В основном просто другое вращение на других решениях, но имеет дополнительный бонус для подавления пустых единиц времени (т.е. 10 seconds вместо 0 hours 0 minutes 10 seconds). Не удалось полностью отследить исходный источник функции, происходит в нескольких репозиториях git.


5 Lri [2014-03-26 17:08:00]

t=12345;printf %02d:%02d:%02d\\n $((t/3600)) $((t%3600/60)) $((t%60)) # POSIX
echo 12345|awk '{printf "%02d:%02d:%02d",$0/3600,$0%3600/60,$0%60}' # POSIX awk
date -d @12345 +%T # GNU date
date -r 12345 +%T # OS X date

Если другие искали, как сделать обратное:

IFS=: read h m s<<<03:25:45;echo $((h*3600+m*60+s)) # POSIX
echo 03:25:45|awk -F: '{print 3600*$1+60*$2+$3}' # POSIX awk

5 Vaulter [2013-09-08 15:46:00]

Все выше для bash, не считая там "#!/bin/sh" без какого-либо бахизма будет:

convertsecs() {
    h=`expr $1 / 3600`
    m=`expr $1  % 3600 / 60`
    s=`expr $1 % 60`
    printf "%02d:%02d:%02d\n" $h $m $s
}

3 linuph [2013-09-29 19:56:00]

Я не мог заставить код Vaulter/chepner работать правильно. Я думаю, что правильный код:

convertsecs() {
    h=$(($1/3600))
    m=$((($1/60)%60))
    s=$(($1%60))
    printf "02d:%02d:%02d\n $h $m $s
}

2 Cugel [2016-06-09 17:23:00]

В одной строке:

show_time () {

    if [ $1 -lt 86400 ]; then 
        date -d@${1} -u '+%Hh:%Mmn:%Ss';
    else 
        echo "$(($1/86400)) days $(date -d@$(($1%86400)) -u '+%Hh:%Mmn:%Ss')" ;
    fi
}

Добавьте дни, если они существуют.


1 Faron [2016-10-27 13:33:00]

Это старый пост ovbioius - но для тех, кто может искать фактическое время, прошедшее, но в военном формате (00: 05: 15: 22 - вместо 0: 5: 15: 22)

!#/bin/bash
    num=$1
    min=0
    hour=0
    day=0
    if((num>59));then
        ((sec=num%60))
        ((num=num/60))
            if((num>59));then
            ((min=num%60))
            ((num=num/60))
                if((num>23));then
                    ((hour=num%24))
                    ((day=num/24))
                else
                    ((hour=num))
                fi
            else
                ((min=num))
            fi
        else
        ((sec=num))
    fi
    day=`seq -w 00 $day | tail -n 1`
    hour=`seq -w 00 $hour | tail -n 1`
    min=`seq -w 00 $min | tail -n 1`
    sec=`seq -w 00 $sec | tail -n 1`
    printf "$day:$hour:$min:$sec"
 exit 0

0 splaisan [2018-02-13 11:43:00]

на MacOSX 10.13 Незначительное редактирование из кода @eMPee584, чтобы получить все в одном GO (поместите функцию в некоторый файл .bashrc, как и файл, и используйте его как myuptime. Для не-Mac OS замените формулу T на ту, которая дает секунды с последнего загрузки.

myuptime () 
{ 
    local T=$(($(date +%s)-$(sysctl -n kern.boottime | awk '{print $4}' | sed 's/,//g')));
    local D=$((T/60/60/24));
    local H=$((T/60/60%24));
    local M=$((T/60%60));
    local S=$((T%60));
    printf '%s' "UpTime: ";
    [[ $D > 0 ]] && printf '%d days ' $D;
    [[ $H > 0 ]] && printf '%d hours ' $H;
    [[ $M > 0 ]] && printf '%d minutes ' $M;
    [[ $D > 0 || $H > 0 || $M > 0 ]] && printf '%d seconds\n' $S
}

0 Scott Colby [2019-02-05 22:02:00]

Используя dc:

$ echo '12345.678' | dc -e '?1~r60~r60~rn[:]nn[:]nn[[.]n]sad0=ap'
3:25:45.678

Выражение ?1~r60~r60~rn[:]nn[:]nn[[.]n]sad0=ap делает следующее:

?   read a line from stdin
1   push one
~   pop two values, divide, push the quotient followed by the remainder
r   reverse the top two values on the stack
60  push sixty
~   pop two values, divide, push the quotient followed by the remainder
r   reverse the top two values on the stack
60  push sixty
~   pop two values, divide, push the quotient followed by the remainder
r   reverse the top two values on the stack
n   pop the top value from the stack and print it with no newline
[:] push the literal string ':' to the stack
n   pop the top value from the stack and print it with no newline
n   pop the top value from the stack and print it with no newline
[:] push the literal string ':' to the stack
n   pop the top value from the stack and print it with no newline
n   pop the top value from the stack and print it with no newline
[   interpret everything until the closing ] as a string
  [.]   push the literal string '.' to the stack
  n     pop the top value from the stack and print it with no newline
]   end of string, push the whole thing to the stack
sa  pop the top value (the string above) and store it in register a
d   duplicate the top value on the stack
0   push zero
=a  pop two values and execute register a if they are equal
p   pop the top value and print it with a newline

Пример выполнения с состоянием стека после каждой операции.

    : <empty stack>
?   : 12345.678
1   : 1, 12345.678
~   : .678, 12345
r   : 12345, .678  # stack is now seconds, fractional seconds
60  : 60, 12345, .678
~   : 45, 205, .678
r   : 205, 45, .678  # stack is now minutes, seconds, fractional seconds
60  : 60, 205, 45, .678
~   : 25, 3, 45, .678
r   : 3, 25, 45, .678  # stack is now hours, minutes, seconds, fractional seconds

n   : 25, 45, .678  # accumulated stdout: '3'
[:] : :, 25, 45, .678
n   : 25, 45, .678  # accumulated stdout: '3:'
n   : 45, .678  # accumulated stdout: '3:25'
[:] : :, 45, .678
n   : 45, .678  # accumulated stdout: '3:25:'
n   : .678  # accumulated stdout: '3:25:45'

[[.]n]  : [.]n, .678
sa  : .678  # '[.]n' stored to register a
d   : .678, .678
0   : 0, .678, .678
=a  : .678  # not equal, so register a not executed
p   : <empty stack>  # accumulated stdout: '3:25:45.678\n'

В случае 0 дробных секунд

    : 3, 25, 45, 0  # starting just before we begin to print
n   : 25, 45, 0  # accumulated stdout: '3'
[:] : :, 25, 45, 0
n   : 25, 45, 0  # accumulated stdout: '3:'
n   : 45, 0  # accumulated stdout: '3:25'
[:] : :, 45, 0
n   : 45, 0  # accumulated stdout: '3:25:'
n   : 0  # accumulated stdout: '3:25:45'

[[.]n]  : [.]n, 0
sa  : 0  # '[.]n' stored to register a
d   : 0, 0
0   : 0, 0, 0
=a  : 0  # equal, so register a executed
  [.] : ., 0
  n   : 0  # accumulated stdout: '3:35:45.'
p   : <empty stack>  # accumulated stdout: '3:25:45.0\n'