Чи можна легко відформатувати секунди, як люди, що читають час у баші?
Я не хочу форматувати це як дату, а як кількість днів / годин / хвилин тощо ...
Чи можна легко відформатувати секунди, як люди, що читають час у баші?
Я не хочу форматувати це як дату, а як кількість днів / годин / хвилин тощо ...
Відповіді:
Ви можете використовувати щось подібне:
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 11617
3 hours 13 minutes and 37 seconds
$ displaytime 42
42 seconds
$ displaytime 666
11 minutes and 6 seconds
Найпростіший і найпростіший спосіб - це один лайнер (тут припускаємо GNU date
):
Якщо кількість секунд дорівнює, скажіть:
seconds=123456789 # as in one of the answers above
eval "echo $(date -ud "@$seconds" +'$((%s/3600/24)) days %H hours %M minutes %S seconds')"
-> вихід: 1428 days 21 hours 33 minutes 09 seconds
+%T
формат годинник: хвилини: секунди для цього , date +%T "1970-01-01 + ${seconds} seconds"
щоб отримати21:33:09
Кредит належить Стефану Гіменезу, але якщо хтось хотів би відобразити секунди, лише якщо період менший за хвилину, ось моя модифікована версія, яку я використовую (також із фіксованою плюралізацією):
converts()
{
local t=$1
local d=$((t/60/60/24))
local h=$((t/60/60%24))
local m=$((t/60%60))
local s=$((t%60))
if [[ $d > 0 ]]; then
[[ $d = 1 ]] && echo -n "$d day " || echo -n "$d days "
fi
if [[ $h > 0 ]]; then
[[ $h = 1 ]] && echo -n "$h hour " || echo -n "$h hours "
fi
if [[ $m > 0 ]]; then
[[ $m = 1 ]] && echo -n "$m minute " || echo -n "$m minutes "
fi
if [[ $d = 0 && $h = 0 && $m = 0 ]]; then
[[ $s = 1 ]] && echo -n "$s second" || echo -n "$s seconds"
fi
echo
}
Альтернативний приклад в POSIX:
converts(){
t=$1
d=$((t/60/60/24))
h=$((t/60/60%24))
m=$((t/60%60))
s=$((t%60))
if [ $d -gt 0 ]; then
[ $d = 1 ] && printf "%d day " $d || printf "%d days " $d
fi
if [ $h -gt 0 ]; then
[ $h = 1 ] && printf "%d hour " $h || printf "%d hours " $h
fi
if [ $m -gt 0 ]; then
[ $m = 1 ] && printf "%d minute " $m || printf "%d minutes " $m
fi
if [ $d = 0 ] && [ $h = 0 ] && [ $m = 0 ]; then
[ $s = 1 ] && printf "%d second" $s || printf "%d seconds" $s
fi
printf '\n'
}
convert $s
щоб отримати гарний результат.
Я б це зробив так:
$ seconds=123456789; echo $((seconds/86400))" days "$(date -d "1970-01-01 + $seconds seconds" "+%H hours %M minutes %S seconds")
1428 days 21 hours 33 minutes 09 seconds
$
Ось один вкладиш, розбитий вище, щоб його було легше зрозуміти:
$ seconds=123456789
$ echo $((seconds/86400))" days"\
$(date -d "1970-01-01 + $seconds seconds" "+%H hours %M minutes %S seconds")
У вищесказаному я повторюю вихід іншої команди, яка виконується всередині $( ... )
підкоманди. Ця підкоманда робить це, обчислюючи кількість днів (секунд / 86400), потім використовуючи date
команду в іншій підкоманді $(date -d ... )
, щоб генерувати години, хвилини та секунди за задану кількість секунд.
Я змінив функцію відображення вище ... таким чином:
seconds2time ()
{
T=$1
D=$((T/60/60/24))
H=$((T/60/60%24))
M=$((T/60%60))
S=$((T%60))
if [[ ${D} != 0 ]]
then
printf '%d days %02d:%02d:%02d' $D $H $M $S
else
printf '%02d:%02d:%02d' $H $M $S
fi
}
тому що я завжди хочу бачити HH: MM: SS, навіть якщо вони нулі.
Я будую на відповіді atti, яка мені сподобалась як ідея.
Ви можете зробити це за допомогою вбудованого bash, printf
який займе секунди з епохи як аргумент. Не потрібно роздрібнюватися для запуску date
.
Вам потрібно встановити часовий пояс на UTC, printf
оскільки він формулює час у вашому локальному часовому поясі, і ви отримаєте неправильну відповідь, якщо ви не в часі UTC.
$ seconds=123456789
$ TZ=UTC printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1428 days 21 hours 33 minutes 09 seconds
У мій місцевий час (який зараз є NZDT - +1300) відповідь неправильна, якщо я не встановлю часовий пояс
$ seconds=123456789
$ printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1428 days 09 hours 33 minutes 09 seconds
З і без встановлення часового поясу
$ seconds=$(( 3600 * 25))
$ printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1 days 13 hours 00 minutes 00 seconds
$ TZ=UTC printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1 days 01 hours 00 minutes 00 seconds
printf
ввів це %(datefmt)T
позначення, починаючи з bash-4.2-alpha.
Ось один
secs=378444
echo $(($secs/86400))d $(($(($secs - $secs/86400*86400))/3600))h:$(($(($secs - $secs/86400*86400))%3600/60))m:$(($(($secs - $secs/86400*86400))%60))s
Вихід:
4d 9h:7m:24s
date --date '@1005454800'
дає вам Sun Nov 11 00:00:00 EST 2001
, що становить 1005454800 секунд після епохи Unix. Ви можете відформатувати його за допомогою дати + FORMAT.