如何使用Python的datetime模块确定当前时间是否在指定范围内?

74

怎样才能最好地判断当前时间是否在 10:30 AM4:30 PM 之间呢?

我能想到以下方法,但不确定是否正确:

from datetime import datetime
nw = datetime.now()
hrs = nw.hour;mins = nw.minute;secs = nw.second;
zero = timedelta(seconds = secs+mins*60+hrs*3600)
st = nw - zero # this take me to 0 hours. 
time1 = st + timedelta(seconds=10*3600+30*60) # this gives 10:30 AM
time2 = st + timedelta(seconds=16*3600+30*60)  # this gives 4:30 PM
if nw>= time1 or nw <= time2:
    print "yes, within the interval"

请告诉我这是否是正确的方法,是否有更好的写法?


timedelta() 允许您指定天数、小时和分钟,因此您不必进行计算,代码更易读。 - C2H5OH
9个回答

127

我的原始答案非常专注于所提出的问题,并没有考虑跨越午夜时间范围的情况。由于这仍然是6年后被接受的答案,我已经结合了@rouble的答案来支持午夜时间。

from datetime import datetime, time

def is_time_between(begin_time, end_time, check_time=None):
    # If check time is not given, default to current UTC time
    check_time = check_time or datetime.utcnow().time()
    if begin_time < end_time:
        return check_time >= begin_time and check_time <= end_time
    else: # crosses midnight
        return check_time >= begin_time or check_time <= end_time

# Original test case from OP
is_time_between(time(10,30), time(16,30))

# Test case when range crosses midnight
is_time_between(time(22,0), time(4,00))

我仍然坚持我的原始评论,即大多数逻辑应用可能更适合使用 datetime 对象,其中跨越午夜反映为日期更改。

25
也应该适用于:if time(10,30) <= now.time() <= time(16,30): - Rik Poggi
7
如果您想检查一个时间是否在晚上10点到凌晨4点之间,该怎么办呢? :-) - 2arrs2ells
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Joe Holloway
3
@rouble的解决方法更为通用。这种解决方案只在start_time < end_time的情况下有效,而如果你的时间段开始于前一天的午夜之前,则该情况并不成立。(例如,晚上11点开始,并在早上5点结束,此时11PM > 5AM)。 - Alain1405
1
@JoeHolloway,我遇到了一个问题,例如:我在Django中有一个模型,其中包含from_time和to_time。考虑这样一个情况,已经存在一个from_time为6:00 am和end_time为10:00 am的条目。现在,如果有人尝试创建start_time = 8:00am和end_time = 9:00 am的条目,它应该抛出错误。你能帮我解决一下吗?https://stackoverflow.com/questions/61522909/creation-of-slots-at-regular-intervals - Timshrok
显示剩余8条评论

68

上述被接受的解决方案无法处理过夜时间,而这个可以:

import datetime as dt  
def isNowInTimePeriod(startTime, endTime, nowTime): 
    if startTime < endTime: 
        return nowTime >= startTime and nowTime <= endTime 
    else: 
        #Over midnight: 
        return nowTime >= startTime or nowTime <= endTime 

#normal example: 
isNowInTimePeriod(dt.time(13,45), dt.time(21,30), dt.datetime.now().time())

#over midnight example: 
isNowInTimePeriod(dt.time(20,30), dt.time(1,30), dt.datetime.now().time())

5
好的解决方案。请注意,startTime、endTime 和 nowTime 都是时间对象,你可以使用 datetime.time() 访问 datetime 对象的时间部分。 - Braza
3
大家怎么都忽略了这个! - Carson Holzheimer
@rouble 如果开始时间是早上7点,结束时间也是早上7点,而当前时间是早上5点,则它无法正常工作。它会返回True而不是False。 - Mirza715
Python代码在小版本更新中发展得非常快,以至于一年前运行良好的python3代码现在已经无法正常工作,而且需要数年时间才能将120多个最受欢迎的答案移到它们应该在的页面底部(因为它们已经过时和失效)。 - Eric Leschinski

15

这里是@rouble答案的小例子:

from datetime import datetime

def isNowInTimePeriod(startTime, endTime, nowTime):
    if startTime < endTime:
        return nowTime >= startTime and nowTime <= endTime
    else: #Over midnight
        return nowTime >= startTime or nowTime <= endTime


timeStart = '3:00PM'
timeEnd = '11:00AM'
timeNow = '2:59AM'
timeEnd = datetime.strptime(timeEnd, "%I:%M%p")
timeStart = datetime.strptime(timeStart, "%I:%M%p")
timeNow = datetime.strptime(timeNow, "%I:%M%p")

