python 时间范围验证器

python time range validator

我在数据库中有 2 个参数:启动和停止。它们的值可以是 07:00-23:00 或 23:00-07:00 (07后开始,23后停止或23后开始,07后停止)

那个时候状态必须是0或者1,比方说是LED

如何创建不会在半夜搞砸的统一逻辑控制器after/before?

我糟糕的实现(不会工作)如下。事实上,我已经尝试了很多很多变体,但最终仍然是我现在所在的位置..

            if curtime >= vv_time_trig1 and curtime <= vv_time_trig2:
                logger.info("turning socket on")
                logger.debug("#1")

                #check current status
                #if current is 0
                #turn socket on
                if vvstatus == 0:
                    logger.debug("current status off, turning socket on")
                    GPIO.output(25, GPIO.HIGH)

                #check current status
                #if current is already 1
                #do nothing
                elif vvstatus == 1:
                    logger.info("skiping. already on")

                #unhandeled current status
                else:
                    logger.critical("unhandeled vvstatus!")
                    logger.critical("turning socket off")
                    GPIO.output(25, GPIO.LOW)

            #if current time is before start
            #turn off
            elif curtime <= vv_time_trig1 and curtime >= vv_time_trig2:
                logger.info("turning socket off")
                logger.debug("#2")

                #check current status
                #if current is 1
                #turn socket off
                if vvstatus == 1:
                    logger.debug("current status on, turning socket off")
                    GPIO.output(25, GPIO.LOW)

                #check current status
                #if current is already 0
                #do nothing
                elif vvstatus == 0:
                    logger.info("skiping. already off")

                #unhandeled current status
                else:
                    logger.critical("unhandeled vvstatus!")
                    logger.critical("turning socket off")
                    GPIO.output(25, GPIO.LOW)

            #if current time is after stop
            #turn off
            elif curtime >= vv_time_trig2:
                logger.info("turning socket off")
                logger.debug("#3")

                #check current status
                #if current is 1
                #turn socket off
                if vvstatus == 1:
                    logger.debug("current status: %s, turning socket off", vvstatus)
                    GPIO.output(25, GPIO.LOW)

                #check current status
                #if current is already 0
                #do nothing
                elif vvstatus == 0:
                    logger.info("skiping. already on")

                #unhandeled current status
                else:
                    logger.critical("unhandeled vvstatus!")
                    logger.critical("turning socket off")
                    GPIO.output(25, GPIO.LOW)

            #if current time is before stop
            #turn off
            elif curtime <= vv_time_trig2 and curtime <= vv_time_trig1:
                logger.info("turning socket on")
                logger.debug("#4")

                #check current status
                #if current is 0
                #turn socket on
                if vvstatus == 0:
                    logger.debug("current status off, turning socket on")
                    GPIO.output(25, GPIO.HIGH)

                #check current status
                #if current is already 1
                #do nothing
                elif vvstatus == 1:
                    logger.info("skiping. already on")

                #unhandeled current status
                else:
                    logger.critical("unhandeled vvstatus!")
                    logger.critical("turning socket off")
                    GPIO.output(25, GPIO.LOW)

更新版本。 确定当前相对于结束的时间位置。如果午夜过去,结束时间设置为明天

            n1 = datetime.now()
            startTrig = datetime(n1.year, n1.month, n1.day, 23, 00, 0)
            logger.debug("start: %s",startTrig)

            n = datetime.now()
            endTrig = datetime(n.year, n.month, n.day, 07, 00, 0)
            logger.debug("end: %s",endTrig)

            if startTrig > endTrig:
                logger.debug("start > stop")
                endTrig += timedelta(days=1)
                logger.debug("new stop trig: %s",endTrig)


            if datetime.now() < endTrig:

                if curStatus == 1:
                    logger.debug("socket %s already on. doing nothing.")

                elif curStatus == 0:
                    logger.debug("socket %s sould be on. flipping switch")
                    flipSocketStatus(bcmNo,bcmDir)

                else:
                    logger.critical("unhandeled socket %s current status %s",socName,curStatus)

                    if curStatus == 1:
                        logger.critical("shutting socket %s down",socName)
                        GPIO.output(bcmNo, GPIO.LOW)

                    elif curStatus == 0:
                        logger.warn("socket %s already off",socName)

                    else:
                        logger.critical("unhandeled current status for pin: %s",bcmNo)
                        logger.critical("forcing socket %s down",socName)
                        GPIO.output(bcmNo, GPIO.LOW)
            else:
                logger.critical("unhandeled start-stop rules")

更新:基于您的更新

这看起来好多了,我唯一感到困惑的是你的 if datetime.now() < endTrig 条件。

如果我仍然误解你,请纠正我,但你当前的条件看起来是这样的:

if now() is before endTrigger:
  - if status is 1, we are good, stay on
  - if status is 0, turn on
  - if status is anything else (but cant it only be 1 or 0?):
    * if status is 1 ... (but wait, we already checked for this above!)
    * if status is 0 ... (ditto, these two checks will never trigger)
    * otherwise, force off
if now() is after endTime:
  - some logging (shouldnt this be where we turn off?)

您提到状态必须为 0 或 1。基于此,我希望您的条件看起来像:

.
. [start/end setup stuff]
.
# If we haven't reached end time yet
if datetime.now() < endTrig:
    # If status is 1, we're already on
    if curStatus == 1:
        log('Already on')
    # If status isn't 1, it must be 0 and we should turn on
    else:
        log('Turn on')
        flipSwitchOn()

# If we have passed the end time
else:
    # If we're on, time to turn off
    if curStatus == 1:
        log('Turning off')
        flipSwitchOff()
    # If its not 1 it must be 0, we're off, stay off
    else:
        log('Already off')

有两种情况:当前时间在给定时间之间(顺时针)或在给定时间之外(想象时钟圈):

#!/usr/bin/env python
from datetime import datetime

def in_between(now, start, end):
    if start < end: # e.g., "07:00-23:00"
        return start <= now < end
    elif end < start: # e.g., "23:00-07:00"
        return start <= now or now < end
    else: # start == end
        return True # consider it 24 hour interval

now = datetime.now().time()
for date_range in ["07:00-23:00", "23:00-07:00"]:
    start, end = [datetime.strptime(s, "%H:%M").time()
                  for s in date_range.split("-")]
    not_ = '' if in_between(now, start, end) else 'not '
    print("{now:%H:%M} is {not_}in between {date_range}".format(**vars()))

输出

02:26 is not in between 07:00-23:00
02:26 is in between 23:00-07:00