python - 循环Python脚本如何检测当前时间是否在某个小时:minute time range?

标签 python loops datetime

我正在尝试编写一个小函数,连续循环的脚本可以调用该函数来查看当前时间是否在特定的每日时间范围内。例如,脚本可能设置为每天从早上 09:00 运行到晚上 17:00,或者可能设置为从晚上 19​​:00 运行到早上 07:00。

我已经开始编写这样一个函数,但问题是当进入新的一天时事情会变得疯狂。因此,如果脚本被告知从 19:00 运行到 07:00,那么在 00:00 时它会变得困惑并停止等待新一天的 19:00 再次启动。

解决这个问题的好方法是什么?我很高兴脚本假设开始时间是在设置运行后的 future 某个时间。

我觉得该函数需要跟踪时间窗口的边缘是开始边缘还是停止边缘,但我不知道如何做到这一点。

#!/usr/bin/env python

"""
################################################################################
#                                                                              #
# cool timin' yea                                                              #
#                                                                              #
################################################################################

usage:
    program [options]

options:
    -h, --help         display help message
    --version          display version and exit
    --dayruntime=TEXT  HHMM--HHMM [default: 1900--0700]
"""

import datetime
import docopt
import time

def main(options):

    day_run_time = options["--dayruntime"]

    while True:

        if in_daily_time_range(time_range = day_run_time):

            print("ok let's do this thing")

            # complex deep learning shit

        else:

            print("i'll wait till it's ma time fam")

            # doin' some other things while chillin'

        time.sleep(5)

def in_daily_time_range(
    time_range = None, # string "HHMM--HHMM" e.g. "1700--1000"
    time_start = None, # string "HHMM"       e.g. "1700"
    time_stop  = None  # string "HHMM"       e.g. "1000"
    ):

    if time_range is not None:
        time_start = time_range.split("--")[0]
        time_stop  = time_range.split("--")[1]

    time_start_datetime = datetime.datetime.combine(
        datetime.datetime.now().date(),
        datetime.datetime.strptime(
            time_start,
            "%H%M"
        ).time()
    )
    time_stop_datetime = datetime.datetime.combine(
        datetime.datetime.now().date(),
        datetime.datetime.strptime(
            time_stop,
            "%H%M"
        ).time()
    )
    if time_stop_datetime < time_start_datetime:
        time_stop_datetime =\
            time_stop_datetime + datetime.timedelta(hours = 24)

    if time_start_datetime      <=\
        datetime.datetime.now() <=\
        time_stop_datetime:
        return True
    else:
        return False

if __name__ == "__main__":
    options = docopt.docopt(__doc__)
    if options["--version"]:
        print(version)
        exit()
    main(options)

最佳答案

这是我在评论中链接的答案中的 in_angle_interval 函数,经过修改以使用分钟,因为您的代码使用该分辨率。 in_time_interval 函数本身非常简单,但我编写了一些其他函数以使其更方便使用和测试。下面的代码还有一个简单的 now_in_months 函数,因此您可以轻松测试当前时间是否落在指定的时间间隔内;我的测试代码中未使用该函数。

from datetime import datetime

def hhmm_to_minutes(s):
    h, m = s[:2], s[2:]
    return 60 * int(h) + int(m)

def minutes_to_hhmm(minutes):
    return hour_min_to_hhmm(*divmod(minutes, 60))

def hour_min_to_hhmm(h, m):
    return '{:02d}{:02d}'.format(h, m)

def now_in_minutes():
    now = datetime.now()
    return 60 * now.hour + now.minute

# Test if x falls within the the time interval from a to b, inclusive
# All times are given in minutes since midnight.
minutes_per_day = 1440
def in_time_interval(x, a, b):
    return (x - a) % minutes_per_day <= (b - a) % minutes_per_day

# Find which times fall in the interval t0 - t1, inclusive.
# Test times start at 0000 and increment by delta minutes
def in_test(t0, t1, delta=10):
    print('{} - {}: '.format(t0, t1), end='')
    t0 = hhmm_to_minutes(t0)
    t1 = hhmm_to_minutes(t1)

    passed = [minutes_to_hhmm(nowmin)
        for nowmin in range(0, minutes_per_day, delta)
            if in_time_interval(nowmin, t0, t1)
    ]
    print(', '.join(passed))

