Как проверить, является ли текущее время между 23:00 и 06:30


9

У меня возникают проблемы с пониманием того, как правильно проверить из сценария bash текущее время между 23:00 и 06:30. Я пытаюсь запустить бесконечный цикл, чтобы проверить время и что-то сделать, если интервал времени между 11 вечера и 6:30 утра. Вот что я написал до сих пор, что не работает на следующий день:

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 &
 }

Что я делаю не так?


"который не работает на следующий день" ... если вы используете вчерашние отметки времени 23:00 и 06:30 и никогда не обновляете их ...
Muru

Ответы:


17

Если все, что вам нужно, это проверить, если HH:MMмежду 23:00 и 06:30, то не используйте метки времени Unix. Просто проверьте HH:MMзначения напрямую:

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 &
}

Ноты:

  • Время HH:MMбудет в лексикографическом порядке, поэтому вы можете напрямую сравнивать их как строки.
  • Избегайте использования -aили -oв[ ] , используйте ||и &&вместо этого.
  • Поскольку это bash, предпочитайте [[ ]]более [ ], это облегчает жизнь.

Можете ли вы проверить текущее время в определенном часовом поясе? Спасибо!
tommy.carstensen

1
@ tommy.carstensen вы можете dateиспользовать определенный часовой пояс, используя TZпеременную (например, TZ=Asia/Tokyo dateилиTZ=UTC date +%H:%M
Муру

Я бы дал вам дополнительный плюс только за то, что назвал метод fireup ()
jbrahy

@jbrahy, это была идея ОП (это в вопросе)
Муру

5

Если вы хотите быть более точным в отношении времени, которое вы хотите сопоставить, вы можете использовать caseутверждение. Вот 24-часовой цикл с оператором case, который указывает, соответствует ли текущее время вашему диапазону:

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

Чтобы использовать его в вашем скрипте, просто замените переменные вызовом date:

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

Вы можете подумать о том, чтобы быть более дружественным к вашему ЦП и вычислять промежуток времени между (сейчас) и временем следующего запуска, и в sleepтечение этого промежутка времени.


Ух ты. Это очень неожиданное и отличное решение. Спасибо!
SinaOwolabi

1

Вы можете преобразовать время в секунды с начала «этого» дня, а затем проверить, что значение секунд больше 23*60*60(82800) или меньше 6*60*60+30*60(23400).

Чтобы получить секунды с начала «этого» дня, вы можете сделать:

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

И тест будет:

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

0

У меня похожая ситуация. Моя цель - найти решение, которое очень просто поддерживать не-юниксам.

Когда мой сервер Linux перезагружается, он запускает скрипт, который отправляет предупреждение. Но если это происходит как часть нашего «Окна обслуживания», которое определяется как между 23:00 субботы и 6:00 воскресенья, я не хочу отправлять страницу, потому что перезапуск в этом окне - «Хорошо» (исправления применены и т. Д.). Я проверил его, и он работает как задумано (насколько я могу судить).

Вот календарь для справки:

      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

Вот мой тестовый код:

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

Вот вывод

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

1
Поскольку это, кажется, пытается ответить на вопрос, я оставил его с некоторыми правками. Если вы действительно хотите, чтобы кто-то просмотрел ваш код, я бы предложил codereview.stackexchange.com
Джефф Шаллер

Спасибо, Джефф, да, я искал предложения. Я не знал о сайте codereview. Спасибо
Даниэль

0

В этом конкретном случае альтернативой, упрощающей тестирование, является добавление часа и тестирование один раз для менее чем 07:30

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

-2

Подсказка: ответ Муру выше работал для меня, но вместо || (трубы, "или"), я должен был использовать && ("и" оператор).

например: if [["$ currenttime"> "23:00"]] && [["$ currenttime" <"06:30"]]


2
Это не имеет никакого смысла. Что возможное значение CurrentTime является и больше «23:00» , а также меньше , чем «06:30»? Подсказка: их нет.
Скотт
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.