Como verificar se a hora atual é entre 23:00 e 06:30

9

Estou tendo problemas para entender como verificar corretamente em um script bash se o horário atual é entre 23:00 e 06:30. Estou tentando executar um loop infinito para verificar a hora agora e fazer algo se o intervalo de tempo estiver entre 23h e 6h30. Aqui está o que escrevi até agora, que não funciona no dia seguinte:

fireup()
{

 local starttime=$(date --date="23:00" +"%s")
 local endtime=$(date --date="06:30" +"%s")

 while :; do
     local currenttime=$(date +%s)
     if [ "$currenttime" -ge "$starttime" -a "$currenttime" -ge "$endtime" ]; then
        do_something
     else
         do_something_else
     fi
     test "$?" -gt 128 && break
     local currenttime=$(date +%s)
 done &
 }

O que estou fazendo errado?

SinaOwolabi
fonte
"que não funciona no dia seguinte" ... se você usar 23:00 e 06:30 timestamps de ontem e nunca atualizar aqueles ....
Muru

Respostas:

17

Se tudo o que você precisa é verificar se HH:MMestá entre 23:00 e 06:30, não use os carimbos de data e hora do Unix. Basta verificar os HH:MMvalores diretamente:

fireup()
{  
  while :; do
   currenttime=$(date +%H:%M)
   if [[ "$currenttime" > "23:00" ]] || [[ "$currenttime" < "06:30" ]]; then
     do_something
   else
     do_something_else
   fi
   test "$?" -gt 128 && break
  done &
}

Notas:

  • O tempo HH:MMentrará em ordem lexicográfica, para que você possa compará-los diretamente como strings.
  • Evite usar -aou -oem[ ] , uso ||e &&em vez disso.
  • Uma vez que isso é uma festa, prefira [[ ]]mais [ ], facilita a vida.
muru
fonte
Você pode verificar a hora atual em um fuso horário específico? Obrigado!
tommy.carstensen
1
@ tommy.carstensen você pode dateusar um fuso horário específico usando a TZvariável (por exemplo, TZ=Asia/Tokyo dateouTZ=UTC date +%H:%M
muru
Eu daria uma vantagem extra apenas por nomear o método fireup ()
jbrahy
@jbrahy essa foi a idéia do OP (está em questão)
muru
5

Se você quiser ser mais explícito sobre os horários que deseja corresponder, use uma casedeclaração. Aqui está um loop de 24 horas com uma declaração de caso dentro que indica se o horário atual corresponde ao seu intervalo:

for hh in {00..23}
do
  for mm in {00..59}
  do
    case $hh:$mm in
        (23:*)        echo YES $hh:$mm;;
        (0[012345]:*) echo YES $hh:$mm;;
        (06:[012]*)   echo YES $hh:$mm;;
        (*)           echo  NO $hh:$mm;;
    esac
  done
done

Para usá-lo em seu script, basta substituir as variáveis ​​por uma chamada para date:

case $(date +%H:%M) in
    (23:*)        echo YES;;
    (0[012345]:*) echo YES;;
    (06:[012]*)   echo YES;;
    (*)           echo NO;;
esac

Você pode considerar ser mais amigável à sua CPU e calcular a quantidade de tempo entre (agora) e a próxima hora de início e sleeppor essa quantidade de tempo.

Jeff Schaller
fonte
Uau. Esta é uma solução muito inesperada e ótima. Obrigado!
SinaOwolabi 04/04/19
1

Você pode converter o tempo em segundos desde o início deste "dia" e depois verificar se o valor de segundos é maior que 23*60*60(82800) ou menor que 6*60*60+30*60(23400).

Para obter segundos desde o início deste "dia", você pode:

secsSinceMidnight=$(( $(date +%s) - $(date -d '00:00:00' +%s) ))

E o teste seria:

[[ $secsSinceMidnight -lt 23400 || $secsSinceMidnight -gt 82800 ]] && echo YES
Isaac
fonte
0

Eu tenho uma situação parecida. Meu objetivo é ter uma solução que seja muito simples para os geeks não-unix manterem.

Quando meu servidor Linux é reiniciado, ele executa um script que envia um alerta. Mas se isso acontecer como parte da nossa "Janela de manutenção", definida entre 23h de sábado e 6h de domingo, não quero enviar a página, porque uma reinicialização durante esta janela é válida (correções aplicadas etc.). Eu testei e funciona como pretendido (tanto quanto eu posso dizer).

Aqui está o calendário para referência:

      June 2018
Su Mo Tu We Th Fr Sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

Aqui está o meu código de teste:

FMT='+%k:%a' # i.e. Sat:23 for Saturday at 11pm local time

TESTDATE1=$(date -d '2018-06-23 14:30:00' $FMT)
TESTDATE2=$(date -d '2018-06-23 23:59:59' $FMT)
TESTDATE3=$(date -d '2018-06-24 00:00:00' $FMT)
TESTDATE4=$(date -d '2018-06-24 05:59:59' $FMT)
TESTDATE5=$(date -d '2018-06-24 08:01:00' $FMT)

for VAL in "${TESTDATE1}" $TESTDATE2 $TESTDATE3 $TESTDATE4 $TESTDATE5
do

    #extract the 24 hour value and the day
    HH="$(echo ${VAL} | cut -d':' -f1)"
    DAY="$(echo ${VAL} | cut -d':' -f2)"

    echo Testing $VAL  $HH  $DAY

    if [[ "$DAY" = "Sat" && $HH -ge 23 ]]; then
            echo '    Shhhh People are trying to sleep ... Sat window'
    elif [[ "$DAY" = "Sun" && $HH -le 6 ]]; then
            echo '    People are trying to sleep ... Sun window'
    else
            echo '    PAGE SOMEONE - time is outside the Maintenance Window'
    fi

done

Aqui está a saída

Testing 14:Sat 14 Sat
    PAGE SOMEONE - time is outside the Maintenance Window
Testing 23:Sat 23 Sat
    Shhhh People are trying to sleep ... Sat window
Testing 0:Sun 0 Sun
    People are trying to sleep ... Sun window
Testing 5:Sun 5 Sun
    People are trying to sleep ... Sun window
Testing 8:Sun 8 Sun
    PAGE SOMEONE - time is outside the Maintenance Window
Daniel
fonte
1
Como isso parece tentar responder à pergunta, eu a deixei com algumas edições. Se você realmente tem o desejo de ter alguém revisar seu código, eu sugiro codereview.stackexchange.com
Jeff Schaller
Obrigado Jeff, sim, eu estava procurando sugestões. Eu não conhecia o site de revisão de códigos. Graças
Daniel
0

Nesse caso específico, uma alternativa para simplificar o teste é adicionar uma hora e testar uma vez por menos de 07:30

if [[ $(date -d "now + 60 minutes" +'%H:%M') < "07:30" ]]
    then echo "wake up"
else
    echo "Zzzzzz"
fi
bu5hman
fonte
-2

Dica: a resposta de muru acima funcionou para mim, mas em vez de || (pipes "ou"), tive que usar o && ("and" operator).

assim: se [["$ currenttime"> "23:00"]] && [["$ currenttime" <"06:30"]]

ChaLinux
fonte
2
Isso não faz nenhum sentido. O valor possível de CurrentTime é tanto maior que “23:00” e também menos do que “6:30”? Dica: não há nenhum.
8759 Scott