# Find which times DON'T fall in the interval t0 - t1, inclusive.
# Test times start at 0000 and increment by delta minutes
def out_test(t0, t1, delta=10):
    print('{} - {}: '.format(t0, t1), end='')
    t0 = hhmm_to_minutes(t0)
    t1 = hhmm_to_minutes(t1)

    failed = [minutes_to_hhmm(nowmin)
        for nowmin in range(0, minutes_per_day, delta)
            if not in_time_interval(nowmin, t0, t1)
    ]
    print(', '.join(failed))

m = 30
print('In tests. The printed times are in the interval at the start of the line')
for h in range(24):
    t0 = hour_min_to_hhmm(h, m)
    t1 = hour_min_to_hhmm((h + 2) % 24, m)
    in_test(t0, t1)

print('\n' + '- ' * 20 + '\n')
print('Out tests. The printed times are outside the interval at the start of the line')
for h in range(24):
    t0 = hour_min_to_hhmm(h, m)
    t1 = hour_min_to_hhmm((h + 2) % 24, m)
    out_test(t1, t0)

输出

In tests. The printed times are in the interval at the start of the line
0030 - 0230: 0030, 0040, 0050, 0100, 0110, 0120, 0130, 0140, 0150, 0200, 0210, 0220, 0230
0130 - 0330: 0130, 0140, 0150, 0200, 0210, 0220, 0230, 0240, 0250, 0300, 0310, 0320, 0330
0230 - 0430: 0230, 0240, 0250, 0300, 0310, 0320, 0330, 0340, 0350, 0400, 0410, 0420, 0430
0330 - 0530: 0330, 0340, 0350, 0400, 0410, 0420, 0430, 0440, 0450, 0500, 0510, 0520, 0530
0430 - 0630: 0430, 0440, 0450, 0500, 0510, 0520, 0530, 0540, 0550, 0600, 0610, 0620, 0630
0530 - 0730: 0530, 0540, 0550, 0600, 0610, 0620, 0630, 0640, 0650, 0700, 0710, 0720, 0730
0630 - 0830: 0630, 0640, 0650, 0700, 0710, 0720, 0730, 0740, 0750, 0800, 0810, 0820, 0830
0730 - 0930: 0730, 0740, 0750, 0800, 0810, 0820, 0830, 0840, 0850, 0900, 0910, 0920, 0930
0830 - 1030: 0830, 0840, 0850, 0900, 0910, 0920, 0930, 0940, 0950, 1000, 1010, 1020, 1030
0930 - 1130: 0930, 0940, 0950, 1000, 1010, 1020, 1030, 1040, 1050, 1100, 1110, 1120, 1130
1030 - 1230: 1030, 1040, 1050, 1100, 1110, 1120, 1130, 1140, 1150, 1200, 1210, 1220, 1230
1130 - 1330: 1130, 1140, 1150, 1200, 1210, 1220, 1230, 1240, 1250, 1300, 1310, 1320, 1330
1230 - 1430: 1230, 1240, 1250, 1300, 1310, 1320, 1330, 1340, 1350, 1400, 1410, 1420, 1430
1330 - 1530: 1330, 1340, 1350, 1400, 1410, 1420, 1430, 1440, 1450, 1500, 1510, 1520, 1530
1430 - 1630: 1430, 1440, 1450, 1500, 1510, 1520, 1530, 1540, 1550, 1600, 1610, 1620, 1630
1530 - 1730: 1530, 1540, 1550, 1600, 1610, 1620, 1630, 1640, 1650, 1700, 1710, 1720, 1730
1630 - 1830: 1630, 1640, 1650, 1700, 1710, 1720, 1730, 1740, 1750, 1800, 1810, 1820, 1830
1730 - 1930: 1730, 1740, 1750, 1800, 1810, 1820, 1830, 1840, 1850, 1900, 1910, 1920, 1930
1830 - 2030: 1830, 1840, 1850, 1900, 1910, 1920, 1930, 1940, 1950, 2000, 2010, 2020, 2030
1930 - 2130: 1930, 1940, 1950, 2000, 2010, 2020, 2030, 2040, 2050, 2100, 2110, 2120, 2130
2030 - 2230: 2030, 2040, 2050, 2100, 2110, 2120, 2130, 2140, 2150, 2200, 2210, 2220, 2230
2130 - 2330: 2130, 2140, 2150, 2200, 2210, 2220, 2230, 2240, 2250, 2300, 2310, 2320, 2330
2230 - 0030: 0000, 0010, 0020, 0030, 2230, 2240, 2250, 2300, 2310, 2320, 2330, 2340, 2350
2330 - 0130: 0000, 0010, 0020, 0030, 0040, 0050, 0100, 0110, 0120, 0130, 2330, 2340, 2350

