Python – определение того, находится ли сейчас время между двумя временами

Я пытаюсь найти самый чистый/самый питонический способ оценки, находится ли «сейчас» между двумя временами; Однако; время начала/окончания может или не может пересекать границу дня, например (просто используя простые примеры):

onhour=23
onmin=30
offhour=4
offmin=15
timenow = datetime.datetime.now().time()

Выполнение прямого сценария if START < NOW < END для этого не сработает!

В настоящее время у меня есть некоторый код, который оценивает, является ли он в настоящее время «NightTime», который выглядит так:

def check_time(timenow, onhour, onmin, offhour, offmin, verbose):
    now = datetime.datetime.now()
    now_time = now.time()
    # If we're actually scheduling at night:
    if int(offhour) < int(onhour):
        # Check to see if we're in daylight times (ie. off schedule)
        if datetime.time(int(offhour),int(offmin)) <= now_time <= datetime.time(int(onhour),int(onmin)):
            if verbose == True:
                print("Day Time detected.")
            return False
        else:
            if verbose == True:
                print("Night Time detected.")
            return True
    else:
        if datetime.time(int(onhour),int(onmin)) <= now_time <= datetime.time(int(offhour),int(offmin)):
            if verbose == True:
                print("Night Time detected.")
            return True
        else:
            if verbose == True:
                print("Day Time detected.")
            return False

Извиняюсь, если название не звучит как что-то новое, но просмотрев несколько существующих ответов на аналогичные проблемы, такие как:

Я заметил, что они, похоже, не учитывают случаи, когда время начала и окончания происходит за пределами дня.

В добавок к этому; любые идеи, связанные с добавлением планирования на основе дня, также будут весьма полезны! т.е. "для пн-пт включение в 23:00, выключение в 04:00" - но управление включением и выключением в течение дня в обе стороны (иначе что-то будет включено в пятницу, но не будет выключено в субботу -- и тем не менее, включая субботу, это означает, что он снова включается в 23!...)

Я решил сделать простое «Включить в X, спать на Y», чтобы обойти это... но если скрипт запускается во время цикла «Вкл», он не будет инициирован до следующего запуска. .Но вроде как самый простой вариант! :)

Я надеюсь, что есть какой-то классный модуль, который делает все это... :D

Совместимость Python 2.7 - 3.2 тоже очень важна для меня!


person dalgibbard    schedule 11.12.2013    source источник
comment
Как узнать, к какому дню относится ваше рабочее и нерабочее время? Например, если сейчас 11 декабря, как вы можете решить в своем примере, будет ли интервал с 10 декабря 23:30 до 11 декабря 4:15 ИЛИ с 11 декабря 23:30 до 12 декабря 4:15?   -  person leeladam    schedule 11.12.2013
comment
Проблема, кажется, в том, что у вас есть только часы и минуты, у вас нет дат. Если у вас три даты, то date1 <= date2 <= date3 работает нормально.   -  person Simeon Visser    schedule 11.12.2013
comment
Вы изучили Расширенный планировщик Python?   -  person jonrsharpe    schedule 11.12.2013
comment
Сначала напишите тестовые примеры для всех вариантов, которые вы хотите...   -  person John La Rooy    schedule 11.12.2013
comment
@SimeonVisser - я согласен, есть определенные возможности для улучшения; но я не мог понять, как оценить, если, скажем, offhour следует назначить сегодня или завтра... Я думаю, что оценки, если time.now() больше, чем offhour или подобное, вероятно, будет достаточно...   -  person dalgibbard    schedule 11.12.2013
comment
@jonrsharpe - я быстро просмотрел Advanced Python Scheduler, и он кажется хорошим для запуска заданий, но я не нашел много способов определения остановки на основе даты/времени (просто продолжительность эквивалентна)? Может быть, я пропустил пример в документах?   -  person dalgibbard    schedule 11.12.2013


Ответы (4)


