Следующие методы делают ненужным вызывать date
дважды.
Затраты на системный вызов могут сделать «простую» команду в 100 раз медленнее, чем bash, которая делает то же самое в своей локальной среде.
ОБНОВЛЕНИЕ Просто краткое упоминание моего комментария: «в 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 пример, против printfВот способ работы с датами в оболочке. Сначала вызовите,
date
чтобы получить компоненты, и заполните позиционные параметры ($1
и$2
т. Д.) Компонентами (обратите внимание, что это один из тех редких случаев, когда вы хотите использовать$(…)
за пределами двойных кавычек, чтобы разбить строку на слова). Затем выполните арифметику, тесты или все, что вам нужно сделать с компонентами. Наконец собрать компоненты.Арифметическая часть может быть немного хитрой, потому что оболочки воспринимаются
0
как восьмеричный префикс; например, здесь$(($5/15))
произойдет сбой в 8 или 9 минут после часа. Поскольку существует не более одного ведущего0
,${5#0}
безопасно для арифметики. Добавление 100 и последующее удаление1
- это способ получить фиксированное количество цифр в выводе.источник
Может быть, это уже не имеет значения, но вы можете попробовать мои собственные dateutils . Округление (вниз) до минут выполняется с
dround
отрицательным аргументом:Или придерживаться вашего формата:
источник
dateutils.dround '2018-11-12 13:55' -15m
производит .2018-11-12T13:15:00
2018-11-12T13:45:00
/-15m
т.е. округлите до следующего кратного 15 минутам в час. Эта функция получила более громоздкий синтаксис, потому что она принимает меньше значений, / -13m, например, невозможно, потому что 13 не является делителем 60 (минут в час)dateutils.dround '2018-11-12 12:52:31' /450s /-15m
, спасибо!Некоторые оболочки могут выполнять эту работу без вызова внешней
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
), если требуется local. Но загрузка внешнего awk или внешнего zsh-модуля может быть такой же медленной, как и сама дата вызова:гну-дата
a=$(date +%s); date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Маленький исполняемый файл like
busybox
может дать аналогичные результаты:BusyBox-дата
a=$(busybox date +%s);busybox date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Обратите внимание, что начальное слово busybox может быть опущено, если busybox связан с этими именами в каталоге PATH.
Оба
date
иbusybox date
выше будет печатать время UTC. Удалить-u
опцию для местного времени.Если ваша ОС имеет более ограниченную версию даты (и это то, что вы должны использовать), попробуйте:
Или, если во FreeBSD, попробуйте:
источник
Если вы можете прожить с датой звонка два раза, это работает в bash на Solaris:
Отредактировано от имени комментария:
источник
Не уверен насчет вашего точного требования. Однако если вы хотите сгенерировать время через 15 минут, то вы можете использовать что-то вроде
date -d '+15 min'
. Вывод показан ниже:источник