Odpowiedzi:
Możesz pobrać bieżący znacznik czasu unix date "+%s"
, znaleźć bieżący kwadrans za pomocą prostej matematyki (mój przykład jest w bash
) i wydrukować go w lepszym formacie za pomocą date
:
curdate=`date "+%s"`
curquarter=$(($curdate - ($curdate % (15 * 60))))
date -d"@$curquarter"
@
Składnia aby ustawić aktualną datę i godzinę z datownika jest rozbudowa GNU do tej pory, jeśli nie działa na OS, można zrobić to samo jak ten (nie zapomnij podać UTC, w przeciwnym razie, to won” t pracy):
date -d"1970-01-01 $curquarter seconds UTC"
Poniższe metody sprawiają, że nie trzeba dzwonić date
dwukrotnie.
Narzut wywołania systemowego może wykonać „proste” polecenie 100 razy wolniej niż bash, robiąc to samo w swoim lokalnym środowisku.
AKTUALIZACJA Krótka wzmianka o moim powyższym komentarzu: „100 razy wolniej”. Teraz można odczytać „ 500 razy wolniej” ... Niedawno wpadłem (nie, szedłem na oślep) do tego właśnie problemu. tutaj jest link: Szybki sposób na zbudowanie pliku testowego
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
lub
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
Obie wersje zostaną zwrócone tylko
2011.02.23 01:00
2011.02.23 01:15
2011.02.23 01:30
2011.02.23 01:45
Oto pierwszy z pętlą TEST dla wszystkich 60 wartości {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
lub sed
, a także, że „niepotrzebne” cat
vs <plik robi dramatyczną rzeczywistą różnicę czasu wykonywania. podczas zapętlania, jak w moim przykładzie „500 razy wolniejszym”. Wydaje się, że używanie powłoki tam, gdzie to możliwe, i pozwalanie programowi takiemu jak date
proces wsadowy, mam na myśli… np. Przykład Gillesa Left-Pad-0, a printf
Oto sposób pracy nad datami w powłoce. Najpierw wywołaj, date
aby pobrać komponenty i wypełnić parametry pozycji ( $1
, $2
itp.) Komponentami (zauważ, że jest to jeden z tych rzadkich przypadków, w których chcesz użyć $(…)
poza podwójnymi cudzysłowami, aby rozbić ciąg na słowa). Następnie wykonaj arytmetykę, testy lub cokolwiek innego, co musisz zrobić na komponentach. Na koniec zmontuj elementy.
Część arytmetyczna może być nieco trudna, ponieważ powłoki traktują 0
jak ośmiokrotny przedrostek; na przykład tutaj $(($5/15))
nie powiedzie się o 8 lub 9 minut po godzinie. Ponieważ jest co najwyżej jeden wiodący 0
, ${5#0}
jest bezpieczny dla arytmetyki. Dodanie 100, a następnie usunięcie, 1
jest sposobem na uzyskanie stałej liczby cyfr na wyjściu.
set $(date "+%Y %m %d %H %M")
m=$((100+15*(${5#0}/15)))
last_quarter_hour="$1.$2.$3 $4:${m#1}"
Może to już nie ma znaczenia, ale możesz wypróbować moje własne dateutils . Zaokrąglanie (w dół) do minut odbywa się za dround
pomocą argumentu ujemnego:
dround now /-15m
=>
2012-07-11T13:00:00
Lub zastosować się do swojego formatu:
dround now /-15m -f '%Y.%m.%d %H:%M'
=>
2012.07.11 13:00
dateutils.dround '2018-11-12 13:55' -15m
produkuje . 2018-11-12T13:15:00
2018-11-12T13:45:00
/-15m
tj. Zaokrąglić w dół do następnej wielokrotności 15 minut w ciągu godziny. Ta funkcja ma bardziej nieporęczną składnię, ponieważ akceptuje mniej wartości, / -13 m nie jest możliwe, na przykład ponieważ 13 nie jest dzielnikiem 60 (minut na godzinę)
Niektóre powłoki są w stanie wykonać pracę bez wywoływania zewnętrznego date
polecenia:
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)))
Trzy powyższe zapewniają czas lokalny (nie UTC). W razie potrzeby użyj wiodącego TZ = UTC0.
Składnia ksh i bash jest prawie identyczna (z wyjątkiem wymaganej #
w ksh). Zsh wymaga załadowania modułu (zawartego w dystrybucji zsh).
Można to również zrobić za pomocą awk (GNU):
gapić się awk 'BEGIN{t=systime();print strftime("%Y.%m.%d %H:%M",t-t%(15*60),1)}'
Zapewnia to wynik UTC (zmień ostatni 1
na 0
), jeśli lokalny jest potrzebny. Ale ładowanie zewnętrznego awk lub zewnętrznego modułu zsh może być tak wolne jak sama data wywołania:
data gnu a=$(date +%s); date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Mały plik wykonywalny, taki jak, busybox
może zapewnić podobne wyniki:
busy-date a=$(busybox date +%s);busybox date -ud "@$((a-a%(15*60)))" +'%Y.%m.%d %H:%M'
Zauważ, że wiodące słowo busybox może zostać pominięte, jeśli busybox jest powiązany z tymi nazwami w katalogu ŚCIEŻKI.
Zarówno wyżej, jak date
i busybox date
wyżej będą drukować czasy UTC. Usuń -u
opcję czasu lokalnego.
Jeśli twój system operacyjny ma bardziej ograniczoną wersję daty (i właśnie tego musisz użyć), spróbuj:
a=$(date +%s); a=$(( a-a%(15*60) ))
date -d"1970-01-01 $a seconds UTC" +'%Y.%m.%d %H:%M'
Lub, jeśli we FreeBSD, spróbuj:
a=$(date +%s); a=$(( a-a%(15*60) ))
date -r "$a" +'%Y.%m.%d %H:%M'
Jeśli możesz dwa razy żyć z datą dzwonienia, ta działa bash na Solarisie:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))"
Edytowane w imieniu komentarza do:
date +"%Y.%m.%d %H:$(( $(date +'%M') / 15 * 15 ))" | sed 's/:0$/:00/'
Nie jestem pewien dokładnych wymagań. Jeśli jednak chcesz wygenerować czas po 15 minutach, możesz użyć czegoś takiego date -d '+15 min'
. Dane wyjściowe pokazano poniżej:
$ date; date -d '+15 min'
Tue Feb 22 18:12:39 IST 2011
Tue Feb 22 18:27:39 IST 2011