Ваш код немного хаотичен. Я бы сделал что-то вроде этого:

import datetime

DAY, NIGHT = 1, 2
def check_time(time_to_check, on_time, off_time):
    if on_time > off_time:
        if time_to_check > on_time or time_to_check < off_time:
            return NIGHT, True
    elif on_time < off_time:
        if time_to_check > on_time and time_to_check < off_time:
            return DAY, True
    elif time_to_check == on_time:
        return None, True
    return None, False


on_time = datetime.time(23,30)
off_time = datetime.time(4,15)
timenow = datetime.datetime.now().time()
current_time = datetime.datetime.now().time()

when, matching = check_time(current_time, on_time, off_time)

if matching:
    if when == NIGHT:
        print("Night Time detected.")
    elif when == DAY:
        print("Day Time detected.")
person smeso    schedule 11.12.2013
comment
Можно ли упростить это, используя ›= для операторов if time_to_check, тем самым устраняя необходимость в последнем elif? - person dalgibbard; 11.12.2013
comment
Последний elif предназначен для управления случаем, когда on_time и off_time точно совпадают (и time_to_check находится в этом интервале). В этом случае вы не можете сказать, является ли это ночным или дневным интервалом, если вы не выберете какой-то фиксированный интервал для ночи и дня на основе времени заката/восхода солнца в интересующей вас географической области. - person smeso; 11.12.2013

Чтобы узнать, находится ли заданное время (без даты) между заданным временем начала и окончания (конец не включен):

def in_between(now, start, end):
    if start <= end:
        return start <= now < end
    else: # over midnight e.g., 23:30-04:15
        return start <= now or now < end

Пример:

from datetime import datetime, time

print("night" if in_between(datetime.now().time(), time(23), time(4)) else "day")
person jfs    schedule 12.11.2015
comment
что, если начало в 2 часа ночи, окончание в 2 часа ночи, а сейчас 4 часа ночи, не будет ли это ошибкой? - не должен ли первый если читать, если начало ‹ конец? - person rouble; 08.08.2016
comment
@rouble [2AM, 2AM) — это пустой диапазон (конец не включен — как явно сказано в ответе), т. е. код ведет себя так, как задокументировано. При желании; требования и могут быть изменены. Хотя есть и преимущества, во многих случаях указывать диапазон без правой границы (поэтому range(2,2) тоже пусто в Python). - person jfs; 08.08.2016
comment
Я вижу вашу точку зрения. И ваш ответ - лучший ответ (отсюда и плюс). Я действительно думаю, что когда мы пытаемся выяснить, находится ли время в пределах периода времени дня, мы должны разрешить полный 24-часовой диапазон времени. - person rouble; 10.08.2016

def is_hour_between(start, end, now):
    is_between = False

    is_between |= start <= now <= end
    is_between |= end < start and (start <= now or now <= end)

    return is_between

тест с:

assert is_hour_between(6, 10, 6)
assert not is_hour_between(6, 10, 4)
assert is_hour_between(17, 20, 17)
assert not is_hour_between(17, 20, 16)
person Kevron Rees    schedule 04.04.2018

Сообщение Кеврона действительно помогло решить мою проблему. Мое требование было немного другим, когда я передавал строки. Моя версия выглядит так:

def is_hour_between(start, end):
    # Time Now
    now = datetime.datetime.now().time()
    # Format the datetime string
    time_format = '%Y-%m-%d %H:%M:%S'
    # Convert the start and end datetime to just time
    start = datetime.datetime.strptime(start, time_format).time()
    end = datetime.datetime.strptime(end, time_format).time()

    is_between = False
    is_between |= start <= now <= end
    is_between |= end <= start and (start <= now or now <= end)

    return is_between

check = is_hour_between('2021-04-07 08:30:00', '2021-04-07 04:29:00') #spans to the next day
print("time check", check) # result = True

Надеюсь, это поможет кому-то, кто борется со строковыми временами.

person jAC    schedule 22.02.2021