【问题标题】:How do I determine if current time is within a specified range using Python's datetime module?如何使用 Python 的 datetime 模块确定当前时间是否在指定范围内?
【发布时间】:2012-04-20 08:27:58
【问题描述】:

查看当前时间是否介于 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() 也允许您指定天数、小时数和分钟数,因此您不必计算它并且代码更具可读性。

标签: python python-datetime


【解决方案1】:

我最初的答案非常专注于提出的问题,并且不适应跨越午夜的时间范围。由于 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 对象,其中跨越午夜无论如何都会反映为日期更改。

【讨论】:

  • 还应该使用:if time(10,30) &lt;= now.time() &lt;= time(16,30):
  • 扩展:我如何对日期进行这些比较。假设今天是 3 月 12 日。那么如何检查给定日期是否是 3 月 12 日?
  • 但是如果您要检查时间是否在晚上 10 点到凌晨 4 点之间呢? :-)
  • @rouble 的解决方案更通用。此解决方案仅适用于start_time &lt; end_time,如果您的经期在前一天的午夜之前开始,则不是这样。 (例如,夜晚从晚上 11 点开始,到凌晨 5 点结束,并且 `11PM > 5AM)
  • @JoeHolloway,我遇到了一个问题,例如:我在 Django 中有一个模型,它有 from_time 和 to_time。考虑一个已经存在 from_time:6:00 am 和 end_time:10:00 am 的条目的情况。现在,如果有人尝试为 start_time = 8:00 am 和 end_time = 9:00 am 创建。它应该抛出错误。你能帮我吗? stackoverflow.com/questions/61522909/…
【解决方案2】:

上述接受的解决方案不适用于通宵时间,但可以:

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())

【讨论】:

  • 很好的解决方案。注意 startTime、endTime 和 nowTime 是时间对象,您可以通过datetime.time() 访问日期时间对象的时间部分
  • 大家怎么都错过了这个!
  • @rouble 如果 start_time 是 7AM 并且 end_time 是 7AM 并且当前时间是 5 AM 则不起作用。它给出了 True 而不是 False
  • Python 代码在次要版本更新中发展得如此之快,以至于一年前运行良好的 python3 代码现在不再运行,并且需要数年时间才能将 120 多个最受好评的答案带到底部它所属的页面(折旧和损坏)
【解决方案3】:

这是@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))

【讨论】:

    【解决方案4】:

    我的 2 美分,它对我有用,而且很简单

    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)
    

    【讨论】:

      【解决方案5】:

      查看 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)
      

      【讨论】:

        【解决方案6】:

        可以进一步简化:

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

        【讨论】:

          【解决方案7】:

          我有一个类似的要求,我希望某个任务在每个工作日的上午 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(星期一)和 datetime 格式的当前时间是否 >= 9:00 AM 在今天的日期,当前时间是否

          【讨论】:

            【解决方案8】:

            可能比所选答案更接近 OP 要求的解决方案。 它使用日期时间而不是时间作为要检查的对象。 它还使用持续时间而不是时间来指定间隔的结束。

            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)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-09-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-11-22
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多