bash 将秒转换为小时、分钟、秒
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12199631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert seconds to hours, minutes, seconds
提问by Charlie
How can I convert seconds to hours, minutes and seconds?
如何将秒转换为小时、分钟和秒?
show_time() {
?????
}
show_time 36 # 00:00:36
show_time 1036 # 00:17:26
show_time 91925 # 25:32:05
采纳答案by choroba
I use the following function myself:
我自己使用以下功能:
function show_time () {
num=
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
}
Note it counts days as well. Also, it shows a different result for your last number.
请注意,它也计算天数。此外,它会为您的最后一个数字显示不同的结果。
回答by perreal
#!/bin/sh
convertsecs() {
((h=/3600))
((m=(%3600)/60))
((s=%60))
printf "%02d:%02d:%02d\n" $h $m $s
}
TIME1="36"
TIME2="1036"
TIME3="91925"
echo $(convertsecs $TIME1)
echo $(convertsecs $TIME2)
echo $(convertsecs $TIME3)
For float seconds:
对于浮动秒:
convertsecs() {
h=$(bc <<< "/3600")
m=$(bc <<< "(%3600)/60")
s=$(bc <<< "%60")
printf "%02d:%02d:%05.2f\n" $h $m $s
}
回答by ACyclic
Use date, converted to UTC:
使用日期,转换为 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
The limitation is the hours will loop at 23, but that doesn't matter for most use cases where you want a one-liner.
限制是小时数将在 23 点循环,但这对于大多数需要单行的用例来说并不重要。
On macOS, run brew install coreutils
and replace date
with gdate
在 macOS 上,运行brew install coreutils
并替换date
为gdate
回答by BashDevel
The simplest way I know of:
我所知道的最简单的方法:
secs=100000
printf '%dh:%dm:%ds\n' $(($secs/3600)) $(($secs%3600/60)) $(($secs%60))
Note - if you want days then just add other unit and divide by 86400.
注意 - 如果你想要天,那么只需添加其他单位并除以 86400。
回答by qubodup
Simple one-liner
简单的单线
$ secs=236521
$ printf '%dh:%dm:%ds\n' $(($secs/3600)) $(($secs%3600/60)) $(($secs%60))
65h:42m:1s
With leading zeroes
带前导零
$ secs=236521
$ printf '%02dh:%02dm:%02ds\n' $(($secs/3600)) $(($secs%3600/60)) $(($secs%60))
65h:42m:01s
With days
随着天
$ secs=236521
$ printf '%dd:%dh:%dm:%ds\n' $(($secs/86400)) $(($secs%86400/3600)) $(($secs%3600/60)) \
$(($secs%60))
2d:17h:42m:1s
With nanoseconds
纳秒级
$ 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
Based on https://stackoverflow.com/a/28451379/188159but edit got rejected.
回答by eMPee584
For us lazy people: ready-made script available at https://github.com/k0smik0/FaCRI/blob/master/fbcmd/bin/displaytime:
对于我们懒惰的人:https: //github.com/k0smik0/FaCRI/blob/master/fbcmd/bin/displaytime提供的现成脚本:
#!/bin/bash
function displaytime {
local T=
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
Basically just another spin on the other solutions, but has the added bonus of suppressing empty time units (f.e. 10 seconds
instead of 0 hours 0 minutes 10 seconds
). Couldn't quite track down the original source of the function, occurs in multiple git repos..
基本上只是其他解决方案的另一种旋转,但具有抑制空时间单位(fe10 seconds
而不是0 hours 0 minutes 10 seconds
)的额外好处。无法完全追踪该函数的原始来源,出现在多个 git 存储库中。
回答by Lri
t=12345;printf %02d:%02d:%02d\n $((t/3600)) $((t%3600/60)) $((t%60)) # POSIX
echo 12345|awk '{printf "%02d:%02d:%02d",IFS=: read h m s<<<03:25:45;echo $((h*3600+m*60+s)) # POSIX
echo 03:25:45|awk -F: '{print 3600*+60*+}' # POSIX awk
/3600,convertsecs() {
h=`expr / 3600`
m=`expr % 3600 / 60`
s=`expr % 60`
printf "%02d:%02d:%02d\n" $h $m $s
}
%3600/60,$ echo '12345.678' | dc -e '?1~r60~r60~r[[0]P]szn[:]ndZ2>zn[:]ndZ2>zn[[.]n]sad0=ap'
3:25:45.678
%60}' # POSIX awk
date -d @12345 +%T # GNU date
date -r 12345 +%T # OS X's date
If others were searching for how to do the reverse:
如果其他人正在寻找如何做相反的事情:
? 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
[ interpret everything until the closing ] as a string
[0] push the literal string '0' 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
sz pop the top value (the string above) and store it in register z
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
d duplicate the top value on the stack
Z pop the top value from the stack and push the number of digits it has
2 push two
>z pop the top two values and executes register z if the original top-of-stack is greater
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
d duplicate the top value on the stack
Z pop the top value from the stack and push the number of digits it has
2 push two
>z pop the top two values and executes register z if the original top-of-stack is greater
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
回答by Vaulter
All above is for bash, disregarding there "#!/bin/sh" without any bashism will be:
以上所有内容都是针对 bash 的,不考虑“#!/bin/sh”而没有任何 bashism 将是:
: <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
[[0]n] : [0]n, 3, 25, 45, .678
sz : 3, 25, 45, .678 # '[0]n' stored in register z
n : 25, 45, .678 # accumulated stdout: '3'
[:] : :, 25, 45, .678
n : 25, 45, .678 # accumulated stdout: '3:'
d : 25, 25, 45, .678
Z : 2, 25, 45, .678
2 : 2, 2, 25, 45, .678
>z : 25, 45, .678 # not greater, so register z is not executed
n : 45, .678 # accumulated stdout: '3:25'
[:] : :, 45, .678
n : 45, .678 # accumulated stdout: '3:25:'
d : 45, 45, .678
Z : 2, 45, 45, .678
2 : 2, 2, 45, .678
>z : 45, .678 # not greater, so register z is not executed
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'
回答by Scott Colby
Using dc
:
使用dc
:
: 3, 25, 45, 0 # starting just before we begin to print
n : 25, 45, .678 # accumulated stdout: '3'
[:] : :, 25, 45, .678
n : 25, 45, .678 # accumulated stdout: '3:'
d : 25, 25, 45, .678
Z : 2, 25, 45, .678
2 : 2, 2, 25, 45, .678
>z : 25, 45, .678 # not greater, so register z is not executed
n : 45, .678 # accumulated stdout: '3:25'
[:] : :, 45, .678
n : 45, .678 # accumulated stdout: '3:25:'
d : 45, 45, .678
Z : 2, 45, 45, .678
2 : 2, 2, 45, .678
>z : 45, .678 # not greater, so register z is not executed
n : .678 # 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'
The expression ?1~r60~r60~rn[:]nn[:]nn[[.]n]sad0=ap
does the following:
该表达式?1~r60~r60~rn[:]nn[:]nn[[.]n]sad0=ap
执行以下操作:
: 3, 9, 45, 0 # starting just before we begin to print
n : 9, 45, .678 # accumulated stdout: '3'
[:] : :, 9, 45, .678
n : 9, 45, .678 # accumulated stdout: '3:'
d : 9, 9, 45, .678
Z : 1, 9, 45, .678
2 : 2, 1, 9, 45, .678
>z : 9, 45, .678 # greater, so register z is executed
[0] : 0, 9, 45, .678
n : 9, 45, .678 # accumulated stdout: '3:0'
n : 9, .678 # accumulated stdout: '3:09'
# ...and continues as above
An example execution with the stack state after each operation:
每次操作后堆栈状态的示例执行:
convertsecs() {
h=$((/3600))
m=$(((/60)%60))
s=$((%60))
printf "02d:%02d:%02d\n $h $m $s
}
In the case of 0 fractional seconds:
在 0 小数秒的情况下:
##代码##In case of a minutes value less than 10:
如果分钟值小于 10:
##代码##EDIT:this had a bug where strings like 7:7:34.123 could be printed. I have modified it to print a leading zero if necessary.
编辑:这有一个错误,可以打印像 7:7:34.123 这样的字符串。如有必要,我已将其修改为打印前导零。
回答by linuph
I couldn't get Vaulter's/chepner's code to work correctly. I think that the correct code is:
我无法让 Vaulter/chepner 的代码正常工作。我认为正确的代码是:
##代码##