- - - - - - - - - - - - - - - - - - - - 

Out tests. The printed times are outside the interval at the start of the line
0230 - 0030: 0040, 0050, 0100, 0110, 0120, 0130, 0140, 0150, 0200, 0210, 0220
0330 - 0130: 0140, 0150, 0200, 0210, 0220, 0230, 0240, 0250, 0300, 0310, 0320
0430 - 0230: 0240, 0250, 0300, 0310, 0320, 0330, 0340, 0350, 0400, 0410, 0420
0530 - 0330: 0340, 0350, 0400, 0410, 0420, 0430, 0440, 0450, 0500, 0510, 0520
0630 - 0430: 0440, 0450, 0500, 0510, 0520, 0530, 0540, 0550, 0600, 0610, 0620
0730 - 0530: 0540, 0550, 0600, 0610, 0620, 0630, 0640, 0650, 0700, 0710, 0720
0830 - 0630: 0640, 0650, 0700, 0710, 0720, 0730, 0740, 0750, 0800, 0810, 0820
0930 - 0730: 0740, 0750, 0800, 0810, 0820, 0830, 0840, 0850, 0900, 0910, 0920
1030 - 0830: 0840, 0850, 0900, 0910, 0920, 0930, 0940, 0950, 1000, 1010, 1020
1130 - 0930: 0940, 0950, 1000, 1010, 1020, 1030, 1040, 1050, 1100, 1110, 1120
1230 - 1030: 1040, 1050, 1100, 1110, 1120, 1130, 1140, 1150, 1200, 1210, 1220
1330 - 1130: 1140, 1150, 1200, 1210, 1220, 1230, 1240, 1250, 1300, 1310, 1320
1430 - 1230: 1240, 1250, 1300, 1310, 1320, 1330, 1340, 1350, 1400, 1410, 1420
1530 - 1330: 1340, 1350, 1400, 1410, 1420, 1430, 1440, 1450, 1500, 1510, 1520
1630 - 1430: 1440, 1450, 1500, 1510, 1520, 1530, 1540, 1550, 1600, 1610, 1620
1730 - 1530: 1540, 1550, 1600, 1610, 1620, 1630, 1640, 1650, 1700, 1710, 1720
1830 - 1630: 1640, 1650, 1700, 1710, 1720, 1730, 1740, 1750, 1800, 1810, 1820
1930 - 1730: 1740, 1750, 1800, 1810, 1820, 1830, 1840, 1850, 1900, 1910, 1920
2030 - 1830: 1840, 1850, 1900, 1910, 1920, 1930, 1940, 1950, 2000, 2010, 2020
2130 - 1930: 1940, 1950, 2000, 2010, 2020, 2030, 2040, 2050, 2100, 2110, 2120
2230 - 2030: 2040, 2050, 2100, 2110, 2120, 2130, 2140, 2150, 2200, 2210, 2220
2330 - 2130: 2140, 2150, 2200, 2210, 2220, 2230, 2240, 2250, 2300, 2310, 2320
0030 - 2230: 0000, 0010, 0020, 2240, 2250, 2300, 2310, 2320, 2330, 2340, 2350
0130 - 2330: 0000, 0010, 0020, 0030, 0040, 0050, 0100, 0110, 0120, 2340, 2350
<小时/>

虽然我的 now_in_months 函数返回本地时间,但如果您居住在使用夏令时的地区,我强烈建议您认真考虑使用 UTC 工作。如果您使用本地时间并且以包含 DST 时间更改的时间间隔调用 in_time_interval,则可能会发生不好的事情。

关于python - 循环Python脚本如何检测当前时间是否在某个小时:minute time range?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42569700/

相关文章:

java - 使用 switch 语句跳出 while 循环

c# - 如何设计一个在编译时以未知顺序迭代多个列表的算法?

r - 我如何绘制时间 (HH :MM:SS) in X axis in R

java - 德国语言环境的日期时间格式不一致

python - 如果满足条件则终止 Scrapy

python - 在Python中调用外部命令

python - Native Client (NaCl) 程序可以用 C 或 C++ 以外的语言编写吗?

NDB Model.query() 上的 Python TypeError

ios - 有没有办法把它变成一个 for 循环或改进它?

c# - 如何在不使用代码的情况下格式化日期 - 格式化字符串问题