date: obtenha o intervalo atual de 15 minutos

15

Existe alguma maneira de obter o intervalo atual de 15 minutos usando o comando date ou similar?

por exemplo. algo como data %Y.%m.%d %H:%M me dará 2011.02.22 10:19 , preciso de algo que rende 2011.02.22 10:15 no intervalo de tempo de 10:15 a 10:29 .

    
por nos 22.02.2011 / 13:14

7 respostas

15

Você pode obter o timestamp unix atual com date "+%s" , encontrar o quarto-hora atual com alguma matemática simples (meu exemplo está em bash ) e imprimi-lo com um formato melhor com date :

curdate='date "+%s"'
curquarter=$(($curdate - ($curdate % (15 * 60))))
date -d"@$curquarter"

A sintaxe @ para definir a data e hora atuais de um registro de data e hora é uma extensão GNU até o momento, se não funcionar no seu sistema operacional, você pode fazer o mesmo assim (não se esqueça de especificar o UTC caso contrário, não funcionará):

date -d"1970-01-01 $curquarter seconds UTC"
    
por 22.02.2011 / 13:28
5

Os métodos a seguir tornam desnecessário chamar date duas vezes.
A sobrecarga de uma chamada do sistema pode tornar um comando "simples" 100 vezes mais lento que o bash fazendo a mesma coisa em seu próprio ambiente local.

UPDATE Apenas uma menção rápida sobre o meu comentário acima: "100 vezes mais lento". Agora ele pode ler " 500 vezes mais devagar" ... Recentemente eu caí (não, andei cegamente) nessa questão. aqui está o link: Forma rápida de construir um arquivo de teste

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  

ou

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

Ambas as versões retornarão apenas

2011.02.23 01:00
2011.02.23 01:15
2011.02.23 01:30
2011.02.23 01:45   

Aqui está o primeiro com um loop de teste para todos os 60 valores {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 
    
por 22.02.2011 / 15:13
3

Aqui está uma maneira de trabalhar em datas no shell. Primeiro, chame date para obter os componentes e preencha os parâmetros posicionais ( $1 , $2 , etc) com os componentes (observe que esse é um desses casos raros em que você deseja usar $(…) fora de aspas duplas, para quebrar a string em palavras). Em seguida, execute aritmética, testes ou o que você precisa fazer nos componentes. Finalmente monte os componentes.

A parte aritmética pode ser um pouco complicada porque os shells tratam 0 como um prefixo octal; por exemplo, aqui $(($5/15)) falharia às 8 ou 9 minutos após a hora. Como há no máximo um 0 , ${5#0} é seguro para a aritmética. Adicionar 100 e, posteriormente, retirar o 1 é uma maneira de obter um número fixo de dígitos na saída.

set $(date "+%Y %m %d %H %M")
m=$((100+15*(${5#0}/15)))
last_quarter_hour="$1.$2.$3 $4:${m#1}"
    
por 22.02.2011 / 20:44
3

Talvez isso não importe mais, mas você pode experimentar os meus próprios dateutils . O arredondamento (para baixo) para minutos é feito com dround e um argumento negativo:

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

Ou para aderir ao seu formato:

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

Se você pode viver com a data de chamada duas vezes, esta trabalha no bash no Solaris:

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

Editado em nome do comentário para:

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

Alguns shells conseguem fazer o trabalho sem chamar um comando date externo:

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)))

Os três acima fornecem tempo local (não UTC). Use um TZ principal = UTC0, se necessário.

A sintaxe do ksh e do bash é quase idêntica (exceto para o # requerido no ksh). O zsh requer para carregar um módulo (incluído na distribuição zsh).

Também é possível fazer isso com o (GNU) awk:

awk 'BEGIN{t=systime();print strftime("%Y.%m.%d %H:%M",t-t%(15*60),1)}'

Isso fornece um resultado UTC (altere a última 1 para 0 ) se local for necessário. Mas carregar um awk externo ou um módulo zsh externo pode ser tão lento quanto a própria data de chamada:

a=$(date +%s); date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'

Um pequeno executável como busybox poderia fornecer resultados semelhantes:

a=$(busybox date +%s);busybox date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'

Observe que a palavra busybox principal pode ser omitida se o busybox estiver vinculado a esses nomes em um diretório do PATH.

Tanto date como busybox date acima imprimem as horas UTC. Remova a opção -u para os horários locais.

Se o seu sistema operacional tiver uma versão de data mais limitada (e é isso que você deve usar), tente:

a=$(date +%s); a=$(( a-a%(15*60) ))
date -d"1970-01-01 $a seconds UTC" +'%Y.%m.%d %H:%M'

Ou, se estiver no FreeBSD, tente:

a=$(date +%s); a=$(( a-a%(15*60) ))
date -r "$a" +'%Y.%m.%d %H:%M'
    
por 13.11.2018 / 17:40
-1

Não tenho certeza sobre sua exigência exata. No entanto, se você quiser gerar o tempo após 15 min, poderá usar algo como date -d '+15 min' . A saída é mostrada abaixo:

$ date; date  -d '+15 min'
Tue Feb 22 18:12:39 IST 2011
Tue Feb 22 18:27:39 IST 2011
    
por 22.02.2011 / 13:34