Відповіді:
Ви можете отримати поточну мітку часу Unix date "+%s"
, знайти поточну чверть години за допомогою простої математики (мій приклад є в bash
) та роздрукувати її в кращому форматі за допомогою date
:
curdate=`date "+%s"`
curquarter=$(($curdate - ($curdate % (15 * 60))))
date -d"@$curquarter"
@
Синтаксис для установки поточної дати і часу з позначки часу є GNU продовженням на сьогоднішній день, якщо вона не працює на вашій операційній системі, ви можете зробити те ж саме , як це (не забудьте вказати UTC, в іншому випадку, він виграв » t робота):
date -d"1970-01-01 $curquarter seconds UTC"
Наведені нижче методи роблять зайвим дзвонити date
двічі.
Накладні виклики системного виклику можуть зробити "просту" команду в 100 разів повільніше, ніж баш, що робить те ж саме у власному локальному середовищі.
ОНОВЛЕННЯ Лише коротка згадка про мій вище коментар: "У 100 разів повільніше". Зараз він може читати " 500 разів повільніше" ... Я нещодавно потрапив (ні, пішов наосліп) у цю саму проблему. ось посилання: Швидкий спосіб створення тестового файлу
eval $(date +Y=%Y\;m=%m\;d=%d\;H=%H\;M=%M)
[[ "$M" < "15" ]] && M=00 # cater for octal clash
M=$(((M/15)*15))
((M==0)) && M=00 # the math returns 0, so make it 00
echo $Y.$m.$d $H:$M
або
eval $(date +Y=%Y\;m=%m\;d=%d\;H=%H\;M=%M)
if [[ "$M" < "15" ]] ; then M=00
elif [[ "$M" < "30" ]] ; then M=15
elif [[ "$M" < "45" ]] ; then M=30
else M=45
fi
echo $Y.$m.$d $H:$M
Обидві версії повернуться лише
2011.02.23 01:00
2011.02.23 01:15
2011.02.23 01:30
2011.02.23 01:45
Ось перший з циклом TEST для всіх 60 значень {00..59}
for X in {00..59} ; ###### TEST
do ###### TEST
eval $(date +Y=%Y\;m=%m\;d=%d\;H=%H\;M=%M)
M=$X ###### TEST
[[ "$M" < "15" ]] && M=00 # cater for octal clash
M=$(((M/15)*15))
((M==0)) && M=00 # the math returns 0, so make it 00
echo $Y.$m.$d $H:$M
done ###### TEST
printf
або, sed
а також те, що "непотрібний" cat
vs <файл, робить суттєву різницю в процесі виконання. при циклічному циклі, як у моєму прикладі "в 500 разів повільніше". Отже, здається, що використання оболонки, де це можливо, і дозволити програмі, такі як date
пакетний процес - це те, що я маю на увазі .. наприклад. Приклад Gilles 'Left-Pad-0, vs printf
Ось спосіб роботи над датами в оболонці. Спочатку зателефонуйте, date
щоб отримати компоненти, і заповніть позиційні параметри ( $1
, $2
тощо) компонентами (зауважте, що це один з таких рідкісних випадків, коли ви хочете використовувати $(…)
поза подвійними лапки, щоб розбити рядок на слова). Потім виконайте арифметику, тести або все, що вам потрібно зробити на компонентах. Нарешті зібрати компоненти.
Арифметична частина може бути трохи хитрою, оскільки оболонки трактуються 0
як восьмеричний префікс; наприклад, тут $(($5/15))
не вдасться о 8 або 9 хвилин минулої години. Оскільки є щонайбільше один провідний 0
, ${5#0}
безпечний для арифметики. Додавання 100 та згодом відсікання 1
- це спосіб отримати фіксовану кількість цифр у висновку.
set $(date "+%Y %m %d %H %M")
m=$((100+15*(${5#0}/15)))
last_quarter_hour="$1.$2.$3 $4:${m#1}"
Можливо, це вже не має значення, але ви можете спробувати мої власні датування . Округлення (вниз) до хвилин робиться за допомогою dround
і негативним аргументом:
dround now /-15m
=>
2012-07-11T13:00:00
Або дотримуватися вашого формату:
dround now /-15m -f '%Y.%m.%d %H:%M'
=>
2012.07.11 13:00
dateutils.dround '2018-11-12 13:55' -15m
виробляє 2018-11-12T13:15:00
не 2018-11-12T13:45:00
.
/-15m
тобто, округлюйте до наступного кратного 15 хвилин у годині. Ця функція отримала більш громіздкий синтаксис, оскільки вона приймає менші значення, / -13m не можлива, наприклад, тому що 13 - це не дільник 60 (хвилин у годині)
Деякі оболонки здатні виконати роботу без виклику зовнішньої date
команди:
ksh
a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "#$((a-a%(15*60)))"
bash a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "$((a-a%(15*60)))"
zsh zmodload zsh/datetime; a=$EPOCHSECONDS; strftime '%Y-%m-%d %H:%M' $((a-a%(15*60)))
Три вище наведені місцеві (не UTC) часу. Використовуйте провідний TZ = UTC0, якщо потрібно.
Синтаксис ksh і bash майже ідентичний (крім необхідного #
в ksh). Zsh потрібно завантажити модуль (включений до розподілу zsh).
Це також можна зробити за допомогою (GNU) awk:
гаук awk 'BEGIN{t=systime();print strftime("%Y.%m.%d %H:%M",t-t%(15*60),1)}'
Це дає результат UTC (змінити останній 1
на 0
), якщо потрібен локальний. Але завантаження зовнішнього awk або зовнішнього модуля zsh може бути настільки ж повільним, як і сама дата виклику:
гну-побачення a=$(date +%s); date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Невеликий виконуваний файл busybox
може надати схожі результати:
зайнятий-дата a=$(busybox date +%s);busybox date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Зауважте, що ведуче слово зайнятої скриньки може бути опущено, якщо зайнятий ящик пов'язаний з тими іменами в каталозі PATH.
І вище, date
і busybox date
вище буде надруковано UTC-раз. Видаліть -u
опцію для місцевих часів.
Якщо ваша ОС має більш обмежену версію дати (і це те, що вам потрібно використовувати), спробуйте:
a=$(date +%s); a=$(( a-a%(15*60) ))
date -d"1970-01-01 $a seconds UTC" +'%Y.%m.%d %H:%M'
Або, якщо у FreeBSD, спробуйте:
a=$(date +%s); a=$(( a-a%(15*60) ))
date -r "$a" +'%Y.%m.%d %H:%M'
Якщо ви можете жити з датою виклику два рази, ця працює в баш на Solaris:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))"
Відредаговано від імені коментаря до:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))" | sed 's/:0$/:00/'
Я не впевнений у вашій точній вимозі. Однак якщо ви хочете генерувати час через 15 хв, тоді ви можете використовувати щось на кшталт date -d '+15 min'
. Результат показаний нижче:
$ date; date -d '+15 min'
Tue Feb 22 18:12:39 IST 2011
Tue Feb 22 18:27:39 IST 2011