Réponses:
Vous pouvez obtenir l'horodatage Unix actuel avec date "+%s"
, trouver le quart d'heure actuel avec des calculs simples (mon exemple est bash
dedans) et l'imprimer avec un meilleur format avec date
:
curdate=`date "+%s"`
curquarter=$(($curdate - ($curdate % (15 * 60))))
date -d"@$curquarter"
La @
syntaxe pour définir la date et l'heure actuelles à partir d'un horodatage est une extension GNU à ce jour, si cela ne fonctionne pas sur votre système d'exploitation, vous pouvez faire la même chose comme ceci (n'oubliez pas de spécifier UTC, sinon, il gagnera ' t travail):
date -d"1970-01-01 $curquarter seconds UTC"
Les méthodes suivantes rendent inutile d'appeler date
deux fois.
La surcharge d'un appel système peut rendre une commande "simple" 100 fois plus lente que bash faire la même chose dans son propre environnement local.
MISE À JOUR Juste une brève mention de mon commentaire ci-dessus: "100 fois plus lent". Il peut maintenant lire " 500 fois plus lentement" ... Je suis récemment tombé (non, j'ai marché aveuglément) sur ce problème. voici le lien: Un moyen rapide de construire un fichier de test
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
Les deux versions ne reviendront que
2011.02.23 01:00
2011.02.23 01:15
2011.02.23 01:30
2011.02.23 01:45
Voici la première avec une boucle TEST pour les 60 valeurs {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
ou sed
et aussi que "inutile" cat
vs <fichier fait une différence réelle d'exécution réelle. lors de la boucle, comme dans mon exemple "500 fois plus lent" .. Il semble donc que l'utilisation du shell autant que possible, et permettre un programme tel que date
le traitement par lots est ce que je veux dire .. par exemple. Exemple de Gilles-Pad-0 gauche, vs printf
Voici un moyen de travailler sur les dates dans le shell. Le premier appel date
pour obtenir les composants et remplir les paramètres de position ( $1
, $2
, etc.) avec les composants (notez que c'est l' un de ces rares cas où vous ne souhaitez utiliser en $(…)
dehors des guillemets doubles, pour briser la chaîne en mots). Effectuez ensuite des calculs, des tests ou tout ce que vous devez faire sur les composants. Assemblez enfin les composants.
La partie arithmétique peut être un peu délicate car les coques sont traitées 0
comme un préfixe octal; par exemple ici $(($5/15))
échouerait à 8 ou 9 minutes après l'heure. Puisqu'il y a au plus un leader 0
, ${5#0}
est sûr pour l'arithmétique. L'ajout de 100 et la suppression ultérieure du 1
est un moyen d'obtenir un nombre fixe de chiffres dans la sortie.
set $(date "+%Y %m %d %H %M")
m=$((100+15*(${5#0}/15)))
last_quarter_hour="$1.$2.$3 $4:${m#1}"
Peut-être que cela n'a plus d'importance, mais vous pouvez essayer mes propres dateutils . L'arrondi (vers le bas) en minutes est effectué avec dround
un argument négatif:
dround now /-15m
=>
2012-07-11T13:00:00
Ou pour adhérer à votre format:
dround now /-15m -f '%Y.%m.%d %H:%M'
=>
2012.07.11 13:00
dateutils.dround '2018-11-12 13:55' -15m
produit 2018-11-12T13:15:00
pas 2018-11-12T13:45:00
.
/-15m
, c'est-à-dire arrondir au multiple de 15 minutes suivant l'heure. Cette fonction a la syntaxe plus lourde , car il accepte moins de valeurs, / -13m n'est pas possible , par exemple , parce que 13 n'est pas un diviseur de 60 minutes (à l'heure)
Certains shells sont capables de faire le travail sans appeler une date
commande externe :
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)))
Les trois ci-dessus fournissent l'heure locale (pas UTC). Utilisez un TZ = UTC0 de tête si nécessaire.
La syntaxe ksh et bash est presque identique (sauf pour le nécessaire #
dans ksh). Les zsh nécessitent de charger un module (inclus avec la distribution zsh).
Il est également possible de le faire avec (GNU) awk:
rester bouche bée awk 'BEGIN{t=systime();print strftime("%Y.%m.%d %H:%M",t-t%(15*60),1)}'
Cela fournit un résultat UTC (remplacez le dernier 1
par 0
) si local est nécessaire. Mais le chargement d'un awk externe ou d'un module zsh externe peut être aussi lent que l'appel de date lui-même:
gnu-date a=$(date +%s); date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Un petit exécutable comme busybox
pourrait fournir des résultats similaires:
busybox-date a=$(busybox date +%s);busybox date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Notez que le premier mot de la boîte occupée peut être omis si la boîte occupée est liée à ces noms dans un répertoire du CHEMIN.
Les deux date
et busybox date
au - dessus imprimeront les heures UTC. Supprimez l' -u
option pour les heures locales.
Si votre système d'exploitation a une version de date plus limitée (et c'est ce que vous devez utiliser), essayez:
a=$(date +%s); a=$(( a-a%(15*60) ))
date -d"1970-01-01 $a seconds UTC" +'%Y.%m.%d %H:%M'
Ou, si dans FreeBSD, essayez:
a=$(date +%s); a=$(( a-a%(15*60) ))
date -r "$a" +'%Y.%m.%d %H:%M'
Si vous pouvez vivre avec la date d'appel deux fois, celle-ci fonctionne en bash sur Solaris:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))"
Modifié au nom du commentaire pour:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))" | sed 's/:0$/:00/'
Je ne suis pas sûr de vos besoins exacts. Cependant, si vous souhaitez générer le temps après 15 min, vous pouvez utiliser quelque chose comme date -d '+15 min'
. La sortie est illustrée ci-dessous:
$ date; date -d '+15 min'
Tue Feb 22 18:12:39 IST 2011
Tue Feb 22 18:27:39 IST 2011