дата: отримати поточний 15-хвилинний інтервал


15

Чи я можу отримати поточний 15-хвилинний інтервал за допомогою команди date або подібного?

наприклад , що - щось на зразок дня %Y.%m.%d %H:%M дасть мені 2011.02.22 10:19, мені потрібно що - то , що дає 2011.02.22 10:15в проміжку часу від 10:15до 10:29.

Відповіді:


17

Ви можете отримати поточну мітку часу 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"

5

Наведені нижче методи роблять зайвим дзвонити 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 

1
Тільки для уточнення - під "системним дзвінком" ви маєте на увазі "fork / exec / wait, як і системний () call", а не системний виклик взагалі. (Я згадую про це, тому що здійснення системних дзвінків також має накладні витрати в межах програми через комутатора користувача / ядра. Тут це не особлива проблема.)
mattdm

mattdm ... Дякую .. Я працюю лише з 6-ти місячним досвідом Linux, тому я, швидше за все, використав неправильну фразу, але я постійно читаю про накладні витрати, викликані непотрібними дзвінками, і на власному досвіді тестую свій власний Сценарії, я бачив багато прикладів, коли виклик printfабо, sedа також те, що "непотрібний" catvs <файл, робить суттєву різницю в процесі виконання. при циклічному циклі, як у моєму прикладі "в 500 разів повільніше". Отже, здається, що використання оболонки, де це можливо, і дозволити програмі, такі як dateпакетний процес - це те, що я маю на увазі .. наприклад. Приклад Gilles 'Left-Pad-0, vs printf
Peter.O

3

Ось спосіб роботи над датами в оболонці. Спочатку зателефонуйте, 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}"

"Витівки торгівлі" ... хороший. :)
Пітер.О

2

Можливо, це вже не має значення, але ви можете спробувати мої власні датування . Округлення (вниз) до хвилин робиться за допомогою droundі негативним аргументом:

dround now /-15m
=>
  2012-07-11T13:00:00

Або дотримуватися вашого формату:

dround now /-15m -f '%Y.%m.%d %H:%M'
=>
  2012.07.11 13:00

це насправді, як працюють утиліти? використовуючи -15m, я отримую перемотування входу до найближчих 15 хвилин минулої години: dateutils.dround '2018-11-12 13:55' -15mвиробляє 2018-11-12T13:15:00не 2018-11-12T13:45:00.

1
@JackDouglas Інструменти еволюціонували, те, що ви хочете зараз: /-15mтобто, округлюйте до наступного кратного 15 хвилин у годині. Ця функція отримала більш громіздкий синтаксис, оскільки вона приймає менші значення, / -13m не можлива, наприклад, тому що 13 - це не дільник 60 (хвилин у годині)
hroptatyr

приємно, я отримую те, що мені зараз потрібно dateutils.dround '2018-11-12 12:52:31' /450s /-15m, дякую!

2

Деякі оболонки здатні виконати роботу без виклику зовнішньої dateкоманди:

a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "#$((a-a%(15*60)))"
a=$(printf '%(%s)T\n'); printf '%(%Y.%m.%d %H:%M)T\n' "$((a-a%(15*60)))"
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'

1

Якщо ви можете жити з датою виклику два рази, ця працює в баш на Solaris:

date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))"

Відредаговано від імені коментаря до:

date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))" | sed 's/:0$/:00/'

1
У першому чверті години це призведе до виведення хвилин лише з одним 0 замість 00
Пітер.O

Виправлено, це простий sed після оригінальної команди.
ddeimeke

Ще одна помилка: вона не працює між H: 08 та H: 10. Дивіться мою відповідь, чому і виправлення.
Жил "ТАК - перестань бути злим"

-1

Я не впевнений у вашій точній вимозі. Однак якщо ви хочете генерувати час через 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

1
Ви неправильно зрозуміли питання. Сенс полягає в округлянні дати (вниз) до кратного 15 хвилин.
Жил 'ТАК - перестань бути злим'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.