Risposte:
È possibile ottenere il timestamp unix corrente con date "+%s"
, trovare l'attuale quarto d'ora con alcuni semplici calcoli (il mio esempio è in bash
) e stamparlo con un formato migliore con date
:
curdate=`date "+%s"`
curquarter=$(($curdate - ($curdate % (15 * 60))))
date -d"@$curquarter"
La @
sintassi per impostare la data e l'ora correnti da un timestamp è un'estensione GNU fino ad oggi, se non funziona sul tuo sistema operativo, puoi fare lo stesso in questo modo (non dimenticare di specificare UTC, altrimenti, ha vinto ' t funziona):
date -d"1970-01-01 $curquarter seconds UTC"
I seguenti metodi rendono superfluo chiamare date
due volte.
L'overhead di una chiamata di sistema può rendere un comando "semplice" 100 volte più lento di bash facendo la stessa cosa nel proprio ambiente locale.
AGGIORNAMENTO Solo una breve menzione del mio commento sopra: "100 volte più lento". Ora può leggere " 500 volte più lento" ... Di recente sono caduto (no, ho camminato alla cieca) proprio in questo problema. ecco il link: modo rapido per creare un file di prova
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
o
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
Entrambe le versioni restituiranno solo
2011.02.23 01:00
2011.02.23 01:15
2011.02.23 01:30
2011.02.23 01:45
Ecco il primo con un ciclo TEST per tutti i 60 valori {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
o sed
e anche che "inutili" cat
vs <file fa una differenza drammatica in fase di esecuzione. quando eseguo il looping, come nel mio esempio "500 volte più lento" .. Quindi sembra che usare la shell laddove possibile e consentire un programma come date
un processo batch sia ciò che intendo ... ad es. Esempio Gilles 'Left-Pad-0, vs printf
Ecco un modo di lavorare sulle date nella shell. Prima chiamata date
per ottenere i componenti e riempire i parametri posizionali ( $1
,$2
, ecc) con i componenti (nota che questo è uno di questi rari casi in cui si desidera utilizzare $(…)
al di fuori di virgolette, per rompere la stringa in parole). Quindi eseguire aritmetica, test o qualsiasi altra cosa che si debba fare sui componenti. Infine assemblare i componenti.
La parte aritmetica può essere un po 'complicata perché le conchiglie trattano 0
come un prefisso ottale; per esempio qui $(($5/15))
fallirebbe dopo 8 o 9 minuti l'ora. Dal momento che c'è al massimo un leader 0
, ${5#0}
è sicuro per l'aritmetica. L'aggiunta di 100 e la successiva eliminazione di 1
è un modo per ottenere un numero fisso di cifre nell'output.
set $(date "+%Y %m %d %H %M")
m=$((100+15*(${5#0}/15)))
last_quarter_hour="$1.$2.$3 $4:${m#1}"
Forse non ha più importanza, ma potresti provare le mie date personali . L'arrotondamento (verso il basso) ai minuti viene eseguito con dround
un argomento negativo:
dround now /-15m
=>
2012-07-11T13:00:00
O per aderire al tuo formato:
dround now /-15m -f '%Y.%m.%d %H:%M'
=>
2012.07.11 13:00
dateutils.dround '2018-11-12 13:55' -15m
produce . 2018-11-12T13:15:00
2018-11-12T13:45:00
/-15m
cioè arrotondare al multiplo successivo di 15 minuti nell'ora. Questa funzione ha la sintassi più ingombrante perché accetta meno valori, / -13m non è possibile ad esempio perché 13 non è un divisore di 60 (minuti nell'ora)
Alcune shell sono in grado di fare il lavoro senza chiamare un date
comando esterno :
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)))
I tre sopra forniscono l'ora locale (non UTC). Utilizzare una TZ = UTC0 iniziale, se necessario.
La sintassi ksh e bash è quasi identica (ad eccezione di quella richiesta #
in ksh). Zsh richiede di caricare un modulo (incluso con la distribuzione zsh).
È anche possibile farlo con (GNU) awk:
allocco awk 'BEGIN{t=systime();print strftime("%Y.%m.%d %H:%M",t-t%(15*60),1)}'
Questo fornisce un risultato UTC (cambia l'ultimo 1
in 0
) se è necessario locale. Ma caricare un awk esterno o un modulo zsh esterno potrebbe essere lento quanto la stessa data di chiamata:
GNU-date a=$(date +%s); date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Un piccolo eseguibile come busybox
potrebbe fornire risultati simili:
busybox-date a=$(busybox date +%s);busybox date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Si noti che la parola principale busybox può essere omessa se busybox è collegato a quei nomi in una directory del PERCORSO.
Entrambi date
e busybox date
sopra stamperanno i tempi UTC. Rimuovi l' -u
opzione per l'ora locale.
Se il tuo sistema operativo ha una versione più limitata della data (ed è quello che devi usare) allora prova:
a=$(date +%s); a=$(( a-a%(15*60) ))
date -d"1970-01-01 $a seconds UTC" +'%Y.%m.%d %H:%M'
Oppure, se in FreeBSD, prova:
a=$(date +%s); a=$(( a-a%(15*60) ))
date -r "$a" +'%Y.%m.%d %H:%M'
Se riesci a convivere due volte con la data della chiamata, questa funziona in modo basico su Solaris:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))"
Modificato a nome del commento per:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))" | sed 's/:0$/:00/'
Non sono sicuro del tuo esatto requisito. Tuttavia, se si desidera generare il tempo dopo 15 minuti, è possibile utilizzare qualcosa di simile date -d '+15 min'
. L'output è mostrato di seguito:
$ date; date -d '+15 min'
Tue Feb 22 18:12:39 IST 2011
Tue Feb 22 18:27:39 IST 2011