print(isNowInTimePeriod(timeStart, timeEnd, timeNow))

8

我想说的是,这对我来说很管用而且很简单

while True:
    now = datetime.now()
    current_time = now.strftime("%H:%M:%S")
    start = '19:19:00'
    end = '19:19:20'
    if current_time > start and current_time < end:
        print('in')
        print(current_time)
        tempo.sleep(1)
    else:
        print('out')
        print(current_time)

1

我有一个类似的需求,希望在每个工作日上午9点到下午3:30之间运行某个特定的任务。

def somefunction():
    cdate = datetime.datetime.strftime(datetime.datetime.now(), "%d-%m-%Y")
    if (0 <= time.localtime().tm_wday <= 4) and (datetime.datetime.strptime(cdate + " 09:00:00", "%d-%m-%Y %H:%M:%S") <= datetime.datetime.now() <= datetime.datetime.strptime(cdate + " 15:30:00", "%d-%m-%Y %H:%M:%S")):
         << do something >>

解释:

cdate变量以字符串格式获取当前日期。

该条件检查当前工作日是否为>=0(星期一)且<=4(星期五)。它还检查当前时间是否在今天的日期上>=9:00 AM,并且当前时间是否<=今天日期上的15:30。


1
一种可能比所选答案更接近 OP 请求的解决方案。它使用 datetime 而不是 time 作为检查对象。它还使用持续时间而不是时间来指定间隔的结束。
from datetime import datetime, time, timedelta

def is_date_within(begin_time, span_time, check_date=None):
    """                                                                                        
    Return True if given check_date is within the interval begining                            
    at begin_time with a duration of span_time.                                                
                                                                                               
    Args:                                                                                      
       - begin_time: datetime.time object                                                      
       - span_time: datetime.timedelta object                                                  
       - check_date: datetime.datetime object.                                                 
           If None, default to current UTC date                                                
    """
    check_date = check_date or datetime.utcnow()
    if check_date.time() >= begin_time:
        begin_date = check_date.combine(check_date.date(), begin_time)
    else:
        begin_date = check_date.combine(check_date.date() - timedelta(days=1),
                                        begin_time)
    return begin_date <= check_date <= begin_date + span_time

test_date = datetime(2020, 6, 22, 11, 31)
assert(is_date_within(time(10,30), timedelta(hours=4), test_date) == True)
assert(is_date_within(time(10,30), timedelta(hours=1), test_date) == False)

# Span midnight                                                                                
assert(is_date_within(time(23,30), timedelta(hours=13), test_date) == True)
assert(is_date_within(time(23,30), timedelta(hours=1), test_date) == False)

0

请查看 py-time-between 包:https://pypi.org/project/py-time-between/

测试用例:

from datetime import time
from timebetween import is_time_between


def test_is_time_between():
    t, s, e = time(0), time(0), time(0)
    assert is_time_between(t, s, e)

    t, s, e = time(0, 0, 0, 1), time(0), time(0, 0, 0, 2)
    assert is_time_between(t, s, e)

    t, s, e = time(0, 0, 0, 1), time(0, 0, 0, 1), time(0, 0, 0, 2)
    assert is_time_between(t, s, e)

    t, s, e = time(0, 0, 0, 2), time(0, 0, 0, 1), time(0, 0, 0, 2)
    assert is_time_between(t, s, e)

    t, s, e = time(0, 0, 1), time(23, 59, 59), time(0, 0, 2)
    assert is_time_between(t, s, e)

    t, s, e = time(12, 0, 0), time(23, 59, 59), time(0, 0, 0)
    assert is_time_between(t, s, e)

    t, s, e = time(23, 59, 57), time(23, 59, 59), time(23, 59, 57)
    assert is_time_between(t, s, e)

    t, s, e = time(23, 59, 58), time(23, 59, 59), time(23, 59, 57)
    assert not is_time_between(t, s, e)

    t, s, e = time(22), time(22), time(5, 59, 59)
    assert is_time_between(t, s, e)

0

可以进一步简化:

def isNowInTimePeriod(startTime, endTime, nowTime):
    if startTime < endTime:
        return startTime <= nowTime <= endTime
    else: #Over midnight
        return nowTime >= startTime or nowTime <= endTime

-1

这是我在Python中的做法

import datetime    
e = datetime.datetime.now()    
current_time = (e.strftime("%I:%M:%S %p"))
if current_time < '04:30:00 PM' or current_time > '9:30 AM':
    print(current_time)

2
这个答案是错误的。它只是进行了一个字符串比较,而且不起作用。 - Hound

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接